diff options
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg')
46 files changed, 19462 insertions, 0 deletions
diff --git a/kxsldbg/kxsldbgpart/libxsldbg/Makefile.am b/kxsldbg/kxsldbgpart/libxsldbg/Makefile.am new file mode 100644 index 00000000..aaea2e53 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/Makefile.am @@ -0,0 +1,12 @@ +noinst_LTLIBRARIES = libxsldbg.la + +libxsldbg_la_METASOURCES = AUTO + +libxsldbg_la_SOURCES = allmoc.cpp xsldbgthread.cpp xsldbg.cpp xsldbgmsg.cpp variable_cmds.cpp utils.cpp trace_cmds.cpp template_cmds.cpp search_cmds.cpp search.cpp param_cmds.cpp os_cmds.cpp options_unix.cpp options.cpp option_cmds.cpp nodeview_cmds.cpp help_unix.cpp files_unix.cpp files.cpp file_cmds.cpp debugXSL.cpp debug.cpp callstack.cpp breakpoint_cmds.cpp breakpoint.cpp arraylist.cpp + +libxsldbg_la_LIBADD = $(LIBXSLT_LIBS) +libxsldbg_la_LDFLAGS = $(all_libraries) + +AM_CPPFLAGS = -DDOCS_PATH=\"$(DOCS_PATH)\" -I.. $(LIBXSLT_CFLAGS) $(all_includes) + +KDE_OPTIONS= nofinal diff --git a/kxsldbg/kxsldbgpart/libxsldbg/allmoc.cpp b/kxsldbg/kxsldbgpart/libxsldbg/allmoc.cpp new file mode 100644 index 00000000..41decae4 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/allmoc.cpp @@ -0,0 +1,2 @@ +#include "../xsldbgdebugger.h" +#include "qtnotifier2.h" diff --git a/kxsldbg/kxsldbgpart/libxsldbg/arraylist.cpp b/kxsldbg/kxsldbgpart/libxsldbg/arraylist.cpp new file mode 100644 index 00000000..a9de14fe --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/arraylist.cpp @@ -0,0 +1,240 @@ + +/*************************************************************************** + arraylist.c - define array implementation of a list + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "arraylist.h" +#include <libxslt/xsltutils.h> + +#ifndef NULL +#define NULL 0 +#endif + +/** + * arrayListNew: + * @initialSize: The initial size of list + * @deleteFunction: The function to call to free items in the list + * + * Create a new list with a size of @initialSize + * + * Returns Non-null on success, + * NULL otherwise + */ +arrayListPtr +arrayListNew(int initialSize, freeItemFunc deleteFunction) +{ + arrayListPtr list = NULL; + + if (initialSize <= 0) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "arrayListNew invalid initialSize %d\n", + initialSize); +#endif + } else + list = (arrayListPtr) xmlMalloc(sizeof(arrayList)); + + if (list) { + list->data = (void **) xmlMalloc(sizeof(void *) * initialSize); + list->deleteFunction = deleteFunction; + list->count = 0; + list->size = initialSize; + } + + return list; +} + + +/** + * arrayListFree: + * @list: A valid list + * + * Free memory assocated with array list, if the array list + * has a valid deleteFunction then content with be freed with + * using that deleteFunction + */ +void +arrayListFree(arrayListPtr list) +{ + if (!list) + return; + + arrayListEmpty(list); + xmlFree(list->data); + xmlFree(list); +} + + +/** + * arrayListEmpty: + * @list: A valid list + * + * Empties the list of its content + * + * Returns 1 on success, + * 0 otherwise + */ +int +arrayListEmpty(arrayListPtr list) +{ + int index, result = 0; + + if (list) { + if (list->deleteFunction) { + for (index = 0; index < list->count; index++) { + if (list->data[index]) + (*list->deleteFunction) (list->data[index]); + } + result = 1; + list->count = 0; + } + } + return result; +} + + +/** + * arrayListSize: + * @list: A valid list + * + * Return The maximum number elements this list can contain + * + * Returns The maximum number elements this list can contain + */ +int +arrayListSize(arrayListPtr list) +{ + int result = 0; + + if (list) + result = list->size; + + return result; +} + + +/** + * arrayListCount: + * @list: A valid list + * + * Return the count of number items in list + * + * Returns The count of number items in list + */ +int +arrayListCount(arrayListPtr list) +{ + int result = 0; + + if (list) + result = list->count; + + return result; +} + + +/** + * arrayListAdd: + * @list: A valid list + * @item: A valid list + * + * Add @item to @list + * + * Returns 1 if able to add @item to end of @list, + * 0 otherwise + */ +int +arrayListAdd(arrayListPtr list, void *item) +{ + int result = 0; + + if (list && item) { + if (list->count + 1 > list->size) { + /* grow the size of data */ + void **temp; + int newSize, index; + + if (list->size < DOUBLE_SIZE_MAX_ITEM) + newSize = list->size * 2; + else + newSize = (int) (list->size * 1.5); + temp = (void **) xmlMalloc(sizeof(void *) * newSize); + for (index = 0; index < list->count; index++) { + temp[index] = list->data[index]; + } + xmlFree(list->data); + list->data = temp; + list->size = newSize; + } + list->data[list->count++] = item; + result = 1; + } + return result; +} + + +/** + * arrayListDelete: + * @list: A valid list + * @position: 0 =< @position < arrayListCount(@list) + * + * Delete item at position @position from @list + * + * Returns 1 if able to delete element in @list at position @position, + * 0 otherwise + */ +int +arrayListDelete(arrayListPtr list, int position) +{ + int result = 0, index; + + if (list && (list->count > 0) && (position >= 0) && + (position < list->count) && list->data[position]) { + if (list->deleteFunction) + (*list->deleteFunction) (list->data[position]); + + /* shuffle all elements upwards */ + for (index = position; index < (list->count - 1); index++) { + list->data[index] = list->data[index + 1]; + } + list->count--; + result = 1; + } + return result; +} + + + +/** + * arrayListGet: + * @list: A valid list + * @position: 0 =< @position < arrayListCount(@list) + * + * Get item at position @position from @list + * + * Returns Non-null if able to retrieve element in @list at position @position, + * NULL otherwise + */ +void * +arrayListGet(arrayListPtr list, int position) +{ + void *result = NULL; + + if (list && (position >= 0) && (position < list->count)) { + result = list->data[position]; + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/arraylist.h b/kxsldbg/kxsldbgpart/libxsldbg/arraylist.h new file mode 100644 index 00000000..81398459 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/arraylist.h @@ -0,0 +1,291 @@ + +/************************************************************************** + arraylist.h - declare the functions for + implementation of the array list + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + +#ifndef ARRAYLIST_H +#define ARRAYLIST_H + +#ifdef USE_KDE_DOCS + +/** + * Provide a fast easy to use array list. Support the basic functions of add + * delete, empty, count, free + * + * @short Array list support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef USE_GNOME_DOCS + +#else +#ifdef USE_KDE_DOCS + +#endif +#endif + + + typedef void (*freeItemFunc) (void *item); + /* A dynamic structure behave like a list */ + typedef struct _arrayList arrayList; + typedef arrayList *arrayListPtr; + struct _arrayList { + int size, count; + void **data; + freeItemFunc deleteFunction; + }; + +/* what size of the list do we stop automatic doubling of capacity + if array list size growth is needed */ +#define DOUBLE_SIZE_MAX_ITEM 10 + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListNew: + * @initialSize: The initial size of list + * @deleteFunction: The function to call to free items in the list + * + * Create a new list with a size of @initialSize + * + * Returns Non-null on success, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Create a new list with a size of @p initialSize + * + * @returns Non-null on success, + * NULL otherwise + * + * @param initial The initial size of list + * @param deleteFunction the Function to call to free items in the list + */ +#endif +#endif + arrayListPtr arrayListNew(int initialSize, + freeItemFunc deleteFunction); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListFree: + * @list: A valid list + * + * Free memory assocated with array list, if the array list + * has a valid deleteFunction then content with be freed with + * using that deleteFunction + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free memory assocated with array list, if the array list + * has a valid deleteFunction then content with be freed with + * using that deleteFunction + * + * @param list A valid list + */ +#endif +#endif + void arrayListFree(arrayListPtr list); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListEmpty: + * @list: A valid list + * + * Empties the list of its content + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Empties the list of its content + * + * @returns 1 on success, + * 0 otherwise + * + * @param list A valid list + */ +#endif +#endif + int arrayListEmpty(arrayListPtr list); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListSize: + * @list: A valid list + * + * Return The maximum number elements this list can contain + * + * Returns The maximum number elements this list can contain + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Return the maximum number elements this list can contain + * + * @returns The maximum number elements this list can contain + * + * @param list A valid list + */ +#endif +#endif + int arrayListSize(arrayListPtr list); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListCount: + * @list: A valid list + * + * Return the count of number items in list + * + * Returns The count of number items in list + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Return the count of number items in list + * @returns The count of number items in list + * + * @param list A valid list + */ +#endif +#endif + + int arrayListCount(arrayListPtr list); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListAdd: + * @list: A valid list + * @item:A valid item + * + * Add @item to @list + * + * Returns 1 if able to add @item to end of @list, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Add @p item to @p list + * + * @returns 1 if able to add @p item to end of @p list, + * 0 otherwise + * + * @param list A valid list + * @param item A valid item + */ +#endif +#endif + int arrayListAdd(arrayListPtr list, void *item); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListDelete: + * @list: A valid list + * @position: 0 =< @position < arrayListCount(@list) + * + * Delete item at position @position from @list + * + * Returns 1 if able to delete element in @list at position @position, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns 1 if able to delete element in @p list at position @p position, + * 0 otherwise + * + * @param list A valid list + * @param position 0 =< @p position < arrayListCount(@p list) + */ +#endif +#endif + int arrayListDelete(arrayListPtr list, int position); + + + +#ifdef USE_GNOME_DOCS + +/** + * arrayListGet: + * @list: A valid list + * @position: 0 =< @position < arrayListCount(@list) + * + * Get item at position @position from @list + * + * Returns Non-null if able to retrieve element in @list at position + * @position, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns Non-null if able to retrieve element in @p list at position + * @p position, + * NULL otherwise + * + * @param list A valid list + * @param position 0 =< @p position < arrayListCount(@p list) + */ +#endif +#endif + void *arrayListGet(arrayListPtr list, int position); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.cpp b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.cpp new file mode 100644 index 00000000..270ce82d --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.cpp @@ -0,0 +1,696 @@ + +/*************************************************************************** + 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; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.h b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.h new file mode 100644 index 00000000..83f2e712 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint.h @@ -0,0 +1,633 @@ + +/************************************************************************** + breakpoint.h - public functions for the + breakpoint API + ------------------- + begin : Fri Dec 7 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + + +#ifndef XSLBREAKPOINT_H +#define XSLBREAKPOINT_H + +#ifdef USE_KDE_DOCS + +/** + * Provide a basic break point support + * + * @short break point support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + +#ifndef BUILD_DOCS +#include <libxml/tree.h> +#include <libxml/xpath.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/xsltutils.h> + +#include "arraylist.h" +#endif /* BUILD_DOCS */ + +#ifdef __cplusplus +extern "C" { +#endif + + /* indicate that we are to toggle a breakpoint , used for enableBreakPoint */ +#define XSL_TOGGLE_BREAKPOINT -1 + + /* Define the types of status whilst debugging */ +#ifndef USE_KDOC + typedef enum { + DEBUG_NONE = 0, /* must start at zero!! */ + DEBUG_INIT, + DEBUG_STEP, + DEBUG_STEPUP, + DEBUG_STEPDOWN, + DEBUG_NEXT, + DEBUG_STOP, + DEBUG_CONT, + DEBUG_RUN, + DEBUG_RUN_RESTART, + DEBUG_QUIT, + DEBUG_TRACE, + DEBUG_WALK + } DebugStatusEnum; + + + typedef enum { + DEBUG_BREAK_SOURCE = 300, + DEBUG_BREAK_DATA + } BreakPointTypeEnum; + + +/*Indicate what type of variable to print out. + Is used by print_variable and searching functions */ + typedef enum { + DEBUG_GLOBAL_VAR = 200, /* pick a unique starting point */ + DEBUG_LOCAL_VAR, + DEBUG_ANY_VAR + } VariableTypeEnum; + +/*What type of flags can breakpoints have */ + typedef enum { + BREAKPOINT_ENABLED = 1, + BREAKPOINT_ORPHANED = 2, + BREAKPOINT_ALLFLAGS = 255 + } BreakPointFlags; + +/*What state of breakpoint validation can we be in */ + typedef enum { + BREAKPOINTS_ARE_VALID, + BREAKPOINTS_NEED_VALIDATION, + BREAKPOINTS_BEING_VALIDATED + } BreakPointValidationStates; +#else + /* keep kdoc happy */ + enum DebugStatusEnum { + DEBUG_NONE = 0, /* must start at zero!! */ + DEBUG_INIT, + DEBUG_STEP, + DEBUG_STEPUP, + DEBUG_STEPDOWN, + DEBUG_NEXT, + DEBUG_STOP, + DEBUG_CONT, + DEBUG_RUN, + DEBUG_RUN_RESTART, + DEBUG_QUIT, + DEBUG_TRACE, + DEBUG_WALK + }; + + + enum BreakPointTypeEnum { + DEBUG_BREAK_SOURCE = 300, + DEBUG_BREAK_DATA + }; + + +/*Indicate what type of variable to print out. + Is used by print_variable and searching functions */ + enum VariableTypeEnum { + DEBUG_GLOBAL_VAR = 200, /* pick a unique starting point */ + DEBUG_LOCAL_VAR, + DEBUG_ANY_VAR + } VariableTypeEnum; + +/*What type of flags can breakpoints have */ + enum BreakPointFlags { + BREAKPOINT_ENABLED = 1, + BREAKPOINT_ORPHANED = 2, + BREAKPOINT_ALLFLAGS = 255 + } BreakPointFlags; + +/*What state of breakpoint validation can we be in */ + enum BreakPointValidationStates { + BREAKPOINTS_ARE_VALID, + BREAKPOINTS_NEED_VALIDATION, + BREAKPOINTS_BEING_VALIDATED + } BreakPointValidationStates; +#endif + + /* The main structure for holding breakpoints */ + typedef struct _breakPoint breakPoint; + typedef breakPoint *breakPointPtr; + struct _breakPoint { + xmlChar *url; + long lineNo; + xmlChar *templateName, *modeName; + int flags; + BreakPointTypeEnum type; + int id; + }; + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointInit: + * + * Intialized the breakpoint module + * + * Returns 1 if breakpoint module haas been initialized properly and all + * memory required has been obtained, + * 0 otherwise +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Intialized the breakpoint module + * + * @returns 1 if breakpoint module has been initialized properly and all + * memory required has been obtained, + * 0 otherwise +*/ +#endif +#endif + int breakPointInit(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointFree: + * + * Free all memory used by breakpoint module + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free all memory used by breakpoint module + */ +#endif +#endif + void breakPointFree(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointActiveBreakPoint: + * + * Get the active break point + * + * Returns the last break point that we stoped at + * + * Depreciated + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Get the active break point + * + * @returns The last break point that we stoped at + * + * Depreciated + */ +#endif +#endif + breakPointPtr breakPointActiveBreakPoint(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointSetActiveBreakPoint: + * @breakPtr: Is valid break point or NULL + * + * Set the active break point + * + * Depreciated + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set the active break point + * + * @param breakPoint Is valid break point or NULL + * + * Depreciated + */ +#endif +#endif + void breakPointSetActiveBreakPoint(breakPointPtr breakPtr); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Add break point at file and line number specified + * + * @returns 1 if successful, + * 0 otherwise + * + * @param url Non-null, non-empty file name that has been loaded by + * debugger + * @param lineNumber @p lineNumber >= 0 and is available in url specified and + * points to an xml element + * @param temlateName The template name of break point or NULL + * @param modeName : The mode of breakpoint or NULL + * @param type Valid BreakPointTypeEnum +*/ +#endif +#endif + int breakPointAdd(const xmlChar * url, long lineNumber, + const xmlChar * templateName, + const xmlChar * modeName, + BreakPointTypeEnum type); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Delete the break point specified if it can be found using + * @p breakPtr's url and lineNo + * + * @returns 1 if successful, + * 0 otherwise + * + * @param breakPoint Is valid + * +*/ +#endif +#endif + int breakPointDelete(breakPointPtr breakPtr); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointEmpty: + * + * Empty the break point collection + * + * Returns 1 if able to empty the breakpoint list of its contents, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Empty the break point collection + * + * @returns 1 if able to empty the break point list of its contents, + * 0 otherwise + */ +#endif +#endif + int breakPointEmpty(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Enable or disable a break point + * + * @returns 1 if successful, + * 0 otherwise + * + * @param breakPoint A valid breakpoint + * @param enable Enable break point if 1, disable if 0, toggle if -1 +*/ +#endif +#endif + int breakPointEnable(breakPointPtr breakPtr, int enable); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Get a break point for the breakpoint collection + * + * @returns break point if break point exists at location specified, + * NULL otherwise + * + * @param url Non-null, non-empty file name that has been loaded by + * debugger + * @param lineNumber @p lineNumber >= 0 and is available in url specified +*/ +#endif +#endif + breakPointPtr breakPointGet(const xmlChar * url, long lineNumber); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Return A hash of breakpoints with same line number + * + * @param lineNo : Line number of of breakpoints of interest + * + * @returns A hash of breakpoints with a line number of @p lineNo + */ +#endif +#endif + xmlHashTablePtr breakPointGetLineNoHash(long lineNo); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointItemNew: + * + * Create a new break point item + * Returns A valid break point with default values set if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Create a new break point item + * + * @returns A valid break point with default values set if successful, + * NULL otherwise + */ +#endif +#endif + breakPointPtr breakPointItemNew(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointItemFree: + * @payload: valid breakPointPtr + * @name: not used + * + * Free memory associated with this break point + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free memory associated with this break point + * + * @param payload Valid breakPointPtr + * @param name not used + * + */ +#endif +#endif + void breakPointItemFree(void *payload, xmlChar * name); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 + */ +#else +#ifdef USE_KDE_DOCS + +/** + * 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 + */ +#endif +#endif + int breakPointLinesCount(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointPrint: + * @breakPtr: A valid break point + * + * Print the details of @breakPtr to @file + * + * Returns 1 if successful, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print the details of @p breakPtr to @p file + * + * @returns 1 if successful, + * 0 otherwise + * + * @param breakPoint A valid break point + */ +#endif +#endif + int breakPointPrint(breakPointPtr breakPtr); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Determine if there is a break point at file and line number specified + * + * @returns 1 if successful, + * 0 otherwise + * + * @param url Non-null, non-empty file name that has been loaded by + * debugger + * @lineNumber @p lineNumber >= 0 and is available in url specified +*/ +#endif +#endif + int breakPointIsPresent(const xmlChar * url, long lineNumber); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointIsPresentNode: + * @node: node != NULL + * + * Determine if a node is a break point + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Determine if a node is a break point + * + * @returns 1 on success, + * 0 otherwise + * + * @param node Is valid + */ +#endif +#endif + int breakPointIsPresentNode(xmlNodePtr node); + + + +#ifdef USE_GNOME_DOCS + +/** + * breakPointLinesList: + * + * Return The list of hash tables for break points + * Dangerous function to use!! + * + * Returns The list of hash tables for break points + * Dangerous function to use!! + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Return The list of hash tables for break points + * Dangerous function to use!! + * + * Returns The list of hash tables for break points + * Dangerous function to use!! + */ +#endif +#endif + arrayListPtr breakPointLineList(void); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp new file mode 100644 index 00000000..7935ea8c --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp @@ -0,0 +1,1036 @@ + +/*************************************************************************** + breakpoint_cmds.c - breakpoint commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "files.h" +#include "utils.h" +#include <libxml/valid.h> /* needed for xmlSplitQName2 */ +#include <libxml/xpathInternals.h> /* needed for xmlNSLookup */ +#include <libxml/uri.h> /* needed for xmlURIEscapeStr */ +#include "xsldbgthread.h" /* for getThreadStatus() */ +#include "xsldbgmsg.h" +#include "options.h" + +/* temp buffer needed occationaly */ +static xmlChar buff[DEBUG_BUFFER_SIZE]; + +/* needed by breakpoint validation */ +extern int breakPointCounter; + +/* we need to have a fake URL and line number for orphaned template breakpoints */ +int orphanedTemplateLineNo = 1; +const xmlChar *orphanedTemplateURL= (xmlChar*)"http://xsldbg.sourceforge.net/default.xsl"; +/* --------------------------------------------------- + Private function declarations for breakpoint_cmds.c + ----------------------------------------------------*/ + +/** + * validateSource: + * @url : is valid name of a xsl source file + * @lineNo : lineNo >= 0 + * + * Returns 1 if a breakpoint could be set at specified file url and line number + * 0 otherwise + */ +int validateSource(xmlChar ** url, long *lineNo); + +/** + * validateData: + * @url : is valid name of a xml data file + * @lineNo : lineNo >= 0 + * + * Returns 1 if a breakpoint could be set at specified file url and line number + * 0 otherwise + */ +int validateData(xmlChar ** url, long *lineNo); + + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + + +/* ----------------------------------------- + + BreakPoint related commands + + ------------------------------------------- */ + + +/** + * xslDbgShellFrameBreak: + * @arg: Is valid number of frames to change location by + * @stepup: If != 1 then we step up, otherwise step down + * + * Set a "frame" break point either up or down from here + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellFrameBreak(xmlChar * arg, int stepup) +{ + int result = 0; + + /* how many frames to go up/down */ + int noOfFrames; + static const char *errorPrompt = I18N_NOOP("Failed to add breakpoint."); + + if (!filesGetStylesheet() || !filesGetMainDoc()) { + xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded. Try reloading files.\n")); + xsldbgGenericErrorFunc(QString("Error: %1.\n").arg(i18n(errorPrompt))); + return result; + } + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + } + + if (xmlStrLen(arg) > 0) { + if (!sscanf((char *) arg, "%d", &noOfFrames)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a number of frames.\n").arg((char*)arg)); + noOfFrames = -1; + } + } else { + noOfFrames = 0; + } + + if (noOfFrames >0){ + if (stepup) { + result = callStackStepup(callStackGetDepth() - noOfFrames); + } else { + result = callStackStepdown(callStackGetDepth() + noOfFrames); + } + } + + if (!result) + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; +} + + +/** + * validateSource: + * @url : is valid name of a xsl source file + * @lineNo : lineNo >= 0 + * + * Returns 1 if a breakpoint could be set at specified file url and line number + * 0 otherwise + */ +int +validateSource(xmlChar ** url, long *lineNo) +{ + + int result = 0, type; + searchInfoPtr searchInf; + nodeSearchDataPtr searchData = NULL; + + if (!filesGetStylesheet()) { + xsldbgGenericErrorFunc(i18n("Error: Stylesheet is not valid or file is not loaded.\n")); + return result; + } + + if (!url) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + searchInf = searchNewInfo(SEARCH_NODE); + + if (searchInf && searchInf->data) { + type = DEBUG_BREAK_SOURCE; + searchData = (nodeSearchDataPtr) searchInf->data; + if (lineNo != NULL) + searchData->lineNo = *lineNo; + searchData->nameInput = (xmlChar *) xmlMemStrdup((char *) *url); + guessStylesheetName(searchInf); + /* try to verify that the line number is valid */ + if (searchInf->found) { + /* ok it looks like we've got a valid url */ + /* searchData->url will be freed by searchFreeInfo */ + if (searchData->absoluteNameMatch) + searchData->url = (xmlChar *) + xmlMemStrdup((char *) searchData->absoluteNameMatch); + else + searchData->url = (xmlChar *) + xmlMemStrdup((char *) searchData->guessedNameMatch); + + if (lineNo != NULL) { + /* now to check the line number */ + if (searchData->node) { + searchInf->found = 0; + /* searchData->node is set to the topmost node in stylesheet */ + walkChildNodes((xmlHashScanner) scanForNode, searchInf, + searchData->node); + if (!searchInf->found) { + xsldbgGenericErrorFunc(i18n("Warning: Breakpoint for file \"%1\" at line %2 does not seem to be valid.\n").arg(xsldbgUrl(*url)).arg(*lineNo)); + } + + *lineNo = searchData->lineNo; + xmlFree(*url); + *url = xmlStrdup(searchData->url); + result = 1; + } + + } else { + /* we've been asked just to check the file name */ + if (*url) + xmlFree(*url); + if (searchData->absoluteNameMatch) + *url = (xmlChar *) + xmlMemStrdup((char *) searchData->absoluteNameMatch); + else + *url = (xmlChar *) + xmlMemStrdup((char *) searchData->guessedNameMatch); + result = 1; + } + } else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to find a stylesheet file whose name contains %1.\n").arg(xsldbgUrl(*url))); + if (lineNo){ + xsldbgGenericErrorFunc(i18n("Warning: Breakpoint for file \"%1\" at line %2 does not seem to be valid.\n").arg(xsldbgUrl(*url)).arg(*lineNo)); + } + } + } + + if (searchInf) + searchFreeInfo(searchInf); + else + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + + return result; +} + + + + +/** + * validateData: + * @url : is valid name of a xml data file + * @lineNo : lineNo >= 0 + * + * Returns 1 if a breakpoint could be set at specified file url and line number + * 0 otherwise + */ +int +validateData(xmlChar ** url, long *lineNo) +{ + int result = 0; + searchInfoPtr searchInf; + nodeSearchDataPtr searchData = NULL; + char *lastSlash; + + if (!filesGetMainDoc()) { + if (!optionsGetIntOption(OPTIONS_GDB)){ + xsldbgGenericErrorFunc(i18n("Error: Data file is invalid. Try the run command first.\n")); + } + return result; + } + + if (!url) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + searchInf = searchNewInfo(SEARCH_NODE); + if (searchInf && searchInf->data && filesGetMainDoc()) { + /* Try to verify that the line number is valid. + First try an absolute name match */ + searchData = (nodeSearchDataPtr) searchInf->data; + if (lineNo != NULL) + searchData->lineNo = *lineNo; + else + searchData->lineNo = -1; + searchData->url = (xmlChar *) xmlMemStrdup((char *) *url); + walkChildNodes((xmlHashScanner) scanForNode, searchInf, + (xmlNodePtr) filesGetMainDoc()); + + /* Next try to guess file name by adding the prefix of main document + if no luck so far */ + if (!searchInf->found) { + /* Find the last separator of the documents URL */ + lastSlash = xmlStrrChr(filesGetMainDoc()->URL, URISEPARATORCHAR); + if (!lastSlash) + lastSlash = xmlStrrChr(filesGetMainDoc()->URL, PATHCHAR); + + if (lastSlash) { + lastSlash++; + xmlStrnCpy(buff, filesGetMainDoc()->URL, + lastSlash - (char *) filesGetMainDoc()->URL); + buff[lastSlash - (char *) filesGetMainDoc()->URL] = '\0'; + xmlStrCat(buff, *url); + } else + xmlStrCpy(buff, ""); + if (xmlStrLen(buff) > 0) { + if (searchData->url) + xmlFree(searchData->url); + searchData->url = (xmlChar *) xmlMemStrdup((char *) buff); + walkChildNodes((xmlHashScanner) scanForNode, searchInf, + (xmlNodePtr) filesGetMainDoc()); + } + } + + if (!searchInf->found) { + if (lineNo){ + xsldbgGenericErrorFunc(i18n("Warning: Breakpoint for file \"%1\" at line %2 does not seem to be valid.\n").arg(xsldbgUrl(*url)).arg(*lineNo)); + } else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to find a data file whose name contains %1.\n").arg(xsldbgUrl(*url))); + } + result = 1; + } else { + if (*url) + xmlFree(*url); + *url = xmlStrdup(searchData->url); + result = 1; + } + } + + if (searchInf) + searchFreeInfo(searchInf); + else + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + + return result; +} + + +/** + * xslDbgShellBreak: + * @arg: Is valid and in UTF-8 + * @style: Is valid + * @ctxt: Is valid + * + * Add break point specified by arg + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellBreak(xmlChar * arg, xsltStylesheetPtr style, + xsltTransformContextPtr ctxt) +{ + int result = 0; + long lineNo = -1; + xmlChar *url = NULL; + int orphanedBreakPoint = 0; + breakPointPtr breakPtr; + + static const char *errorPrompt = I18N_NOOP("Failed to add breakpoint."); + + if (style == NULL) { + style = filesGetStylesheet(); + } + if (!style || !filesGetMainDoc()) { + if (!optionsGetIntOption(OPTIONS_GDB)){ + xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded. Try reloading files.\n")); + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + }else{ + orphanedBreakPoint = 1; + } + } + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + if (arg[0] == '-') { + xmlChar *opts[2]; + + if ((xmlStrLen(arg) > 1) && (arg[1] == 'l')) { + if (splitString(&arg[2], 2, opts) == 2) { + if ((xmlStrlen(opts[1]) == 0) || + !sscanf((char *) opts[1], "%ld", &lineNo)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a line number.\n").arg((char*)opts[1])); + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + } else { + /* try to guess whether we are looking for source or data + * break point + */ + xmlChar *escapedURI; + trimString(opts[0]); + url = filesExpandName(opts[0]); + if (url){ + escapedURI = xmlURIEscapeStr(url, (const xmlChar*)"/"); + if (escapedURI){ + xmlFree(url); + url = escapedURI; + } + } + if (url) { + if (!orphanedBreakPoint){ + if (filesIsSourceFile(url)) { + if (validateSource(&url, &lineNo)) + result = + breakPointAdd(url, lineNo, NULL, NULL, + DEBUG_BREAK_SOURCE); + } else { + if (validateData(&url, &lineNo)) + result = + breakPointAdd(url, lineNo, NULL, NULL, + DEBUG_BREAK_DATA); + } + }else{ + if (filesIsSourceFile(url)) { + result = + breakPointAdd(url, lineNo, NULL, NULL, + DEBUG_BREAK_SOURCE); + }else{ + result = + breakPointAdd(url, lineNo, NULL, NULL, + DEBUG_BREAK_DATA); + } + breakPtr = breakPointGet(url, lineNo); + if (breakPtr){ + breakPtr->flags |= BREAKPOINT_ORPHANED; + }else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to find the added breakpoint.")); + } + } + } + } + } else + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to command %1.\n").arg("break")); + } + } else { + /* add breakpoint at specified template names */ + xmlChar *opts[2]; + xmlChar *name = NULL, *nameURI = NULL, *mode = NULL, *modeURI = NULL; + xmlChar *templateName = NULL, *modeName = NULL; + xmlChar *tempUrl = NULL; /* we must use a non-const xmlChar * + and we are not making a copy + of orginal value so this must not be + freed */ + xmlChar *defaultUrl = (xmlChar *) "<n/a>"; + int newBreakPoints = 0, validatedBreakPoints = 0; + int allTemplates = 0; + int ignoreTemplateNames = 0; + int argCount; + int found; + xsltTemplatePtr templ; + if (orphanedBreakPoint || !ctxt){ + /* Add an orphaned template breakpoint we will need to call this function later to + activate the breakpoint */ + result = + breakPointAdd(orphanedTemplateURL, orphanedTemplateLineNo, arg, NULL, + DEBUG_BREAK_SOURCE); + breakPtr = breakPointGet(orphanedTemplateURL, orphanedTemplateLineNo++); + if (breakPtr){ + breakPtr->flags |= BREAKPOINT_ORPHANED; + }else{ +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to find added breakpoint"); +#endif + } + return result; + } + + argCount = splitString(arg, 2, opts); + if ((argCount == 2) && (xmlStrLen(opts[1]) == 0)) + argCount = 1; + + switch (argCount){ + case 0: + allTemplates = 1; + break; + + case 1: + if (xmlStrEqual(opts[0], (xmlChar*)"*")){ + allTemplates = 1; + }else{ + + if (xmlStrEqual(opts[0], (xmlChar*)"\\*")){ + opts[0][0] = '*'; + opts[0][1] = '\0'; + } + + name = xmlSplitQName2(opts[0], &nameURI); + if (name == NULL){ + name = xmlStrdup(opts[0]); + }else{ + if (nameURI){ + /* get the real URI for this namespace */ + const xmlChar *temp = xmlXPathNsLookup(ctxt->xpathCtxt, nameURI); + if (temp) + xmlFree(nameURI); + nameURI = xmlStrdup(temp); + } + + } + } + break; + + case 2: + if (xmlStrLen(opts[0]) == 0){ + /* we don't care about the template name ie we are trying to match + templates with a given mode */ + ignoreTemplateNames = 1; + }else{ + name = xmlSplitQName2(opts[0], &nameURI); + if (name == NULL) + name = xmlStrdup(opts[0]); + if (nameURI){ + /* get the real URI for this namespace */ + const xmlChar *temp = xmlXPathNsLookup(ctxt->xpathCtxt, + nameURI); + if (temp) + xmlFree(nameURI); + nameURI = xmlStrdup(temp); + } + } + mode = xmlSplitQName2(opts[1], &modeURI); + if (mode == NULL) + mode = xmlStrdup(opts[1]); + if (modeURI){ + /* get the real URI for this namespace */ + const xmlChar *temp = xmlXPathNsLookup(ctxt->xpathCtxt, modeURI); + if (temp) + xmlFree(modeURI); + modeURI = xmlStrdup(temp); + } + break; + + default: + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for command %1.\n").arg("break")); + return 0; + } + + while (style) { + templ = style->templates; + while (templ) { + found = 0; + if (templ->elem && templ->elem->doc + && templ->elem->doc->URL) { + tempUrl = (xmlChar *) templ->elem->doc->URL; + } else { + tempUrl = defaultUrl; + } + + if (templ->match) + templateName = xmlStrdup(templ->match); + else + templateName = fullQName(templ->nameURI, templ->name); + + if (allTemplates) + found = 1; + else { + if (ignoreTemplateNames){ + if (!mode || (xmlStrEqual(templ->mode, mode) && + (!modeURI || xmlStrEqual(templ->modeURI, + modeURI)))) + found = 1; + } else if (templ->match){ + if ((xmlStrEqual(templ->match, name) && + (!modeURI || xmlStrEqual(templ->modeURI, + modeURI)) && + (!mode || xmlStrEqual(templ->mode, + mode)))) + found = 1; + }else{ + if(xmlStrEqual(templ->name, name) && + (!nameURI || xmlStrEqual(templ->nameURI, nameURI))) + found = 1; + } + } + if (found) { + int templateLineNo = xmlGetLineNo(templ->elem); + breakPointPtr searchPtr = breakPointGet(tempUrl, templateLineNo); + + if (templ->mode) + modeName = + fullQName(templ->modeURI, templ->mode); + + + if (!searchPtr){ + if (breakPointAdd(tempUrl, templateLineNo, + templateName, modeName, + DEBUG_BREAK_SOURCE)){ + newBreakPoints++; + } + }else{ + + if ((templateLineNo != searchPtr->lineNo ) || !xmlStrEqual(tempUrl, searchPtr->url)){ + int lastId = searchPtr->id; + int lastCounter = breakPointCounter; + /* we have a new location for breakpoint */ + if (breakPointDelete(searchPtr)){ + if (breakPointAdd(tempUrl, templateLineNo, templateName, modeName,DEBUG_BREAK_SOURCE)){ + searchPtr = breakPointGet(tempUrl, templateLineNo); + if (searchPtr){ + searchPtr->id = lastId; + result = 1; + breakPointCounter = lastCounter; + xsldbgGenericErrorFunc(i18n("Information: Breakpoint validation has caused breakpoint %1 to be re-created.\n").arg(searchPtr->id)); + validatedBreakPoints++; + } + } + } + }else{ + if (xsldbgValidateBreakpoints != BREAKPOINTS_BEING_VALIDATED){ + xsldbgGenericErrorFunc(i18n("Warning: Breakpoint exits for file \"%1\" at line %2.\n").arg(xsldbgUrl(tempUrl)).arg(templateLineNo)); + } + validatedBreakPoints++; + } + } + } + if (templateName){ + xmlFree(templateName); + templateName = NULL; + } + if (modeName){ + xmlFree(modeName); + modeName = NULL; + } + templ = templ->next; + } + if (style->next) + style = style->next; + else + style = style->imports; + } + + if ((newBreakPoints == 0) && (validatedBreakPoints == 0)) { + xsldbgGenericErrorFunc(i18n("Error: No templates found or unable to add breakpoint.\n")); + url = NULL; /* flag that we've printed partial error message about the problem url */ + } else { + result = 1; + if (newBreakPoints){ + xsldbgGenericErrorFunc(i18n("Information: Added %n new breakpoint.", "Information: Added %n new breakpoints.", newBreakPoints) + QString("\n")); + } + } + + if (name) + xmlFree(name); + if (nameURI) + xmlFree(nameURI); + if (mode) + xmlFree(mode); + if (modeURI) + xmlFree(modeURI); + if (defaultUrl && !xmlStrEqual((xmlChar*)"<n/a>", defaultUrl)) + xmlFree(defaultUrl); + if (tempUrl) + url = xmlStrdup(tempUrl); + } /* end add template breakpoints */ + + if (!result) { + if (url) + xsldbgGenericErrorFunc(i18n("Error: Failed to add breakpoint for file \"%1\" at line %2.\n").arg(xsldbgUrl(url)).arg(lineNo)); + else + xsldbgGenericErrorFunc(i18n("Error: Failed to add breakpoint.\n")); + } + + if (url) + xmlFree(url); + return result; +} + + +/** + * xslDbgShellDelete: + * @arg: Is valid and in UTF-8 + * + * Delete break point specified by arg + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellDelete(xmlChar * arg) +{ + int result = 0, breakPointId; + long lineNo; + breakPointPtr breakPtr = NULL; + static const char *errorPrompt = I18N_NOOP("Failed to delete breakpoint."); + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + } + + if (arg[0] == '-') { + xmlChar *opts[2], *url = NULL; + + if ((xmlStrLen(arg) > 1) && (arg[1] == 'l')) { + if (splitString(&arg[2], 2, opts) == 2) { + if ((xmlStrlen(opts[1]) == 0) || + !sscanf((char *) opts[1], "%ld", &lineNo)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a line number.\n").arg((char*)opts[1])); + } else { + xmlChar *escapedURI; + trimString(opts[0]); + url = filesExpandName(opts[0]); + if (url){ + escapedURI = xmlURIEscapeStr(url, (const xmlChar*)"/"); + if (escapedURI){ + xmlFree(url); + url = escapedURI; + } + } + if (url) { + if (filesIsSourceFile(url)) { + if (validateSource(&url, &lineNo)) + breakPtr = breakPointGet(url, lineNo); + } else if (validateData(&url, &lineNo)) + breakPtr = breakPointGet(url, lineNo); + if (!breakPtr || !breakPointDelete(breakPtr)){ + xsldbgGenericErrorFunc(i18n("Error: Breakpoint does not exist for file \"%1\" at line %2.\n").arg(xsldbgUrl(url)).arg(lineNo)); + }else{ + result = 1; + } + xmlFree(url); + } + } + } else{ + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for command %1.\n").arg("delete")); + } + } + } else if (xmlStrEqual((xmlChar*)"*", arg)) { + result = 1; + /*remove all from breakpoints */ + breakPointEmpty(); + + } else if (sscanf((char *) arg, "%d", &breakPointId)) { + breakPtr = findBreakPointById(breakPointId); + if (breakPtr) { + result = breakPointDelete(breakPtr); + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Unable to delete breakpoint %1.\n").arg(breakPointId)); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Breakpoint %1 does not exist.\n").arg(breakPointId)); + } + } else { + breakPtr = findBreakPointByName(arg); + if (breakPtr) { + result = breakPointDelete(breakPtr); + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Unable to delete breakpoint at template %1.\n").arg(xsldbgText(arg))); + } + } else{ + xsldbgGenericErrorFunc(i18n("Error: Breakpoint at template \"%1\" does not exist.\n").arg(xsldbgText(arg))); + } + } + if (!result) + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; +} + + +/** + * xslDbgShellEnableBreakPoint: + * @payload: A valid breakPointPtr + * @data: Enable type, a pointer to an integer + * for a value of + * 1 enable break point + * 0 disable break point + * -1 toggle enabling of break point + * @name: Not used + * + * Enable/disable break points via use of scan of break points +*/ +void +xslDbgShellEnableBreakPoint(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + if (payload && data) { + breakPointEnable((breakPointPtr) payload, *(int *) data); + } +} + + +/** + * xslDbgShellEnable: + * @arg : is valid and in UTF-8 + * @enableType : enable break point if 1, disable if 0, toggle if -1 + * + * Enable/disable break point specified by arg using enable + * type of @enableType + * Returns 1 if successful, + * 0 otherwise + */ + +int +xslDbgShellEnable(xmlChar * arg, int enableType) +{ + int result = 0, breakPointId; + long lineNo; + breakPointPtr breakPtr = NULL; + static const char *errorPrompt = I18N_NOOP("Failed to enable/disable breakpoint."); + + if (!filesGetStylesheet() || !filesGetMainDoc()) { + xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded. Try reloading files.\n")); + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + } + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; + } + + if (arg[0] == '-') { + xmlChar *opts[2], *url = NULL; + + if ((xmlStrLen(arg) > 1) && (arg[1] == 'l')) { + if (splitString(&arg[2], 2, opts) == 2) { + if ((xmlStrlen(opts[1]) == 0) || + !sscanf((char *) opts[1], "%ld", &lineNo)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a line number.\n").arg((char*)opts[1])); + } else { + xmlChar *escapedURI; + trimString(opts[0]); + url = filesExpandName(opts[0]); + if (url){ + escapedURI = xmlURIEscapeStr(url, (const xmlChar*)"/"); + if (escapedURI){ + xmlFree(url); + url = escapedURI; + } + } + if (url) { + if (strstr((char *) url, ".xsl")) { + if (validateSource(&url, NULL)) + breakPtr = breakPointGet(url, lineNo); + } else if (validateData(&url, NULL)) + breakPtr = breakPointGet(url, lineNo); + if (breakPtr){ + result = breakPointEnable(breakPtr, enableType); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Breakpoint does not exist for file \"%1\" at line %2.\n").arg(xsldbgUrl(url)).arg(lineNo)); + } + xmlFree(url); + } + } + } else + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for command %1.\n").arg("enable")); + } + } else if (xmlStrEqual((xmlChar*)"*", arg)) { + result = 1; + /*enable/disable all from breakpoints */ + walkBreakPoints((xmlHashScanner) xslDbgShellEnableBreakPoint, + &enableType); + + } else if (sscanf((char *) arg, "%d", &breakPointId)) { + breakPtr = findBreakPointById(breakPointId); + if (breakPtr) { + result = breakPointEnable(breakPtr, enableType); + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Unable to enable/disable breakpoint %1.\n").arg(breakPointId)); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Breakpoint %1 does not exist.\n").arg(breakPointId)); + } + } else { + breakPtr = findBreakPointByName(arg); + if (breakPtr) { + result = breakPointEnable(breakPtr, enableType); + } else + xsldbgGenericErrorFunc(i18n("Error: Breakpoint at template \"%1\" does not exist.\n").arg(xsldbgText(arg))); + } + + if (!result) + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + return result; +} + + +/** + * xslDbgShellPrintBreakPoint: + * @payload: A valid breakPointPtr + * @data: Not used + * @name: Not used + * + * Print data given by scan of break points +*/ +void +xslDbgShellPrintBreakPoint(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + + if (payload) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListQueue(payload); + } else { + printCount++; + xsldbgGenericErrorFunc(" "); + breakPointPrint((breakPointPtr) payload); + xsldbgGenericErrorFunc("\n"); + } + } +} + + +/* Validiate a breakpoint at a given URL and line number + breakPtr and copy must be valid +*/ +static int validateBreakPoint(breakPointPtr breakPtr, breakPointPtr copy) +{ + + int result = 0; + if (!breakPtr || !copy){ +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Warning: NULL arguments passed to validateBreakPoint\n"); +#endif + return result; + } + + if (filesIsSourceFile(breakPtr->url)) { + result = validateSource(©->url, ©->lineNo); + } else { + result = validateData(©->url, ©->lineNo); + } + if (result) + breakPtr->flags &= BREAKPOINT_ALLFLAGS ^ BREAKPOINT_ORPHANED; + else + breakPtr->flags |= BREAKPOINT_ORPHANED; + + if ( breakPtr->flags & BREAKPOINT_ORPHANED){ + xsldbgGenericErrorFunc(QString("Warning: Breakpoint %1 is orphaned. Result: %2. Old flags: %3. New flags: %4.\n").arg(breakPtr->id).arg(result).arg(copy->flags).arg(breakPtr->flags)); + } + + if (!(breakPtr->flags & BREAKPOINT_ORPHANED) && ((copy->lineNo != breakPtr->lineNo ) || + (xmlStrlen(copy->url) != xmlStrlen(breakPtr->url)) || xmlStrCmp(copy->url, breakPtr->url))){ + /* we have a new location for breakpoint */ + int lastCounter = breakPointCounter; + copy->templateName = xmlStrdup(breakPtr->templateName); + copy->modeName = xmlStrdup(breakPtr->modeName); + if (breakPointDelete(breakPtr) && !breakPointGet(copy->url, copy->lineNo)){ + if (breakPointAdd(copy->url, copy->lineNo, NULL, NULL, copy->type)){ + breakPtr = breakPointGet(copy->url, copy->lineNo); + if (breakPtr){ + breakPtr->id = copy->id; + breakPtr->flags = copy->flags; + breakPointCounter = lastCounter; /* compensate for breakPointAdd which always + increments the breakPoint counter */ + result = 1; + xsldbgGenericErrorFunc(i18n("Information: Breakpoint validation has caused breakpoint %1 to be re-created.\n").arg(breakPtr->id)); + } + } + if (!result){ + xsldbgGenericErrorFunc(i18n("Warning: Validation of breakpoint %1 failed.\n").arg(copy->id)); + } + } + } + + return result; +} + +/* Validiate a breakpoint at a given URL and line number + breakPtr, copy and ctx must be valid + */ +static int validateTemplateBreakPoint(breakPointPtr breakPtr, breakPointPtr copy, xsltTransformContextPtr ctxt) +{ + int result = 0; + if (!breakPtr || !copy || !ctxt){ +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Warning: NULL arguments passed to validateTemplateBreakPoint\n"); +#endif + return result; + } + + copy->templateName = xmlStrdup(breakPtr->templateName); + if ((xmlStrlen(copy->templateName) == 0) || xmlStrEqual(copy->templateName, (xmlChar*)"*")){ + if (xmlStrEqual(breakPtr->url, orphanedTemplateURL)) + breakPointDelete(breakPtr); + if ( xslDbgShellBreak(copy->templateName, NULL, ctxt)){ + result = 1; + xsldbgGenericErrorFunc(i18n("Information: Breakpoint validation has caused one or more breakpoints to be re-created.\n")); + } + }else{ + if (xmlStrEqual(breakPtr->url, orphanedTemplateURL)) + breakPointDelete(breakPtr); + if (xslDbgShellBreak(copy->templateName, NULL, ctxt)){ + result = 1; + } + } + xmlFree(copy->templateName); + if (!result){ + xsldbgGenericErrorFunc(i18n("Warning: Validation of breakpoint %1 failed.\n").arg(copy->id)); + } + return result; +} + +/** + * xslDbgShellValidateBreakPoint: + * @payload: A valid breakPointPtr + * @data: Not used + * @name: Not used + * + * Print an warning if a breakpoint is invalid + + */ +void xslDbgShellValidateBreakPoint(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + int result = 0; + if (payload){ + breakPointPtr breakPtr = (breakPointPtr) payload; + + breakPoint copy; /* create a copy of the breakpoint */ + copy.lineNo = breakPtr->lineNo; + copy.url = xmlStrdup(breakPtr->url); + copy.flags = breakPtr->flags; + copy.type = breakPtr->type; + copy.id = breakPtr->id; + if (copy.url){ + if (breakPtr->templateName){ + /* template name is used to contain the rules to add template breakpoint */ + result = validateTemplateBreakPoint(breakPtr, ©, (xsltTransformContextPtr)data); + }else{ + result = validateBreakPoint(breakPtr, ©); + } + }else{ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + + xmlFree(copy.url); + } +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/callstack.cpp b/kxsldbg/kxsldbgpart/libxsldbg/callstack.cpp new file mode 100644 index 00000000..585a70d1 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/callstack.cpp @@ -0,0 +1,509 @@ + +/*************************************************************************** + 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; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/callstack.h b/kxsldbg/kxsldbgpart/libxsldbg/callstack.h new file mode 100644 index 00000000..fd87b9bd --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/callstack.h @@ -0,0 +1,275 @@ + +/* ************************************************************************* + xslcallpoint.h - public functions for the + the call stack + ------------------- + begin : Fri Dec 7 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ************************************************************************* */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* */ + +#ifndef XSLCALLSTACK_H +#define XSLCALLSTACK_H + +/** + * Provide a call stack support + * + * @short call stack support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ + +#ifndef BUILD_DOCS +#include "breakpoint.h" +#endif + +#ifdef WITH_XSLT_DEBUG +#ifndef WITH_XSLT_DEBUG_BREAKPOINTS +#define WITH_XSLT_DEBUG_BREAKPOINTS +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + + typedef struct _callPointInfo callPointInfo; + typedef callPointInfo *callPointInfoPtr; + struct _callPointInfo { + xmlChar *templateName, *templateURI; + xmlChar *modeName, *modeURI; + xmlChar *url; + callPointInfoPtr next; + }; + + typedef struct _callPoint callPoint; + typedef callPoint *callPointPtr; + struct _callPoint { + callPointInfoPtr info; + long lineNo; + callPointPtr next; + }; + + +#ifdef USE_GNOME_DOCS + +/** + * 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 +*/ +#endif + int + callStackInit(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * callStackFree: + * + * + * Free all memory used by callStack + */ +#endif + void + callStackFree(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * 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 + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Add template "call" to call stack + * + * @param templ The current template being applied + * @param source The source node being processed + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int callStackAdd(xsltTemplatePtr templ, xmlNodePtr source); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackDrop: + * + * + * Drop the topmost item off the call stack + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Drop the topmost item off the call stack + */ +#endif +#endif + void callStackDrop(void); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackStepup: + * @depth:The frame depth to step up to + * 0 < @depth <= callDepth() + * + * Set the frame depth to step up to + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set the frame depth to step up to + * + * @returns 1 on success, + * 0 otherwise + * + * @param depth The frame depth to step up to + * 0 < @p depth <= callDepth() + */ +#endif +#endif + int callStackStepup(int depth); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackStepdown: + * @depth: The frame depth to step down to, + * 0 < @depth <= callDepth() + * + * Set the frame depth to step down to + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set the frame depth to step down to + * + * @returns 1 on success, + * 0 otherwise + * + * @param depth The frame depth to step down to + * 0 < @p depth <= callDepth() + */ +#endif +#endif + int callStackStepdown(int depth); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackGet: + * @depth: 0 < @depth <= callDepth() + * + * Retrieve the call point at specified call depth + + * Returns Non-null a if depth is valid, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Retrieve the call point at specified call depth + + * @returns Non-null a if depth is valid, + * NULL otherwise + * + * @param depth 0 < @p depth <= callDepth() + */ +#endif +#endif + callPointPtr callStackGet(int depth); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackGetTop: + * + * Get the top item in the call stack + * + * Returns The top of the call stack + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Get the top item in the call stack + * + * @returns The top of the call stack + */ +#endif +#endif + callPointPtr callStackGetTop(void); + + +#ifdef USE_GNOME_DOCS + +/** + * callStackGetDepth: + * + * Return the depth of call stack + * + * Returns The depth of call stack + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns the depth of call stack + */ +#endif +#endif + int callStackGetDepth(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/cmds.h b/kxsldbg/kxsldbgpart/libxsldbg/cmds.h new file mode 100644 index 00000000..f12648c7 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/cmds.h @@ -0,0 +1,197 @@ + +/*************************************************************************** + cmds.h - A list of valid commands ID's for xsldbg + ------------------- + begin : Thu Dec 27 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef CMDS_H +#define CMDS_H + +/* See the top of debugXSL.c for a list of command names and thier shortcuts */ +#ifndef USE_KDE_DOCS +typedef enum { /* id's for commands of xslDbgShell */ + DEBUG_HELP_CMD = 100, + DEBUG_BYE_CMD, + DEBUG_EXIT_CMD, + DEBUG_QUIT_CMD, + + DEBUG_STEP_CMD, + DEBUG_STEPUP_CMD, + DEBUG_STEPDOWN_CMD, + DEBUG_NEXT_CMD, + DEBUG_CONT_CMD, + DEBUG_RUN_CMD, + + DEBUG_TEMPLATES_CMD, + DEBUG_WHERE_CMD, + DEBUG_FRAME_CMD, + DEBUG_STYLESHEETS_CMD, + + DEBUG_BREAK_CMD, + DEBUG_SHOWBREAK_CMD, + DEBUG_DELETE_CMD, + DEBUG_ENABLE_CMD, + DEBUG_DISABLE_CMD, + + DEBUG_LS_CMD, + DEBUG_DIR_CMD, + DEBUG_DU_CMD, + DEBUG_CAT_CMD, + DEBUG_PRINT_CMD, /* cat alternative */ + DEBUG_PWD_CMD, + DEBUG_DUMP_CMD, + DEBUG_BASE_CMD, + + DEBUG_GLOBALS_CMD, + DEBUG_LOCALS_CMD, + /* DEBUG_CAT_CMD, already listed */ + DEBUG_SOURCE_CMD, + DEBUG_DATA_CMD, + DEBUG_OUTPUT_CMD, + DEBUG_CD_CMD, + + /* file related */ + /* DEBUG_OUTPUT_CMD, already listed */ + DEBUG_ENTITIES_CMD, + DEBUG_SYSTEM_CMD, + DEBUG_PUBLIC_CMD, + DEBUG_ENCODING_CMD, + DEBUG_VALIDATE_CMD, + DEBUG_LOAD_CMD, + DEBUG_SAVE_CMD, + DEBUG_WRITE_CMD, + DEBUG_FREE_CMD, + + /* Operating system related */ + DEBUG_CHDIR_CMD, + DEBUG_SHELL_EXEC_CMD, + DEBUG_TTY_CMD, + + /* libxslt parameter and options related */ + DEBUG_ADDPARAM_CMD, + DEBUG_DELPARAM_CMD, + DEBUG_SHOWPARAM_CMD, + DEBUG_SETOPTION_CMD, + DEBUG_OPTIONS_CMD, /* print options */ + + /* extra options/commands */ + DEBUG_TRACE_CMD, + DEBUG_WALK_CMD, + DEBUG_ADDWATCH_CMD, + DEBUG_DELWATCH_CMD, + DEBUG_SHOWWATCH_CMD, + + /* searching */ + DEBUG_SEARCH_CMD, + + /* variable change */ + DEBUG_SET_CMD, + + /* language change */ + DEBUG_LANG_CMD + + /* NULL */ + +} CommandsEnum; +#else + +/* Keep kdoc happy*/ +enum CommandsEnum { /* id's for commands of xslDbgShell */ + DEBUG_HELP_CMD = 100, + DEBUG_BYE_CMD, + DEBUG_EXIT_CMD, + DEBUG_QUIT_CMD, + + DEBUG_STEP_CMD, + DEBUG_STEPUP_CMD, + DEBUG_STEPDOWN_CMD, + DEBUG_NEXT_CMD, + DEBUG_CONT_CMD, + DEBUG_RUN_CMD, + + DEBUG_TEMPLATES_CMD, + DEBUG_WHERE_CMD, + DEBUG_FRAME_CMD, + DEBUG_STYLESHEETS_CMD, + + DEBUG_BREAK_CMD, + DEBUG_SHOWBREAK_CMD, + DEBUG_DELETE_CMD, + DEBUG_ENABLE_CMD, + DEBUG_DISABLE_CMD, + + DEBUG_LS_CMD, + DEBUG_DIR_CMD, + DEBUG_DU_CMD, + DEBUG_CAT_CMD, + DEBUG_PRINT_CMD, /* cat alternative */ + DEBUG_PWD_CMD, + DEBUG_DUMP_CMD, + DEBUG_BASE_CMD, + + DEBUG_GLOBALS_CMD, + DEBUG_LOCALS_CMD, + /* DEBUG_CAT_CMD, already listed */ + DEBUG_SOURCE_CMD, + DEBUG_DATA_CMD, + DEBUG_OUTPUT_CMD, + DEBUG_CD_CMD, + + /* file related */ + /* DEBUG_OUTPUT_CMD, already listed */ + DEBUG_ENTITIES_CMD, + DEBUG_SYSTEM_CMD, + DEBUG_PUBLIC_CMD, + DEBUG_ENCODING_CMD, + DEBUG_VALIDATE_CMD, + DEBUG_LOAD_CMD, + DEBUG_SAVE_CMD, + DEBUG_WRITE_CMD, + DEBUG_FREE_CMD, + + /* Operating system related */ + DEBUG_CHDIR_CMD, + DEBUG_SHELL_EXEC_CMD, + DEBUG_TTY_CMD, + + /* libxslt parameter and options related */ + DEBUG_ADDPARAM_CMD, + DEBUG_DELPARAM_CMD, + DEBUG_SHOWPARAM_CMD, + DEBUG_SETOPTION_CMD, + DEBUG_OPTIONS_CMD, /* print options */ + + /* extra options/commands */ + DEBUG_TRACE_CMD, + DEBUG_WALK_CMD, + DEBUG_ADDWATCH_CMD, + DEBUG_DELWATCH_CMD, + DEBUG_SHOWWATCH_CMD, + + /* searching */ + DEBUG_SEARCH_CMD, + + /* variable change */ + DEBUG_SET_CMD + + /* language change */ + DEBUG_LANG_CMD + + /* NULL */ +}; +#endif + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/debug.cpp b/kxsldbg/kxsldbgpart/libxsldbg/debug.cpp new file mode 100644 index 00000000..2975f814 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/debug.cpp @@ -0,0 +1,235 @@ + +/*************************************************************************** + debug.c - main functions for debugger use + ------------------- + begin : Fri Nov 2 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +#include "xsldbg.h" +#include "debug.h" +#include "debugXSL.h" /* needed for debugXSLBreak function */ +#include "breakpoint.h" +#include "callstack.h" +#include "files.h" +#include "options.h" + +#include <libxslt/xsltutils.h> /* need for breakpoint callback support */ + +/* setup debugger callbacks */ +struct DebuggerCallbacks { + xsltHandleDebuggerCallback debuggercallback; + xsltAddCallCallback addcallback; + xsltDropCallCallback dropcallback; +} debuggerDriver; + + +/* ----------------------------------------- + Private functions + -------------------------------------------*/ + +/** + * debugHandleDebugger: + * @cur : source node being executed + * @node : data node being processed + * @templ : temlate that applies to node + * @ctxt : the xslt transform context + * + * If either cur or node are a breakpoint, or xslDebugStatus in state + * where debugging must occcur at this time, then transfer control + * to the debugXSLBreak function + */ +void debugHandleDebugger(xmlNodePtr cur, xmlNodePtr node, + xsltTemplatePtr templ, + xsltTransformContextPtr ctxt); + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + +/*----------------------------------------------------------- + Main debugger functions +-----------------------------------------------------------*/ + + + +/** + * debugInit : + * + * Initialize debugger + * Returns 1 on success, + * 0 otherwise + */ +int +debugInit(void) +{ + int result; + + xslDebugStatus = DEBUG_NONE; + result = breakPointInit(); + result = result && callStackInit(); + + /* setup debugger callbacks */ + debuggerDriver.debuggercallback = debugHandleDebugger; + debuggerDriver.addcallback = callStackAdd; + debuggerDriver.dropcallback = callStackDrop; + xsltSetDebuggerCallbacks(3, &debuggerDriver); + return result; +} + + +/** + * debugFree : + * + * Free up any memory taken by debugging + */ +void +debugFree(void) +{ + breakPointFree(); + callStackFree(); +} + + +/** + * debugGotControl: + * @reached: 1 if debugger has received control, -1 to read its value, + 0 to clear the flag + * + * Set flag that debugger has received control to value of @reached + * + * Returns 1 if any break point was reached previously, + * 0 otherwise + */ +int +debugGotControl(int reached) +{ + static int hasReached; + int result = hasReached; + + if (reached != -1) + hasReached = reached; + return result; +} + + +/** + * debugHandleDebugger: + * @cur : source node being executed + * @node : data node being processed + * @templ : temlate that applies to node + * @ctxt : the xslt transform context + * + * If either cur or node are a breakpoint, or xslDebugStatus in state + * where debugging must occcur at this time then transfer control + * to the debugXSLBreak function + */ +void +debugHandleDebugger(xmlNodePtr cur, xmlNodePtr node, + xsltTemplatePtr templ, xsltTransformContextPtr ctxt) +{ + + if (!cur && !node) { + xsldbgGenericErrorFunc(i18n("Error: XSLT source and XML data are empty. Cannot enter the debugger.\n")); + } else { + if (optionsGetIntOption(OPTIONS_GDB)){ + int doValidation = 0; + switch(xsldbgValidateBreakpoints){ + case BREAKPOINTS_ARE_VALID: + if (!filesGetStylesheet() || !filesGetMainDoc()) { + xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION; + doValidation = 1; + } + + break; + + case BREAKPOINTS_NEED_VALIDATION: + if (filesGetStylesheet() && filesGetMainDoc() && templ){ + xsldbgValidateBreakpoints = BREAKPOINTS_BEING_VALIDATED; + doValidation = 1; + } + break; + + case BREAKPOINTS_BEING_VALIDATED: + /*should never be in the state for any length of time */ +#ifdef WITH_XSLDBG_DEBUG_BREAKPOINTS + xsltGenericError(xsltGenericErrorContext, + "Error: Unexpected breakpoint validation state %d", xsldbgValidateBreakpoints); +#endif + break; + } + if (doValidation){ + /* breakpoints will either be marked as orphaned or not as needed */ + xsldbgValidateBreakpoints = BREAKPOINTS_BEING_VALIDATED; + walkBreakPoints((xmlHashScanner) + xslDbgShellValidateBreakPoint, ctxt); + if (filesGetStylesheet() && filesGetMainDoc() && templ){ + xsldbgValidateBreakpoints = BREAKPOINTS_ARE_VALID; + }else{ + xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION; + } + } + } + switch (xslDebugStatus) { + + /* A temparary stopping point */ + case DEBUG_WALK: + case DEBUG_TRACE: + /* only allow breakpoints at xml elements */ + if (xmlGetLineNo(cur) != -1) + debugXSLBreak(cur, node, templ, ctxt); + break; + + case DEBUG_STOP: + xslDebugStatus = DEBUG_CONT; + /* only allow breakpoints at xml elements */ + if (xmlGetLineNo(cur) != -1) + debugXSLBreak(cur, node, templ, ctxt); + break; + + case DEBUG_STEP: + /* only allow breakpoints at xml elements */ + if (xmlGetLineNo(cur) != -1) + debugXSLBreak(cur, node, templ, ctxt); + break; + + case DEBUG_CONT: + { + breakPointPtr breakPtr = NULL; + xmlChar *baseUri = NULL; + + if (cur) { + breakPtr = + breakPointGet(cur->doc->URL, + xmlGetLineNo(cur)); + + if (breakPtr && (breakPtr->flags & BREAKPOINT_ENABLED) ){ + debugXSLBreak(cur, node, templ, ctxt); + return; + } + } + if (node) { + baseUri = filesGetBaseUri(node); + if (baseUri != NULL) { + breakPtr = + breakPointGet(baseUri, xmlGetLineNo(node)); + } else { + breakPtr = + breakPointGet(node->doc->URL, + xmlGetLineNo(node)); + } + if (breakPtr) { + if (breakPtr->flags & BREAKPOINT_ENABLED) { + debugXSLBreak(cur, node, templ, ctxt); + } + } + if (baseUri) + xmlFree(baseUri); + } + } + break; + } + } +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/debug.h b/kxsldbg/kxsldbgpart/libxsldbg/debug.h new file mode 100644 index 00000000..c38f37eb --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/debug.h @@ -0,0 +1,101 @@ + +/************************************************************************** + debug.h - declare major debugger functions + ------------------- + begin : Thur Jan 31 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + +#ifndef XSL_DEBUG_H +#define XSL_DEBUG_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef USE_GNOME_DOCS + +/** + * debugInit: + * + * Initialize debugger allocating any memory needed by debugger + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Initialize debugger allocating any memory needed by debugger + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int debugInit(void); + + + +#ifdef USE_GNOME_DOCS + +/** + * debugFree: + * + * Free up any memory taken by debugger + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free up any memory taken by debugger + */ +#endif +#endif + void debugFree(void); + + +#ifdef USE_GNOME_DOCS + +/** + * debugGotControl: + * @reached: 1 if debugger has received control, -1 to read its value, + 0 to clear the flag + * + * Set flag that debuger has received control to value of @reached + * + * Returns 1 if any break point was reached previously, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set flag that debuger has received control to value of @p reached + * + * @returns 1 if any breakpoint was reached previously, + * 0 otherwise + * + * @param reached 1 if debugger has received control, -1 to read its value, + * 0 to clear the flag + */ +#endif +#endif + int debugGotControl(int reached); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp new file mode 100644 index 00000000..39aea804 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.cpp @@ -0,0 +1,2118 @@ + +/*************************************************************************** + debugXSL.c - debugger commands to use + ------------------- + begin : Sun Sep 16 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + * Orinal file : debugXML.c : This is a set of routines used for + * debugging the tree produced by the XML parser. + * + * New file : shell.c : Debug support version + * + * See Copyright for the status of this software. + * + * Daniel Veillard <daniel@veillard.com> + * + * Permission obtained to modify the LGPL'd code and extend to include breakpoints, inspections of + * stylesheet source, xml data, stylesheet variables + */ + +#ifdef WIN32 +#include <wtypes.h> +#include <winbase.h> /* needed fort the sleep function */ +#endif + +#include "xsldbg.h" +#include "files.h" +#include "cmds.h" /* list of command Id's */ +#include "debug.h" +#include "debugXSL.h" +#include "options.h" +#include "breakpoint.h" +#include "help.h" +#include <stdlib.h> +#include <libxslt/transform.h> /* needed by source command */ +#include <libxslt/xsltInternals.h> +#include <libxml/debugXML.h> +#include <stdio.h> + +/* language change support */ +#ifdef LOCALE_PREFIX +#include <locale.h> +#endif + +#include "xsldbgmsg.h" +#include "xsldbgthread.h" /* for get thread status */ +#include "xsldbgio.h" + +/* current template being processed */ +xsltTemplatePtr rootCopy; + +/* how may items have been printed */ +int printCount; + +/* used to sending small amounts data when xsldbg runs as a thread */ +xmlChar messageBuffer[2000]; + +/* To achieve the same fucntionality of a next command + we first do a step, then a step up */ +int nextCommandActive = 0; + +/* Do we print the values for watches each time the debugger stops */ +int showWatchesActive = 1; + +extern FILE *terminalIO; + +int xsldbgStop = 0; +int xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION; +int xsldbgHasLineNumberFix; +bool xsldbgReachedFirstTemplate = false; + +/* valid commands of xslDbgShell */ +const char *commandNames[] = { + "help", + + "bye", + "exit", + "quit", + + "step", + "stepup", + "stepdown", + "next", /* next ie step over template function call*/ + "continue", + "run", + + "templates", + "where", + "frame", + "stylesheets", + + "break", + "showbreak", + "delete", + "enable", + "disable", + + "ls", + "dir", + "du", + "cat", + "print", + "pwd", + "dump", + "base", + + "globals", + "locals", + /* "cat", already listed */ + "source", + "data", + "output", /* output file name */ + "cd", + + /* file related */ + /* "output", already listed */ + "entities", + "system", + "public", + "encoding", + "validate", + "load", + "save", + "write", + "free", + + /* Operating system related */ + "chdir", + "shell", + "tty", + + /* libxslt parameter related */ + "addparam", + "delparam", + "showparam", + "setoption", + "options", + + /* extra options */ + "trace", + "walk", + "addwatch", + "delwatch", + "showwatch", + + /* searching */ + "search", + + /*variable value change */ + "set", + + /* language change */ + "lang", + + NULL /* Indicate the end of list */ +}; + +/* valid commands of xslShell in there alternative|shorter format */ +const char *shortCommandNames[] = { + "h", + + "bye", + "exit", + "q", /*quit */ + + "s", /* step */ + "up", /*stepup */ + "down", /* stepdown */ + "n", /* next ie step over function call*/ + "c", /* continue */ + "r", /* run */ + + "t", /* templates */ + "w", /* where */ + "f", + "style", + + "b", /* break */ + "show", + "d", /* delete */ + "e", /* enabled */ + "disable", + + "ls", + "dir", + "du", + "cat", + "print", + "pwd", + "dump", + "base", + + "globals", + "locals", + /* "cat", already listed */ + "source", + "data", + "o", /* output file name */ + "cd", + + + /* file related */ + /* "output", already listed */ + "ent", /* entities command */ + "sys", /* sytem command */ + "pub", /* public command */ + "encoding", + "validate", + "load", + "save", + "write", + "free", + + /* Operating system related */ + "chdir", + "shell", + "tty", + + /* libxslt parameter related */ + "addparam", + "delparam", + "showparam", + "setoption", + "options", + + /* extra options/commands */ + "trace", + "walk", + "watch", + "delwatch", + "watches", + + /* searching */ + "search", + + /*variable value change */ + "set", + + /* language change */ + "lang", + + NULL /* Indicate the end of list */ +}; + + +/* some convenient short cuts when using cd command*/ +const char *cdShortCuts[] = { + "<<", + ">>", + "<-", + "->", + NULL /* indicate end of list */ +}; + +/* what to replace shortcuts with */ +const char *cdAlternative[] = { + "preceding-sibling::node()", + "following-sibling::node()", + "ancestor::node()", + "descendant::node()", + NULL /* indicate end of list */ +}; + +/* what enum to use for shortcuts */ +enum ShortcutsEnum { + DEBUG_PREV_SIBLING = 200, + DEBUG_NEXT_SIBLING, + DEBUG_ANCESTOR_NODE, + DEBUG_DESCENDANT_NODE +}; + + + +#include <libxml/xpathInternals.h> + +#include <libxslt/extra.h> +#include <string.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + + +#include <libxml/xmlmemory.h> +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/valid.h> +#include <libxml/debugXML.h> +#include <libxml/HTMLtree.h> +#include <libxml/HTMLparser.h> + + +/* ----------------------------------------- + Private function declarations for debugXSL.c + -------------------------------------------*/ + + +/* xslDbgCd : + * Change directories + * @styleCtxt : current stylesheet context + * @ctxt : current shell context + * @arg : path to change to + * @source : is valid + * + * Returns 1 on success, + * 0 otherwise + */ +int xslDbgCd(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt, + xmlChar * arg, xmlNodePtr source); + + +/** + * xslDbgPrintCallStack: + * @arg : the number of frame to print, NULL if all items + * + * Print all items found on the callStack + * + * Returns 1 on success, + * 0 otherwise + */ +int xslDbgPrintCallStack(const xmlChar * arg); + + +/** + * xslDbgSleep: + * @delay : the number of microseconds to delay exection by + * + * Delay execution by a specified number of microseconds. On some system + * this will not be at all accurate. + */ +void xslDbgSleep(long delay); + + +/** + * xslDbgWalkContinue: + * + * Delay execution for time as indicated by OPTION_WALK_SPEED + * Can only be called from within shellPrompt! + * OPTION_WALK_SPEED != WALKSPEED_STOP + * + * Returns 1 if walk is to continue, + * 0 otherwise + */ +int xslDbgWalkContinue(void); + + + +/** + * addBreakPointNode: + * @payload : valid breakPointPtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addBreakPointNode(void *payload, void *data, + xmlChar * name); + + +/** + * addSourceNode: + * @payload : valid xsltStylesheetPtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addSourceNode(void *payload, void *data, + xmlChar * name); + + +/** + * addTemplateNode: + * @payload : valid xsltTemplatePtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addTemplateNode(void *payload, void *data, + xmlChar * name); + +/** + * addGlobalNode: + * @payload : valid xmlNodePtr of global variable + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addGlobalNode(void *payload, void *data, + xmlChar * name); + +/** + * addLocalNode: + * @payload : valid xmlNodePtr of local variable + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addLocalNode(void *payload, void *data, + xmlChar * name); + + +/** + * addIncludeNode: + * @payload : valid xmlNodePtr of include instuction + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void + addIncludeNode(void *payload, void *data, + xmlChar * name); + + + +/** + * addCallStackItems: + * + * Convert call stack items into format needed, and add to search dataBase + */ +void + addCallStackItems(void); + + +/** + * shellPrompt: + * @source: The current stylesheet instruction being executed + * @doc: The current document node being processed + * @filename: Not used + * @input: The function to call to when reading commands from stdio + * @output: Where to put the results + * @styleCtxt: Is valid + * + * Present to the user the xsldbg shell + */ +void shellPrompt(xmlNodePtr source, xmlNodePtr doc, + xmlChar * filename, + xmlShellReadlineFunc input, + FILE * output, xsltTransformContextPtr styleCtxt); + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + + +/** + * debugXSLGetTemplate: + * + * Return the last template node found, if an + * + * Returns The last template node found, if any + */ +xsltTemplatePtr +debugXSLGetTemplate(void) +{ + return rootCopy; +} + + +/**************************************************************** + * * + * The XSL shell related functions * + * * + ****************************************************************/ + + +/* xslDbgCd : + * Change directories + * @styleCtxt : current stylesheet context + * @ctxt : current shell context + * @arg : path to change to and in UTF-8 + * @source : is valid + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgCd(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt, + xmlChar * arg, xmlNodePtr source) +{ + xmlXPathObjectPtr list = NULL; + int result = 0; + int offset = 2; /* in some cases I'm only interested after first two chars */ + + if (!ctxt) { + xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded. Try reloading files.\n")); + return result; + } + + if (arg == NULL) + arg = (xmlChar *) ""; + if (arg[0] == 0) { + ctxt->node = (xmlNodePtr) ctxt->doc; + } else { + if ((arg[0] == '-') && (xmlStrLen(arg) > 2)) { + if (styleCtxt) { + if (arg[1] == 't') { + xmlNodePtr templateNode; + + /* quickly find a template */ + /* skip any white spaces */ + while (_IS_BLANK(arg[offset])) + offset++; + + templateNode = + findTemplateNode(styleCtxt->style, &arg[offset]); + if (!templateNode) { + xsldbgGenericErrorFunc(i18n("Error: The XSLT template named \"%1\" was not found.\n").arg(xsldbgText(&arg[offset]))); + return result; + } else { + xsldbgGenericErrorFunc(i18n(" template: \"%1\"\n").arg(xsldbgText(&arg[offset]))); + ctxt->node = templateNode; + result = 1; + return result; + } + } else if (arg[1] == 's') { + /*quickly switch to another stylesheet node */ + xmlXPathContextPtr pctxt; + + if (source) { + pctxt = xmlXPathNewContext(source->doc); + if (pctxt == NULL) { + xmlFree(ctxt); + /* xslDebugStatus = DEBUG_QUIT; */ + return result; + } + if (!xmlXPathNsLookup(pctxt, (xmlChar *) "xsl")) + xmlXPathRegisterNs(pctxt, (xmlChar *) "xsl", + XSLT_NAMESPACE); + list = + xmlXPathEval((xmlChar *) & arg[offset], pctxt); + if (pctxt) { + xmlFree(pctxt); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to cd. No stylesheet loaded.\n")); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Unknown arguments to the command %1.\n").arg("cd")); + } + } else + xsldbgGenericErrorFunc(i18n("Error: Unable to cd. No stylesheet loaded.\n")); + } else { + xmlNodePtr savenode; + + if (styleCtxt) { + savenode = styleCtxt->xpathCtxt->node; + ctxt->pctxt->node = ctxt->node; + styleCtxt->xpathCtxt->node = ctxt->node; + if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl")) + xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl", + XSLT_NAMESPACE); + list = xmlXPathEval((xmlChar *) arg, styleCtxt->xpathCtxt); + styleCtxt->xpathCtxt->node = savenode; + } else if (ctxt->pctxt) { + if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl")) + xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl", + XSLT_NAMESPACE); + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); + } else { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to the command %1.\n").arg("cd")); + } + } + + if (list != NULL) { + switch (list->type) { + case XPATH_NODESET: + if (list->nodesetval) { + if (list->nodesetval->nodeNr == 1) { + ctxt->node = list->nodesetval->nodeTab[0]; + /* tell the application about the new line + * number we are looking at */ + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + int breakpoint = 0; + + xsldbgUpdateFileDetails(ctxt->node); + notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, + &breakpoint); + } + result = 1; + } else + xsldbgGenericErrorFunc(i18n("Warning: XPath %1 is a Node Set with %n child.", "Warning: XPath %1 is a Node Set with %n children.", list->nodesetval->nodeNr).arg(xsldbgText(arg)) + QString("\n")); + } else { + xsldbgGenericErrorFunc(i18n("Warning: XPath %1 is an empty Node Set.\n").arg(xsldbgText(arg))); + } + break; + + default: + xmlShellPrintXPathError(list->type, (char *) arg); + } + xmlXPathFreeObject(list); + } else { + xsldbgGenericErrorFunc(i18n("Error: XPath %1 was not found.\n").arg(xsldbgText(arg))); + } + if (ctxt->pctxt) + ctxt->pctxt->node = NULL; + } + return result; +} + + +/** + * xslDbgPrintCallStack: + * @arg : the number of frame to print, NULL if all items + * + * Print all items found on the callStack + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgPrintCallStack(const xmlChar * arg) +{ + int depth = 0; + int result = 1; + callPointPtr callPointItem; + + if (arg == NULL) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_CALLSTACK_CHANGED); + /* we send the oldest frame stack first */ + for (depth = 1; depth <= callStackGetDepth(); depth++) { + callPointItem = callStackGet(depth); + if (callPointItem && callPointItem->info) { + notifyListQueue(callPointItem); + } + } + notifyListSend(); + } else { + xmlChar *nameTemp, *modeTemp; + for (depth = callStackGetDepth(); depth >= 1; depth--) { + callPointItem = callStackGet(depth); + nameTemp = NULL; + modeTemp = NULL; + if (callPointItem && callPointItem->info) { + if (depth == callStackGetDepth()) { + xmlChar *curUrl = xsldbgUrl(); + long curLine = xsldbgLineNo(); + /* if possible list the current location */ + if (rootCopy && (rootCopy->match || rootCopy->name) + && curUrl) { + xmlChar *rootNameTemp, *rootModeTemp; + rootNameTemp = fullQName(rootCopy->nameURI, rootCopy->name); + rootModeTemp = fullQName(rootCopy->modeURI, rootCopy->mode); + if (rootNameTemp && rootModeTemp){ + if (rootCopy->match) + /* display information about the current XSLT template */ + xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth).arg(xsldbgText(rootCopy->match)).arg(xsldbgText(rootModeTemp))); + else + /* display information about the current XSLT template */ + xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth).arg(xsldbgText(rootNameTemp)).arg(xsldbgText(rootModeTemp))); + /* display where we are in the source/document file */ + xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(curUrl)).arg(curLine)); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + result = 0; + } + if (rootNameTemp){ + xmlFree(rootNameTemp); + rootNameTemp = NULL; + } + if (rootModeTemp){ + xmlFree(rootModeTemp); + rootModeTemp = NULL; + } + } else if (curUrl) { + /* display information about the current XSLT template */ + xsldbgGenericErrorFunc(i18n("#%1 template: \"LIBXSLT_DEFAULT\" mode: \"\"").arg(depth)); + /* display where we are in the source/document file */ + xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(curUrl)).arg(curLine)); + } + if (curUrl) + xmlFree(curUrl); + + } + nameTemp = fullQName(callPointItem->info->templateURI, + callPointItem->info->templateName); + modeTemp = fullQName(callPointItem->info->modeURI, + callPointItem->info->modeName); + if (nameTemp && modeTemp){ + /* display information about the current XSLT template */ + xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\" mode: \"%3\"").arg(depth - 1).arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp))); + if (callPointItem->info->url) + /* display where we are in the source/document file */ + xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(callPointItem->info->url)).arg(callPointItem->lineNo)); + else + xsldbgGenericErrorFunc("\n"); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + result = 0; + } + if (nameTemp){ + xmlFree(nameTemp); + nameTemp = NULL; + } + if(modeTemp){ + xmlFree(modeTemp); + modeTemp = NULL; + } + + } else { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Call stack item not found at depth %d : xslDbgPrintCallStack\n", depth); +#endif + result = 0; + break; + } + } + if (callStackGetDepth() == 0) + xsldbgGenericErrorFunc(i18n("\tNo items in call stack.\n")); + else + xsldbgGenericErrorFunc("\n"); + } + } else { + long templateDepth = atol((char *) arg); + + + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + /* should never happen but just in case, when running as a + * thread always provide NO params to the where command */ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Notification of a frame not supported\n"); +#endif + result = 0; + return result; + } + + if (templateDepth >= 0) { + callPointItem = callStackGet(templateDepth + 1); + if (callPointItem && callPointItem->info) { + /* display information about the current XSLT template */ + xsldbgGenericErrorFunc(i18n("#%1 template: \"%2\"").arg(templateDepth).arg(xsldbgText(callPointItem->info->templateName))); + /* should alays be present but .. */ + if (callPointItem->info->url) + /* display where we are in the source/document file */ + xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2\n").arg(xsldbgUrl(callPointItem->info->url)).arg(callPointItem->lineNo)); + else + xsldbgGenericErrorFunc("\n"); + } else { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Call stack item not found at templateDepth %d : xslDbgPrintCallStack\n", depth); +#endif + result = 0; + } + } + } + return result; +} + + +/** + * xslDbgSleep: + * @delay : the number of microseconds to delay exection by + * + * Delay execution by a specified number of microseconds. On some system + * this will not be at all accurate. + */ +void +xslDbgSleep(long delay) +{ +#ifdef HAVE_USLEEP + usleep(delay); +#else +#ifdef WIN32 + Sleep(delay / 1000); +#else + /* try to delay things by doing a lot of floating point + * multiplication + */ + long loop1, loop2; + float f1 = 1.0000001, f2; + + for (loop1 = 0; loop1 < 100000 * delay; loop1++) + for (loop2 = 0; loop2 < 100000; loop2++) { + f2 = f1 * f1; + } +#endif +#endif +} + + +/** + * xslDbgWalkContinue: + * + * Delay execution for time as indicated by OPTION_WALK_SPEED + * Can only be called from within shellPrompt! + * OPTION_WALK_SPEED != WALKSPEED_STOP + * + * Returns 1 if walk is to continue, + * 0 otherwise + */ +int +xslDbgWalkContinue(void) +{ + int result = 0, speed = optionsGetIntOption(OPTIONS_WALK_SPEED); + + /* We need to ensure that output is realy sent. Otherwise + * walking using xemacs under WIN32 will not work */ + fflush(stderr); + + switch (speed) { + case WALKSPEED_1: + case WALKSPEED_2: + case WALKSPEED_3: + case WALKSPEED_4: + case WALKSPEED_5: + case WALKSPEED_6: + case WALKSPEED_7: + case WALKSPEED_8: + case WALKSPEED_9: + /* see options.h for defintion of WALKDAY */ + xslDbgSleep(speed * WALKDELAY); + result = 1; + break; + + default: /* stop walking */ + optionsSetIntOption(OPTIONS_WALK_SPEED, WALKSPEED_STOP); + xslDebugStatus = DEBUG_STOP; + break; + } + + return result; +} + + +/** + * addBreakPointNode: + * @payload : valid breakPointPtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addBreakPointNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = searchBreakPointNode((breakPointPtr) payload); + + searchAdd(node); +} + + +/** + * addSourceNode: + * @payload : valid xsltStylesheetPtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addSourceNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = searchSourceNode((xsltStylesheetPtr) payload); + + searchAdd(node); +} + + +/** + * addTemplateNode: + * @payload : valid xsltTemplatePtr + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addTemplateNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = + searchTemplateNode(((xsltTemplatePtr) payload)->elem); + searchAdd(node); +} + + +/** + * addGlobalNode: + * @payload : valid xmlNodePtr of global variable + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addGlobalNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = searchGlobalNode((xmlNodePtr) payload); + + searchAdd(node); +} + + +/** + * addLocalNode: + * @payload : valid xmlNodePtr of local variable + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addLocalNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = searchLocalNode((xmlNodePtr) payload); + + searchAdd(node); +} + + +/** + * addIncludeNode: + * @payload : valid xmlNodePtr of include instuction + * @data : not used + * @name : not used + * + * Convert payload into format needed, and add to search dataBase + */ +void +addIncludeNode(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = searchIncludeNode((xmlNodePtr) payload); + + searchAdd(node); +} + + +/** + * addCallStackItems: + * + * Convert call stack items into format needed, and add to search dataBase + */ +void +addCallStackItems(void) +{ + callPointPtr item; + xmlNodePtr node; + int depth; + + for (depth = callStackGetDepth(); depth > 0; depth--) { + item = callStackGet(depth); + if (item) { + node = searchCallStackNode(item); + if (node) + searchAdd(node); + } + } +} + + +/** + * updateSearchData: + * @styleCtxt: Not used + * @style: Is valid + * @data: Not used but MUST be NULL for the moment + * @variableTypes: What types of variables to look + * + * Update the searchDatabase + * + * Returns 1 on success, + * 0 otherwise + */ +int +updateSearchData(xsltTransformContextPtr styleCtxt, + xsltStylesheetPtr style, + void *data, VariableTypeEnum variableTypes) +{ + Q_UNUSED(styleCtxt); + Q_UNUSED(variableTypes); + int result = 0; + + if (!style) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to update search database no stylesheet loaded\n"); +#endif + return result; + } + searchEmpty(); + xsldbgGenericErrorFunc(i18n("Information: Updating search database. This may take a while...\n")); + /* add items to the search dataBase */ + addCallStackItems(); + xsldbgGenericErrorFunc(i18n("Information: Looking for breakpoints.\n")); + walkBreakPoints((xmlHashScanner) addBreakPointNode, data); + xsldbgGenericErrorFunc(i18n("Information: Looking for imports and top-level stylesheets.\n")); + walkStylesheets((xmlHashScanner) addSourceNode, data, style); + xsldbgGenericErrorFunc(i18n("Information: Looking for xsl:includes.\n")); + walkIncludeInst((xmlHashScanner) addIncludeNode, data, style); + xsldbgGenericErrorFunc(i18n("Information: Looking for templates.\n")); + walkTemplates((xmlHashScanner) addTemplateNode, data, style); + xsldbgGenericErrorFunc(i18n("Information: Looking for global variables.\n")); + walkGlobals((xmlHashScanner) addGlobalNode, data, style); + xsldbgGenericErrorFunc(i18n("Information: Looking for local variables.\n")); + walkLocals((xmlHashScanner) addLocalNode, data, style); + xsldbgGenericErrorFunc(i18n("Information: Formatting output.\n")); + + result = searchSave(NULL); + return result; +} + + +/** + * debugXSLBreak: + * @templ: The source node being executed + * @node: The data node being processed + * @root: The template being applied to "node" + * @ctxt: The transform context for stylesheet being processed + * + * A break point has been found so pass control to user + */ +void +debugXSLBreak(xmlNodePtr templ, xmlNodePtr node, xsltTemplatePtr root, + xsltTransformContextPtr ctxt) +{ + xmlDocPtr tempDoc = NULL; + xmlNodePtr tempNode = NULL; + rootCopy = root; + static const xmlChar *lastTemplate = NULL; + xmlBufferPtr buffer = xmlBufferCreate(); + static char mybuff[6] = " 0\n\x0"; + + if (ctxt && templ && root && !xsldbgReachedFirstTemplate) + xsldbgReachedFirstTemplate = true; + + if (templ == NULL) { + tempDoc = xmlNewDoc((xmlChar *) "1.0"); + if (!tempDoc) + return; + tempNode = xmlNewNode(NULL, (xmlChar *) "xsldbg_default_node"); + if (!tempNode) { + xmlFreeDoc(tempDoc); + return; + } + xmlAddChild((xmlNodePtr) tempDoc, tempNode); + templ = tempNode; + } + + if (node == NULL) + node = (xmlNodePtr) filesGetMainDoc(); + + if (node == NULL) { + tempDoc = xmlNewDoc((xmlChar *) "1.0"); + if (!tempDoc) + return; + tempNode = xmlNewNode(NULL, (xmlChar *) "xsldbg_default_node"); + if (!tempNode) { + xmlFreeDoc(tempDoc); + return; + } + xmlAddChild((xmlNodePtr) tempDoc, tempNode); + node = tempNode; + } + if (root) { + xmlChar *nameTemp = NULL, *modeTemp = NULL; + nameTemp = fullQName(root->nameURI, root->name); + modeTemp = fullQName(root->modeURI, root->mode); + if (!nextCommandActive){ + /* we only want messages if we are not + in the process of completing the next command */ + if (terminalIO == NULL) { + + if (root->match){ + xsldbgGenericErrorFunc(i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(root->match)).arg(xsldbgText(modeTemp))); + if (lastTemplate != root->match && buffer){ + xmlBufferCCat(buffer, "\nreached matched template:"); + xmlBufferCat(buffer, root->match); + xmlBufferCCat(buffer, mybuff); + xsltCopyTextString(ctxt, ctxt->insert,xmlBufferContent(buffer),0); + mybuff[1]++; + lastTemplate = root->match; + } + }else{ + xsldbgGenericErrorFunc(i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp))); + if (lastTemplate != root->name && buffer){ + xmlBufferCCat(buffer, "\nreached named template:"); + xmlBufferCat(buffer,root->match); + xmlBufferCCat(buffer,mybuff); + xsltCopyTextString(ctxt, ctxt->insert,xmlBufferContent(buffer),0); + mybuff[1]++; + lastTemplate = root->name; + } + + } + if (buffer) + xmlBufferFree(buffer); + } else { + if ((xslDebugStatus == DEBUG_TRACE) || + (xslDebugStatus == DEBUG_WALK)) { + QString message; + if (root->match) + message = i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(root->match)).arg(xsldbgText(modeTemp)); + else + message = i18n("\nReached template: \"%1\" mode: \"%2\"\n").arg(xsldbgText(nameTemp)).arg(xsldbgText(modeTemp)); + fprintf(terminalIO, "%s", message.local8Bit().data()); + } + } + } + if (nameTemp) + xmlFree(nameTemp); + if (modeTemp) + xmlFree(modeTemp); + } + + shellPrompt(templ, node, (xmlChar *) "index.xsl", + (xmlShellReadlineFunc) xslDbgShellReadline, stdout, ctxt); + if (tempDoc) + xmlFreeDoc(tempDoc); +} + + +/* Highly modified function based on xmlShell */ + +/** + * shellPrompt: + * @source: The current stylesheet instruction being executed + * @doc: The current document node being processed + * @filename: Not used + * @input: The function to call to when reading commands from stdio + * @output: Where to put the results + * @styleCtxt: Is valid + * + * Present to the user the xsldbg shell + */ +void +shellPrompt(xmlNodePtr source, xmlNodePtr doc, xmlChar * filename, + xmlShellReadlineFunc input, FILE * output, + xsltTransformContextPtr styleCtxt) +{ + xmlChar prompt[DEBUG_BUFFER_SIZE] = "/ > "; + xmlChar *cmdline = NULL, *cur; + int nbargs = 0; + int loadedFiles = 0; + int commandId = -1; /* stores what was the last + * command id entered by user */ + xmlChar command[DEBUG_BUFFER_SIZE]; /* holds the command user entered */ + xmlChar arg[DEBUG_BUFFER_SIZE]; /* holds any extra arguments to + * command entered */ + xmlChar dir[DEBUG_BUFFER_SIZE]; /* temporary buffer used by where + * and pwd commands */ + int cmdResult; /* result of last command */ + int shortCutId = -1; /* used by cd command */ + int i; + static int showSource = 1; /* Do we first show source or data ? */ + xmlChar *baseUri = NULL; /* for used for included xml entities */ + const xmlChar *breakUri; + + /* for convenience keep track of which node was last + * selected of source and doc */ + xmlNodePtr lastSourceNode, lastDocNode; + + + xmlShellCtxtPtr ctxt; + int exitShell = 0; /* Indicate when to exit xslShell */ + + if (source == NULL){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Source NULL in shellPrompt\n"); +#endif + return; + } + if (doc == NULL){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: doc NULL in shellPrompt\n"); +#endif + return; + } + if (filename == NULL){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: fileName NULL in shellPrompt\n"); +#endif + return; + } + if (input == NULL){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Input function NULL in shellPrompt\n"); +#endif + return; + } + if (output == NULL){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Output NULL in shellPrompt\n"); +#endif + return; + } + ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt)); + if (ctxt == NULL){ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + return; + } + + /* flag that we've received control */ + debugGotControl(1); + ctxt->loaded = 0; + lastSourceNode = source; + lastDocNode = doc; + /* show the doc or source first? */ + if (showSource) { + ctxt->doc = source->doc; + ctxt->node = source; + xsldbgUpdateFileDetails(source); + } else { + ctxt->doc = doc->doc; + ctxt->node = (xmlNodePtr) doc; + xsldbgUpdateFileDetails((xmlNodePtr) doc); + } + + ctxt->input = input; + ctxt->output = output; + ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); + + + if (xsldbgStop == 1){ + xslDebugStatus = DEBUG_STOP; + optionsSetIntOption(OPTIONS_TRACE, TRACE_OFF); + optionsSetIntOption(OPTIONS_WALK_SPEED, WALKSPEED_STOP); + xsldbgStop = 0; + } + + /* let any listener know that we got to a new line */ + if (xslDebugStatus != DEBUG_TRACE) { + /* don't send notify message if we are tracing stylesheet */ + int breakpoint = 1; + + notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, &breakpoint); + } + + + /* If using a thread and the thread is running then we don't need to + * send this as the application will see the XSLDBG_MSG_LINE_CHANGED message */ + if ((getThreadStatus() == XSLDBG_MSG_THREAD_NOTUSED) || + (xslDebugStatus == DEBUG_TRACE)) { + QString messageTxt; + if (!nextCommandActive && ctxt->node && ctxt->node && ctxt->node->doc + && ctxt->node->doc->URL) { + if (!showSource) { + baseUri = filesGetBaseUri(ctxt->node); + if (baseUri != NULL) + breakUri = baseUri; + else + breakUri = ctxt->node->doc->URL; + } else + breakUri = ctxt->node->doc->URL; + + if (xmlGetLineNo(ctxt->node) != -1) + messageTxt = i18n("Breakpoint for file \"%1\" at line %2.\n").arg(xsldbgUrl(breakUri)).arg(xmlGetLineNo(ctxt->node)); + else + messageTxt = i18n("Breakpoint at text node in file \"%1\".\n").arg(xsldbgUrl(breakUri)); + if (baseUri != NULL) { + xmlFree(baseUri); + baseUri = NULL; + } + + if (((xslDebugStatus == DEBUG_TRACE) || + (xslDebugStatus == DEBUG_WALK)) && (terminalIO != NULL)) + fprintf(terminalIO, "%s", messageTxt.utf8().data()); + else + xsldbgGenericErrorFunc(messageTxt); + + } + } + if ((showWatchesActive && (xslDebugStatus == DEBUG_TRACE)) || + (xslDebugStatus == DEBUG_WALK)){ + ctxt->pctxt = xmlXPathNewContext(ctxt->doc); + if (ctxt->pctxt) { + xslDbgShellShowWatches(styleCtxt, ctxt, 0); + xsldbgGenericErrorFunc("\n"); + xmlXPathFreeContext(ctxt->pctxt); + ctxt->pctxt = NULL; + } + } + + if (xslDebugStatus == DEBUG_TRACE) { + if (ctxt->filename) + xmlFree(ctxt->filename); + xmlFree(ctxt); + return; /* All done. Trace next instruction/node */ + } + if (xslDebugStatus == DEBUG_WALK) { + if (xslDbgWalkContinue()) { + if (ctxt->filename) + xmlFree(ctxt->filename); + xmlFree(ctxt); + return; /* All done. Walk to next instruction/node */ + } + } + + ctxt->pctxt = xmlXPathNewContext(ctxt->doc); + if (ctxt->pctxt == NULL) { + xmlFree(ctxt); + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + return; + } + + if (showWatchesActive){ + xslDbgShellShowWatches(styleCtxt, ctxt, 0); + xsldbgGenericErrorFunc("\n"); + } + + while (!exitShell && (xslDebugStatus != DEBUG_QUIT)) { + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) { + if (ctxt->node == (xmlNodePtr) ctxt->doc) + snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1, + "(xsldbg) %s > ", "/"); + else if ((ctxt->node->name) && (ctxt->node->ns)) + snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1, + "(xsldbg) %s:%s > ", ctxt->node->ns->prefix, + ctxt->node->name); + else if (ctxt->node->name) + snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1, + "(xsldbg) %s > ", ctxt->node->name); + + else + snprintf((char *) prompt, DEBUG_BUFFER_SIZE - 1, + "(xsldbg) ? > "); + + prompt[sizeof(prompt) - 1] = 0; + + /* + * Get a new command line + */ + if (nextCommandActive && (xslDebugStatus == DEBUG_STEP)) + /* we are processing the "next command" do the next + part of the command which is the up command */ + cmdline = xmlStrdup((xmlChar*)"up"); + else + cmdline = (xmlChar *) ctxt->input((char *) prompt); + if (cmdline && (optionsGetIntOption(OPTIONS_UTF8_INPUT) == 0)) { + /* we are getting encoded characters from the command line + * so decode them into UTF-8 */ + xmlChar *tempResult = filesDecode(cmdline); + + if (tempResult) { + xmlFree(cmdline); + cmdline = tempResult; + } + } + } else { + /* don't need a prompt for running as when running as a thread */ + xmlStrCpy(messageBuffer, ""); + if (nextCommandActive && (xslDebugStatus == DEBUG_STEP)) + /* we are processing the "next command" do the next + part of the command which is the up command */ + cmdline = xmlStrdup((xmlChar*)"up"); + else + cmdline = (xmlChar *) ctxt->input((char *) messageBuffer); + } + + if (cmdline == NULL) + break; + + /* don't allow next command to be active more than at one breakpoint */ + if (nextCommandActive) + nextCommandActive = 0; + + notifyXsldbgApp(XSLDBG_MSG_PROCESSING_INPUT, NULL); + + /* remove leading/trailing blanks */ + trimString(cmdline); + + /* + * Parse the command itself + */ + cur = cmdline; + nbargs = 0; + while ((*cur == ' ') || (*cur == '\t')) + cur++; + i = 0; + while ((*cur != ' ') && (*cur != '\t') && + (*cur != '\n') && (*cur != '\r')) { + if (*cur == 0) + break; + command[i++] = *cur++; + } + command[i] = 0; + if (i == 0) + continue; + nbargs++; + + /* + * Parse the argument + */ + while ((*cur == ' ') || (*cur == '\t')) + cur++; + i = 0; + while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { + if (*cur == 0) + break; + arg[i++] = *cur++; + } + arg[i] = 0; + if (i != 0) + nbargs++; + + + commandId = lookupName(command, (xmlChar **) commandNames); + /* try command shorts if command is not found */ + if (commandId < 0) + commandId = + lookupName(command, (xmlChar **) shortCommandNames); + + cmdResult = -1; /* flag that it contains no result */ + /* + * start interpreting the command + */ + switch (commandId + DEBUG_HELP_CMD) { + /* --- Help related commands --- */ + case DEBUG_HELP_CMD: + cmdResult = helpTop(arg); + if (!cmdResult) + xsldbgGenericErrorFunc(i18n("Unable to print local help. Online help can be found at http://xsldbg.sourceforge.net/docs/index.html.\n")); + break; + + + /* --- Running related commands --- */ + case DEBUG_BYE_CMD: + case DEBUG_EXIT_CMD: + case DEBUG_QUIT_CMD: + /* allow the stylesheet to exit */ + xslDebugStatus = DEBUG_QUIT; + exitShell++; + cmdResult = 1; + break; + + case DEBUG_NEXT_CMD: + xslDebugStatus = DEBUG_STEP; + exitShell++; + cmdResult = 1; + /* Do the the next part of this command + which is the up command */ + nextCommandActive = 1; + break; + + case DEBUG_STEP_CMD: + xslDebugStatus = DEBUG_STEP; + exitShell++; + cmdResult = 1; + break; + + case DEBUG_STEPUP_CMD: + { + xmlChar *noOfFrames = arg; + + /* skip until next space character */ + while (*noOfFrames && (*noOfFrames != ' ')) { + noOfFrames++; + } + cmdResult = xslDbgShellFrameBreak(noOfFrames, 1); + exitShell++; + } + break; + + case DEBUG_STEPDOWN_CMD: + { + xmlChar *noOfFrames = arg; + + /* skip until next space character */ + while (*noOfFrames && (*noOfFrames != ' ')) { + noOfFrames++; + } + cmdResult = xslDbgShellFrameBreak(noOfFrames, 0); + exitShell++; + } + break; + + /* continue to next break point */ + case DEBUG_CONT_CMD: + xslDebugStatus = DEBUG_CONT; + exitShell++; + cmdResult = 1; + break; + + /* restart */ + case DEBUG_RUN_CMD: + xslDebugStatus = DEBUG_RUN_RESTART; + exitShell++; + cmdResult = 1; + break; + + + /* --- Template related commands --- */ + case DEBUG_TEMPLATES_CMD: + { + int allFiles = 1, verbose = 1; + + if (xmlStrLen(arg) && (xmlStrCmp(arg, "this") == 0)) { + allFiles = 0; + } + + /* be verbose when printing template names */ + /* if args is not empty then print names this stylesheet */ + cmdResult = + xslDbgShellPrintTemplateNames(styleCtxt, ctxt, arg, + verbose, allFiles); + break; + } + + + case DEBUG_WHERE_CMD: + /* Print the current working directory as well */ + xslDbgPrintCallStack(NULL); + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) { + if (!xmlShellPwd(ctxt, (char *) dir, ctxt->node, NULL)){ + xsldbgGenericErrorFunc((const char*)dir); + xsldbgGenericErrorFunc("\n"); + } + } + cmdResult = 1; + + break; + + case DEBUG_FRAME_CMD: + cmdResult = xslDbgPrintCallStack(arg); + break; + + case DEBUG_STYLESHEETS_CMD: + cmdResult = xslDbgShellPrintStyleSheets(arg); + break; + + /* --- Break point related commands --- */ + case DEBUG_BREAK_CMD: + if (xmlStrLen(arg)) { + if (styleCtxt) + cmdResult = + xslDbgShellBreak(arg, styleCtxt->style, + styleCtxt); + else + cmdResult = xslDbgShellBreak(arg, NULL, styleCtxt); + } else { + /* select current node to break at */ + xmlChar buff[100]; + xmlChar *tempBaseName = filesGetBaseUri(ctxt->node); + if (tempBaseName){ + snprintf((char *) buff, sizeof(buff), "-l %s %ld", + tempBaseName, + xmlGetLineNo(ctxt->node)); + xmlFree(tempBaseName); + } + if (styleCtxt) + cmdResult = + xslDbgShellBreak(buff, styleCtxt->style, + styleCtxt); + else + cmdResult = + xslDbgShellBreak(buff, NULL, styleCtxt); + } + + break; + + case DEBUG_SHOWBREAK_CMD: + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_BREAKPOINT_CHANGED); + walkBreakPoints((xmlHashScanner) + xslDbgShellPrintBreakPoint, NULL); + notifyListSend(); + } else { + xsldbgGenericErrorFunc("\n"); + printCount = 0; /* printCount will get updated by + * xslDbgShellPrintBreakPoint */ + + walkBreakPoints((xmlHashScanner) + xslDbgShellPrintBreakPoint, NULL); + if (printCount == 0) + xsldbgGenericErrorFunc(i18n("\nNo breakpoints are set for the file.\n")); + else + xsldbgGenericErrorFunc(i18n("\tTotal of %n breakpoint present.","\tTotal of %n breakpoints present.", printCount) + QString("\n")); + } + cmdResult = 1; + break; + + case DEBUG_DELETE_CMD: + if (xmlStrLen(arg)) + cmdResult = xslDbgShellDelete((xmlChar *) arg); + else { + breakPointPtr breakPtr = NULL; + xmlChar* tempBaseName = filesGetBaseUri(ctxt->node); + + if (tempBaseName){ + breakPtr = + breakPointGet(tempBaseName, + xmlGetLineNo(ctxt->node)); + xmlFree(tempBaseName); + } + if (!breakPtr || !breakPointDelete(breakPtr)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to delete breakpoint.\n")); + cmdResult = 0; + } + } + break; + + case DEBUG_ENABLE_CMD: + if (xmlStrLen(arg)) + cmdResult = + xslDbgShellEnable(arg, XSL_TOGGLE_BREAKPOINT); + else { + breakPointPtr breakPtr = NULL; + xmlChar * tempBaseName = filesGetBaseUri(ctxt->node); + + if (tempBaseName){ + breakPtr = + breakPointGet(tempBaseName, + xmlGetLineNo(ctxt->node)); + xmlFree(tempBaseName); + } + if (!breakPtr || + (!breakPointEnable(breakPtr, !(breakPtr->flags & BREAKPOINT_ENABLED)))) { + xsldbgGenericErrorFunc(i18n("Error: Unable to enable/disable breakpoint.\n")); + cmdResult = 0; + } + } + break; + + case DEBUG_DISABLE_CMD: + if (xmlStrLen(arg)) + cmdResult = xslDbgShellEnable(arg, 0); + else { + breakPointPtr breakPtr = NULL; + xmlChar *tempBaseName = filesGetBaseUri(ctxt->node); + + if (tempBaseName){ + breakPtr = + breakPointGet(tempBaseName, + xmlGetLineNo(ctxt->node)); + xmlFree(tempBaseName); + } + if (!breakPtr || !breakPointEnable(breakPtr, 0)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to enable/disable breakpoint.\n")); + cmdResult = 0; + } + } + break; + + + + /* --- Node view related commands --- */ + case DEBUG_LS_CMD: + cmdResult = xslDbgShellPrintList(ctxt, arg, 0); + break; + + case DEBUG_DIR_CMD: + cmdResult = xslDbgShellPrintList(ctxt, arg, 1); + break; + + case DEBUG_DU_CMD: + xmlShellDu(ctxt, NULL, ctxt->node, NULL); + cmdResult = 1; + break; + + case DEBUG_CAT_CMD: + case DEBUG_PRINT_CMD: + cmdResult = xslDbgShellCat(styleCtxt, ctxt, arg); + break; + + case DEBUG_PWD_CMD: + if (!xmlShellPwd(ctxt, (char *) dir, ctxt->node, NULL)) { + xmlChar* tempBaseName = filesGetBaseUri(ctxt->node); + if(tempBaseName){ + xsldbgGenericErrorFunc("\n"); + xsldbgGenericErrorFunc((char*)dir); + xsldbgGenericErrorFunc(i18n(" in file \"%1\" at line %2").arg(xsldbgUrl(tempBaseName)).arg(xmlGetLineNo(ctxt->node))); + xmlFree(tempBaseName); + cmdResult = 1; + } + } + if (cmdResult) + xsldbgGenericErrorFunc("\n"); + else + xsldbgGenericErrorFunc(i18n("Error: Unable to print working directory.\n")); + break; + + case DEBUG_DUMP_CMD: + xmlDebugDumpDocument(stdout, ctxt->doc); + cmdResult = 1; + break; + + case DEBUG_BASE_CMD: + xmlShellBase(ctxt, NULL, ctxt->node, NULL); + cmdResult = 1; + break; + + + /* --- Variable related commands --- */ + case DEBUG_GLOBALS_CMD: + if (loadedFiles == 0) + cmdResult = xslDbgShellPrintVariable(styleCtxt, arg, + DEBUG_GLOBAL_VAR); + else { + xsldbgGenericErrorFunc(i18n("Error: Need to use the run command first.\n")); + cmdResult = 0; + } + break; + + case DEBUG_LOCALS_CMD: + if (loadedFiles == 0) + /* if gdb compatability mode is enable print the globals then + * the locals */ + if (optionsGetIntOption(OPTIONS_GDB) == 1) { + cmdResult = + xslDbgShellPrintVariable(styleCtxt, arg, + DEBUG_GLOBAL_VAR); + if (cmdResult == 1) + cmdResult = + xslDbgShellPrintVariable(styleCtxt, arg, + DEBUG_LOCAL_VAR); + } else + cmdResult = + xslDbgShellPrintVariable(styleCtxt, arg, + DEBUG_LOCAL_VAR); + else { + xsldbgGenericErrorFunc(i18n("Error: Need to use the run command first.\n")); + cmdResult = 0; + } + break; + + + /* It's difficult to put the following commands into + * a separe file so they stay here! */ + /* --- Node selection related commands --- */ + case DEBUG_SOURCE_CMD: + cmdResult = 1; /* only one case where this will command fail */ + xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION; + if (xmlStrLen(arg) == 0) { + if (ctxt->doc == doc->doc) + lastDocNode = ctxt->node; + ctxt->doc = source->doc; + ctxt->node = lastSourceNode; + if (ctxt->pctxt) + xmlXPathFreeContext(ctxt->pctxt); + ctxt->pctxt = xmlXPathNewContext(ctxt->doc); + showSource = 1; + xsldbgUpdateFileDetails((xmlNodePtr) ctxt->node); + /* let any listener know that we got to a new line */ + notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, NULL); + if (ctxt->pctxt == NULL) { + xmlFree(ctxt); + xslDebugStatus = DEBUG_QUIT; + return; + } else + break; + } else { + /* load new stylesheet file, actual loading happens later */ + xmlChar *expandedName = filesExpandName(arg); + + if (expandedName) { + xsldbgGenericErrorFunc(i18n("Load of source deferred. Use the run command.\n")); + + optionsSetStringOption(OPTIONS_SOURCE_FILE_NAME, + expandedName); + notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L); + loadedFiles = 1; + xmlFree(expandedName); + cmdResult = 1; + } else { + cmdResult = 0; + } + } + break; + + case DEBUG_DATA_CMD: + cmdResult = 1; /* only one case where this will command fail */ + xsldbgValidateBreakpoints = BREAKPOINTS_NEED_VALIDATION; + if (xmlStrLen(arg) == 0) { + if (ctxt->doc == source->doc) + lastSourceNode = ctxt->node; + ctxt->doc = doc->doc; + ctxt->node = lastDocNode; + if (ctxt->pctxt) + xmlXPathFreeContext(ctxt->pctxt); + ctxt->pctxt = xmlXPathNewContext(ctxt->doc); + showSource = 0; + xsldbgUpdateFileDetails((xmlNodePtr) ctxt->node); + /* let any listener know that we got to a new line */ + notifyXsldbgApp(XSLDBG_MSG_LINE_CHANGED, NULL); + if (ctxt->pctxt == NULL) { + xmlFree(ctxt); + xslDebugStatus = DEBUG_QUIT; + return; + } else + break; + } else { + /* load new xml file actual loading hapens later */ + xmlChar *expandedName = filesExpandName(arg); + + if (expandedName) { + xsldbgGenericErrorFunc(i18n("Load of data file deferred. Use the run command.\n")); + + optionsSetStringOption(OPTIONS_DATA_FILE_NAME, + expandedName); + notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L); + loadedFiles = 1; + xmlFree(expandedName); + cmdResult = 1; + } else { + cmdResult = 0; + } + } + break; + + case DEBUG_OUTPUT_CMD: + /* set the output file name to use */ + cmdResult = xslDbgShellOutput(arg); + break; + + case DEBUG_CD_CMD: + /* use dir as a working buffer */ + xmlStrnCpy(dir, arg, 2); + dir[2] = '\0'; + shortCutId = lookupName(dir, (xmlChar **) cdShortCuts); + if (shortCutId >= 0) { + if (xmlStrLen(arg) == 2) { + cmdResult = xslDbgCd(styleCtxt, ctxt, (xmlChar *) + cdAlternative[shortCutId], + source); + } else { + + xmlStrCpy(dir, cdAlternative[shortCutId]); + xmlStrCat(dir, &arg[2]); + cmdResult = xslDbgCd(styleCtxt, ctxt, dir, source); + } + + } else + cmdResult = xslDbgCd(styleCtxt, ctxt, arg, source); + break; + + + /* --- File related commands --- */ + case DEBUG_ENTITIES_CMD: + cmdResult = xslDbgEntities(); + break; + + case DEBUG_SYSTEM_CMD: + /* strip off a single argument. I need to do it this + way because I've already public this API */ + { + xmlChar *systemID; + if (splitString(arg, 1, &systemID) == 1){ + cmdResult = xslDbgSystem(systemID); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("system")); + } + } + break; + + case DEBUG_PUBLIC_CMD: + /* strip off a single argument. I need to do it this + way because I've already public this API */ + { + xmlChar *publicID; + if (splitString(arg, 1, &publicID) == 1){ + cmdResult = xslDbgPublic(publicID); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("public")); + } + } + break; + + case DEBUG_ENCODING_CMD: + cmdResult = xslDbgEncoding(arg); + break; + + case DEBUG_VALIDATE_CMD: + xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("validate")); + cmdResult = 0; + /* + * xmlShellValidate(ctxt, arg, NULL, NULL); + */ + break; + + case DEBUG_LOAD_CMD: + cmdResult = optionsLoad(); + /* restart xsldbg and activate new configuration */ + if (cmdResult == 1) { + xslDebugStatus = DEBUG_RUN_RESTART; + exitShell++; + } + break; + + case DEBUG_SAVE_CMD: + cmdResult = optionsSave(); + break; + + case DEBUG_WRITE_CMD: + xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("write")); + cmdResult = 0; + /* + * xmlShellWrite(ctxt, arg, NULL, NULL); + */ + break; + + case DEBUG_FREE_CMD: + xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled.\n").arg("free")); + cmdResult = 0; + /* + * if (arg[0] == 0) { + * xmlMemShow(stdout, 0); + * } else { + * int len = 0; + * sscanf(arg, "%d", &len); + * xmlMemShow(stdout, len); + * } + */ + break; + + + /* operating system related */ + case DEBUG_CHDIR_CMD: + cmdResult = xslDbgShellChangeWd(arg); + break; + + case DEBUG_SHELL_EXEC_CMD: + cmdResult = xslDbgShellExecute(arg, 1); + break; + + + /* libxslt parameter related commands */ + case DEBUG_ADDPARAM_CMD: + cmdResult = xslDbgShellAddParam(arg); + break; + + case DEBUG_DELPARAM_CMD: + cmdResult = xslDbgShellDelParam(arg); + break; + + case DEBUG_SHOWPARAM_CMD: + cmdResult = xslDbgShellShowParam(arg); + break; + + + + /* option related commmands */ + case DEBUG_SETOPTION_CMD: + cmdResult = xslDbgShellSetOption(arg); + break; + + case DEBUG_OPTIONS_CMD: + cmdResult = xslDbgShellOptions(); + break; + + + + /* misc commands */ + case DEBUG_TTY_CMD: + if (openTerminal(arg)) { + /* gdb does to say anything after redirecting its + output */ + if (optionsGetIntOption(OPTIONS_GDB) < 2) + xsldbgGenericErrorFunc(i18n("Opening terminal %1.\n").arg(xsldbgText(arg))); + cmdResult = 1; + } else + cmdResult = 0; + break; + + + /* language selection for messages */ + case DEBUG_LANG_CMD: +#ifdef LOCALE_PREFIX + if (xmlStrlen(arg) > 0){ + setlocale(LC_MESSAGES, (char*)arg); + textdomain("kdewebdev/xsldsbg"); + bindtextdomain("kdewebdev/xsldbg", LOCALE_PREFIX); + cmdResult = 1; + }else{ + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("lang")); + cmdResult = 0; + } +#else + xsldbgGenericErrorFunc(i18n("Warning: The %1 command is disabled\n").arg("lang")); + cmdResult = 1; +#endif + break; + + /* tracing related commands */ + case DEBUG_TRACE_CMD: + if (xslDbgShellTrace(arg)) { + exitShell++; + cmdResult = 1; + } else + cmdResult = 0; + + break; + + case DEBUG_WALK_CMD: + if (xslDbgShellWalk(arg)) { + exitShell++; + cmdResult = 1; + } else + cmdResult = 0; + break; + + case DEBUG_ADDWATCH_CMD: + cmdResult = xslDbgShellAddWatch(arg); + break; + + case DEBUG_DELWATCH_CMD: + cmdResult = xslDbgShellDeleteWatch(arg); + break; + + case DEBUG_SHOWWATCH_CMD: + trimString(arg); + switch (arg[0]){ + case '\0': + cmdResult = xslDbgShellShowWatches(styleCtxt, ctxt, 1); + break; + + case '0': + case '1': + showWatchesActive = arg[0] - '0'; + cmdResult = 1; + break; + + default: + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("showmatch")); + } + break; + + + /* search related commands */ + case DEBUG_SEARCH_CMD: + cmdResult = + xslDbgShellSearch(styleCtxt, filesGetStylesheet(), + arg); + break; + + + + case DEBUG_SET_CMD: + cmdResult = xslDbgShellSetVariable(styleCtxt, arg); + break; + + default: + xsldbgGenericErrorFunc(i18n("Error: Unknown command %1. Try help.\n").arg(xsldbgText(command))); + cmdResult = 0; + } + + /* KDbg likes to get the marker after every command so here it is */ + if ((optionsGetIntOption(OPTIONS_GDB) >1) && optionsGetIntOption(OPTIONS_VERBOSE) && !nextCommandActive + && (commandId != DEBUG_STEPUP_CMD - DEBUG_HELP_CMD)) { + if (ctxt->node && ctxt->node && + ctxt->node->doc && ctxt->node->doc->URL) { + + if (xmlGetLineNo(ctxt->node) != -1) + xsldbgGenericErrorFunc(i18n("Breakpoint for file \"%1\" at line %2.\n").arg(xsldbgUrl(ctxt->node->doc->URL)).arg(xmlGetLineNo(ctxt->node))); + else + xsldbgGenericErrorFunc(i18n("Breakpoint at text node in file \"%1\".\n").arg(xsldbgUrl(ctxt->node->doc->URL))); + } + } + + /* notify any listeners of that the command failed */ + if (cmdResult == 0 && (xmlStrlen(messageBuffer) > 0)) { + snprintf((char *) messageBuffer, sizeof(messageBuffer), + "\nRequest to xsldbg failed:%s\n", cmdline); + notifyTextXsldbgApp(XSLDBG_MSG_TEXTOUT, + (char *) messageBuffer); + } + + xmlFree(cmdline); + cmdline = NULL; + } + + xmlXPathFreeContext(ctxt->pctxt); + + if (ctxt->filename) + xmlFree(ctxt->filename); + + xmlFree(ctxt); + + if (cmdline) + xmlFree(cmdline); +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.h b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.h new file mode 100644 index 00000000..df50a53b --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/debugXSL.h @@ -0,0 +1,1078 @@ + +/************************************************************************** + debugXSL.h - describes the core xsldbg shell functions + ------------------- + begin : Sun Sep 16 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + +/* + * Orinal file : debugXML.h : This is a set of routines used for + * debugging the tree produced by the XML parser. + * + * New file : debugXSL.h : Debug support version + * + * See Copyright for the status of this software. + * + * Daniel Veillard <daniel@veillard.com> + * + * Permission abtained to modify the LGPL'd code and extend to include + * break points, inspections of stylesheet source, xml data, stylesheet + * variables Keith Isdale <k_isdale@tpg.com.au> + */ + +#ifndef __DEBUG_XSL__ +#define __DEBUG_XSL__ + +#ifdef USE_XSLDBG_AS_THREAD +#include "xsldbgmsg.h" +#include "xsldbgthread.h" +#endif + +/* We want skip most of these includes when building documentation*/ +#ifndef BUILD_DOCS +#include "utils.h" +#include "breakpoint.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_BUFFER_SIZE 500 /*used by xslDbgShell */ + +/* how may items have been printed */ + extern int printCount; + + /* used to indicated that xsldbg should stop tracing/walking + value : 1 stop tracing at start of next cycle + value : 0 normal operation + */ + + extern int xsldbgStop; + extern int xsldbgValidateBreakpoints; + /* Some versions of libxml/libxslt need a different type of + line numbers handling */ + extern int xsldbgHasLineNumberFix; + extern bool xsldbgReachedFirstTemplate; + +/**************************************************************** + * * + * The XSL shell related structures and functions * + * * + ****************************************************************/ + +/* + Note that functions that have a prefix of xslDbgShell are NOT implemented + in debugXSL.c unless stated + + All functions with the prefix of debygXSL are implemented in debugXSL.c + + */ + +#ifdef USE_GNOME_DOCS + +/** + * debugXSLBreak: + * @templ: The source node being executed + * @node: The data node being processed + * @root: The template being applied to "node" + * @ctxt: The transform context for stylesheet being processed + * + * A break point has been found so pass control to user + */ +#else +#ifdef USE_KDE_DOCS + +/** + * A break point has been found so pass control to user + * + * @param templ The source node being executed + * @param node The data node being processed + * @param root The template being applied to "node" + * @param ctxt transform context for stylesheet being processed + */ +#endif +#endif + void debugXSLBreak(xmlNodePtr templ, xmlNodePtr node, + xsltTemplatePtr root, xsltTransformContextPtr ctxt); + + +#ifdef USE_GNOME_DOCS + +/** + * debugXSLGetTemplate: + * + * Get the last template node found, if any + * + * Returns The last template node found, if any + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Get the last template node found, if any + * + * @returns the last template node found, if any + */ +#endif +#endif + xsltTemplatePtr debugXSLGetTemplate(void); + + + +/* ----------------------------------------- + Break Point related commands + + They are implemented in breakpoint_cmds.c + ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellFrameBreak: + * @arg: Is valid number of frames to change location by + * @stepup: If != 1 then we step up, otherwise step down + * + * Set a "frame" break point either up or down from here + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set a "frame" break point either up or down from here + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg Is valid and in UTF-8 + * @param stepup If != 1 then we step up, otherwise step down + */ +#endif +#endif + int xslDbgShellFrameBreak(xmlChar * arg, int stepup); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellBreak: + * @arg: Is valid and in UTF-8 + * @style: Is valid + * @ctxt: Is valid + * + * Add break point specified by arg + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Add break point specified by arg + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg Is valid and in UTF-8 + * @param style Is valid + * @param ctxt Is valid + */ +#endif +#endif + int xslDbgShellBreak(xmlChar * arg, xsltStylesheetPtr style, + xsltTransformContextPtr ctxt); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellDelete: + * @arg: Is valid and in UTF-8 + * + * Delete break point specified by arg + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Delete break point specified by arg + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg Is valid and in UTF-8 + */ +#endif +#endif + int xslDbgShellDelete(xmlChar * arg); + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellEnableBreakPoint: + * @payload: A valid xslBreakPointPtr + * @data: Enable type, a pointer to an integer + * for a value of + * 1 enable break point + * 0 disable break point + * -1 toggle enabling of break point + * @name: Not used + * + * Enable/disable break points via use of scan of break points +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Enable/disable break points via use of scan of break points + * + * @param payload Is valid xslBreakPointPtr + * @param data Enable type, a pointer to an integer + * for a value of + * @li 1 enable break point + * @li 0 disable break point + * @li -1 toggle enabling of break point + * @param name Not used +*/ +#endif +#endif + void xslDbgShellEnableBreakPoint(void *payload, void *data, + xmlChar * name); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellEnable: + * @arg : is valid enable "commmand text" and in UTF-8 + * @enableType : enable break point if 1, disable if 0, toggle if -1 + * + * Enable/disable break point specified by arg using enable + * type of @enableType + * Returns 1 if successful, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Enable/disable break point specified by arg using enable + * + * @param arg: is valid enable "commmand text" and in UTF-8 + * @param enableType : enable break point if 1, disable if 0, toggle if -1 + * + * @returns 1 if successful, + * 0 otherwise + */ +#endif +#endif + int xslDbgShellEnable(xmlChar * arg, int enableType); + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellPrintBreakPoint: + * @payload: A valid xslBreakPointPtr + * @data: Not used + * @name: Not used + * + * Print data given by scan of break points +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Print data given by scan of break points + * + * @param payload Is valid xslBreakPointPtr + * @param data Not used + * @param name Not used +*/ +#endif +#endif + void xslDbgShellPrintBreakPoint(void *payload, void *data, + xmlChar * name); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellValidateBreakPoint: + * @payload: A valid xslBreakPointPtr + * @data: Not used + * @name: Not used + * + * Print an warning if a breakpoint is invalid +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Print an warning if a breakpoint is invalid + * + * @param payload Is valid xslBreakPointPtr + * @param data Not used + * @param name Not used +*/ +#endif +#endif + void xslDbgShellValidateBreakPoint(void *payload, void *data, + xmlChar * name); + + +/* ----------------------------------------- + Template related commands + + They are implemented in template_cmds.c + ------------------------------------------- */ + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellPrintStyleSheets: + * @arg: The stylesheets of interests and in UTF-8, is NULL for all stylesheets + * + * Print stylesheets that can be found in loaded stylsheet + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print stylesheets that can be found in loaded stylsheet + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg The stylesheets of interests and in UTF-8, is NULL for all stylesheets + * + */ +#endif +#endif + int xslDbgShellPrintStyleSheets(xmlChar * arg); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellPrintTemplateNames: + * @styleCtxt: Is valid + * @ctxt: Not used + * @arg: Not used + * @verbose: If 1 then print extra messages about templates found, + * otherwise print normal messages only + * @allFiles: If 1 then look for all templates in stylsheets found in + * @styleCtxt + * otherwise look in the stylesheet found by + * debugXSLBreak function + * + * Print out the list of template names found that match critieria +* + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print out the list of template names found that match critieria + * + * @param styleCtxt Is valid + * @param ctxt Not used + * @param arg Not used + * @param verbose If 1 then print extra messages about templates found, + * otherwise print normal messages only + * @param allFiles If 1 then look for all templates in stylsheets found in + * @p styleCtxt + * otherwise look in the stylesheet found by + * debugXSLBreak function + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int xslDbgShellPrintTemplateNames(xsltTransformContextPtr styleCtxt, + xmlShellCtxtPtr ctxt, + xmlChar * arg, int verbose, + int allFiles); + + + + +/* ----------------------------------------- + + Node viewing related commands + + ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellPrintList: + * @ctxt: The current shell context + * @arg: What xpath to display and in UTF-8 + * @dir: If 1 print in dir mode?, + * otherwise ls mode + * + * Print list of nodes in either ls or dir format + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print list of nodes in either ls or dir format + * + * @returns 1 on success, + * 0 otherwise + * + * @param ctxt The current shell context + * @param arg What xpath to display and in UTF-8 + * @param dir If 1 print in dir mode, + * otherwise ls mode + */ +#endif +#endif + int xslDbgShellPrintList(xmlShellCtxtPtr ctxt, xmlChar * arg, int dir); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellCat: + * @styleCtxt: the current stylesheet context + * @ctxt: The current shell context + * @arg: The xpath to print and in UTF-8 + * + * Print the result of an xpath expression. This can include variables + * if styleCtxt is not NULL + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print the result of an xpath expression. This can include variables + * if styleCtxt is not NULL + * + * @returns 1 on success, + * 0 otherwise + * + * @param styleCtxt Current stylesheet context + * @param ctxt Current shell context + * @param arg The xpath to print and in UTF-8 + */ +#endif +#endif + int xslDbgShellCat(xsltTransformContextPtr styleCtxt, + xmlShellCtxtPtr ctxt, xmlChar * arg); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellPrintVariable: + * @styleCtxt: The current stylesheet context + * @arg: The name of variable to look for '$' prefix is optional and in UTF-8 + * @type: A valid VariableTypeEnum + * + * Print the value variable specified by args. + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print the value variable specified by args. + * + * @returns 1 on success, + * 0 otherwise + + * + * @param styleCtxt The current stylesheet context + * @param arg The name of variable to look for '$' prefix is optional and in UTF-8 + * @param type Is valid VariableTypeEnum + */ +#endif +#endif + int xslDbgShellPrintVariable(xsltTransformContextPtr styleCtxt, + xmlChar * arg, VariableTypeEnum type); + + +/* ----------------------------------------- + + File related command + + Implemented in file_cmds.c + ------------------------------------------- */ +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellOutput: + * @arg : Is valid, either a local file name which will be expanded + * if needed, or a "file://" protocol URI + * + * Set the output file name to use + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * xslDbgShellOutput: + * @arg : Is valid, either a local file name which will be expanded + * if needed, or a "file://" protocol URI + * + * Set the output file name to use + * + * Returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int xslDbgShellOutput(const xmlChar *arg); + + + + +#ifdef USE_GNOME_DOCS + + /** + * xslDbgEntities: + * + * Print list of entites found + * + * Returns 1 on sucess, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +#endif +#endif + int xslDbgEntities(void); + + +#ifdef USE_GNOME_DOCS + + /** + * xslDbgSystem: + * @arg : Is valid in UTF-8 + * + * Print what a system file @arg maps to via the current xml catalog + * + * Returns 1 on sucess, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Print what a system file @p arg maps to via the current xml catalog + * + * @param arg Is valid in UTF-8 + * + * @returns 1 on sucess, + * 0 otherwise + */ +#endif +#endif + int xslDbgSystem(const xmlChar * arg); + + +#ifdef USE_GNOME_DOCS + + /** + * xslDbgPublic: + * @arg : Is valid PublicID in UTF-8 + * + * Print what a public ID @arg maps to via the current xml catalog + * + * Returns 1 on sucess, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Print what a public ID @p arg maps to via the current xml catalog + * + * @param arg Is valid PublicID in UTF-8 + * + * @returns 1 on sucess, + * 0 otherwise + */ +#endif +#endif + int xslDbgPublic(const xmlChar * arg); + + +#ifdef USE_GNOME_DOCS + + /** + * xslDbgEncoding: + * @arg: Is valid encoding supported by libxml2 + * + * Set current encoding to use for output to standard output + * + * Returns 1 on sucess, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Set current encoding to use for output to standard output + * + * @param arg Is valid encoding supported by libxml2 + * + * + * Returns 1 on sucess, + */ +#endif +#endif + int xslDbgEncoding(xmlChar * arg); + +/* ----------------------------------------- + + Operating system related commands + + Implemented in os_cmds.c + ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellChangeWd: + * @path: The path to change to and in UTF-8 + * + * Change the current working directory of the operating system + * + * Returns 1 if able to change xsldbg's working directory to @path + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns 1 if able to change xsldbg working direcorty to @p path + * 0 otherwise + * + * @param path Operating system path(directory) to change to and in UTF-8 + */ +#endif +#endif + int xslDbgShellChangeWd(xmlChar * path); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellExecute: + * @name: The name of command string to be executed by operating system shell + * @verbose: If 1 then print extra debugging messages, + * normal messages otherwise + * + * Execute an operating system command + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns 1 if able to execute command @p name, + * 0 otherwise + * + * @param name The name of command string to be executed + * by operating system shell + * @param verbose If 1 then print extra debugging messages, + * normal messages otherwise + */ +#endif +#endif + int xslDbgShellExecute(xmlChar * name, int verbose); + + + + +/* ----------------------------------------- + + libxslt parameter related commands + + Implemented in param_cmds.c + ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellAddParam: + * @arg: A string comprised of two words separated by + * one or more spaces which are in UTF-8. + * + * Add a libxslt parameter to be sent to libxslt later on + * + * Returns 1 on success, + * 0 otherwise +*/ +#else +#ifdef USE_KDE_DOCS + +/* + * Add a parameter to be sent to libxslt later on + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg A string comprised of two words separated by + * one or more spaces which are in UTF-8 + */ +#endif +#endif + int xslDbgShellAddParam(xmlChar * arg); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellDelParam: + * @arg: A single white space trimmed parameter number to look for + * + * Delete a libxslt parameter that was to be sent to libxslt later on + * + * Returns 1 if able to delete parameter @name, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Delete a libxslt parameter that was to be sent to libxslt later on + * + * @returns 1 if able to delete parameter @p name, + * 0 otherwise + * + * @param arg A single white space trimmed libxslt parameter number to look for + */ +#endif +#endif + int xslDbgShellDelParam(xmlChar * arg); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellShowParam: + * @arg: Not used + * + * Print list of current paramters + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Print list of current paramters + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg Not used + */ +#endif +#endif + int xslDbgShellShowParam(xmlChar * arg); + + + /* ----------------------------------------- + * + * Option related commands + * + * Implemented in option_cmds.c + * + * ------------------------------------------- */ + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellSetOption: + * @arg: Is valid, and in the format <NAME> <VALUE> + * + * Set the value of an option + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Set the value of an option + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg is valid, and in format <NAME> <VALUE> + * + */ +#endif +#endif + int xslDbgShellSetOption(xmlChar * arg); + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellOptions: + * + * Prints out values for user options + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Prints out values for user options + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int xslDbgShellOptions(void); + + + /** + * xslDbgShellShowWatches: + * @styleCtxt: the current stylesheet context + * @ctxt: The current shell context + * @showWarnings : If 1 then showWarning messages, + * otherwise do not show warning messages + * + * Print the current watches and their values + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellShowWatches(xsltTransformContextPtr styleCtxt, + xmlShellCtxtPtr ctx,int showWarnings); + + /** + * xslDbgShellAddWatch: + * @arg : A valid xPath of expression to watch the value of + * + * Add expression to list of expressions to watch value of + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellAddWatch(xmlChar* arg); + + /** + * xslDbgShellDeleteWatch: + * @arg : A watch ID to remove + * + * Delete a given watch ID from our list of expressions to watch + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellDeleteWatch(xmlChar* arg); + + + /* ----------------------------------------- + * + * Tracing, walking related commands + * + * Implemented in shell.c + * + * ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellTrace: + * @arg: Not used + * + * Start the tracing of the stylesheet. First need to restart it. + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Start the tracing of the stylesheet. First need to restart it. + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg Not used + */ +#endif +#endif + int xslDbgShellTrace(xmlChar * arg); + + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellWalk: + * @arg: An interger between 0 and 9 indicate the speed of walk + * + * Start walking through the stylesheet. + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Start walking through the stylesheet. + * + * @returns 1 on success, + * 0 otherwise + * + * @param arg An interger between 0 and 9 indicate the speed of walk + */ +#endif +#endif + int xslDbgShellWalk(xmlChar * arg); + + + + /* ----------------------------------------- + * + * Seach related commands + * + * Implemented in search_cmds.c + * ------------------------------------------- */ + + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellSearch: + * @styleCtxt: Is valid + * @style: Is valid + * @arg: The xpath query to use for searching dataBase + * + * Displays the result of performing a query on the search dataBase + * + * Returns 1 if able to run query with @arg, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * @returns 1 if able to run query with @p arg, + * 0 otherwise + * + * @param styleCtxt Is valid + * @param style Is valid + * @param arg The xpath query to use for searching dataBase + */ +#endif +#endif + int xslDbgShellSearch(xsltTransformContextPtr styleCtxt, + xsltStylesheetPtr style, xmlChar * arg); + + +/* ----------------------------------------- + + Seach related commands + + Implemented in variable_cmds.c + ------------------------------------------- */ + +#ifdef USE_GNOME_DOCS + +/** + * xslDbgShellSetVariable: + * @styleCtxt : Is valid + * @arg : Is valid must be in the format of + * <VARIABLE_NAME> <XPATH> + * + * Change the value of a global or local variable + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Change the value of a global or local variable + * + * @param styleCtxt Is valid + * @param arg Is valid must be in the format of + * <VARIABLE_NAME> <XPATH> + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + + int xslDbgShellSetVariable(xsltTransformContextPtr styleCtxt, + xmlChar * arg); + +#ifdef __cplusplus +} +#endif +#endif + /* __DEBUG_XSL__ */ diff --git a/kxsldbg/kxsldbgpart/libxsldbg/file_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/file_cmds.cpp new file mode 100644 index 00000000..083b33b2 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/file_cmds.cpp @@ -0,0 +1,274 @@ + +/*************************************************************************** + file_cmds.c - define file command related functions + ------------------- + begin : Sat Jan 19 2002 + copyright : (C) 2002 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <libxml/tree.h> +#include <libxml/catalog.h> + +#include "xsldbg.h" +#include "debugXSL.h" +#include "files.h" +#include "options.h" +#include "utils.h" +#include "xsldbgthread.h" + +static char buffer[500]; + +/** + * xslDbgEntities: + * + * Print list of entites found + * + * Returns 1 on sucess, + * 0 otherwise + */ +int +xslDbgEntities(void) +{ + int result = 0; + + if (filesEntityList()) { + int entityIndex; + entityInfoPtr entInfo; + + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + /* notify that we are starting new list of entity names */ + notifyListStart(XSLDBG_MSG_ENTITIY_CHANGED); + for (entityIndex = 0; + entityIndex < arrayListCount(filesEntityList()); + entityIndex++) { + entInfo = (entityInfoPtr) arrayListGet(filesEntityList(), + entityIndex); + if (entInfo) + notifyListQueue(entInfo); + + } + notifyListSend(); + result = 1; + } else { + for (entityIndex = 0; + entityIndex < arrayListCount(filesEntityList()); + entityIndex++) { + entInfo = (entityInfoPtr) arrayListGet(filesEntityList(), + entityIndex); + if (entInfo) { + /* display identifier of an XML entity */ + xsldbgGenericErrorFunc(i18n("Entity %1 ").arg(xsldbgText(entInfo->SystemID))); + if (entInfo->PublicID) + xsldbgGenericErrorFunc(xsldbgText(entInfo->PublicID)); + xsldbgGenericErrorFunc("\n"); + } + } + if (arrayListCount(filesEntityList()) == 0) { + xsldbgGenericErrorFunc(i18n("No external General Parsed entities present.\n")); + } else { + xsldbgGenericErrorFunc(i18n("\tTotal of %n entity found.", "\tTotal of %n entities found.", arrayListCount(filesEntityList())) + QString("\n")); + } + + result = 1; + } + } + return result; +} + + +/** + * xslDbgSystem: + * @arg : Is valid + * + * Print what a system file @arg maps to via the current xml catalog + * + * Returns 1 on sucess, + * 0 otherwise + */ +int +xslDbgSystem(const xmlChar * arg) +{ + int result = 0; + xmlChar *name; + + if (!arg || (xmlStrlen(arg) == 0)) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + name = xmlCatalogResolveSystem(arg); + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + if (name) { + notifyXsldbgApp(XSLDBG_MSG_RESOLVE_CHANGE, name); + result = 1; + xmlFree(name); + } else { + notifyXsldbgApp(XSLDBG_MSG_RESOLVE_CHANGE, ""); + xsldbgGenericErrorFunc(i18n("SystemID \"%1\" was not found in current catalog.\n").arg(xsldbgText(arg))); + } + } else { + if (name) { + xsldbgGenericErrorFunc(i18n("SystemID \"%1\" maps to: \"%2\"\n").arg(xsldbgText(arg)).arg(xsldbgText(name))); + xmlFree(name); + result = 1; + } else { + xsldbgGenericErrorFunc(i18n("SystemID \"%1\" was not found in current catalog.\n").arg(xsldbgText(arg))); + } + } + + return result; +} + + +/** + * xslDbgPublic: + * @arg : Is valid + * + * Print what a public ID @arg maps to via the current xml catalog + * + * Returns 1 on sucess, + * 0 otherwise + */ +int +xslDbgPublic(const xmlChar * arg) +{ + int result = 0; + xmlChar *name; + + if (!arg || (xmlStrlen(arg) == 0)) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + name = xmlCatalogResolvePublic(arg); + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + if (name) { + notifyXsldbgApp(XSLDBG_MSG_RESOLVE_CHANGE, name); + result = 1; + xmlFree(name); + } else { + notifyXsldbgApp(XSLDBG_MSG_RESOLVE_CHANGE, ""); + xsldbgGenericErrorFunc(i18n("PublicID \"%1\" was not found in current catalog.\n").arg(xsldbgText(arg))); + } + } else { + if (name) { + xsldbgGenericErrorFunc(i18n("PublicID \"%1\" maps to: \"%2\"\n").arg(xsldbgText(arg)).arg(xsldbgText(name))); + xmlFree(name); + result = 1; + } else { + xsldbgGenericErrorFunc(i18n("PublicID \"%1\" was not found in current catalog.\n").arg(xsldbgText(arg))); + } + xsltGenericError(xsltGenericErrorContext, "%s", buffer); + } + return result; +} + + +/** + * xslDbgEncoding: + * @arg: Is valid encoding supported by libxml2 + * + * Set current encoding to use for output to standard output + * + * Returns 1 on sucess, + * 0 otherwise + */ +int +xslDbgEncoding(xmlChar * arg) +{ + int result = 0; + xmlChar *opts[2]; + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + if (splitString(arg, 1, opts) == 1) { + if (filesSetEncoding((char *) opts[0])) { + optionsSetStringOption(OPTIONS_ENCODING, opts[0]); + result = 1; + } + } else + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("encoding")); + return result; +} + + +/** + * xslDbgShellOutput: + * @arg : Is valid, either a local file name which will be expanded + * if needed, or a "file://" protocol URI + * + * Set the output file name to use + * + * Returns 1 on success, + * 0 otherwise + */ +int xslDbgShellOutput(const xmlChar *arg) +{ + int result = 0; + if (arg && (xmlStrLen(arg) > 0)){ + if (!xmlStrnCmp(arg, "file:/", 6)){ + /* convert URI to local file name */ + xmlChar *outputFileName = filesURItoFileName(arg); + if (outputFileName){ + optionsSetStringOption(OPTIONS_OUTPUT_FILE_NAME, + outputFileName); + notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L); + xmlFree(outputFileName); + result = 1; + } + } else if (xmlStrEqual(arg, (xmlChar*)"-")) { + optionsSetStringOption(OPTIONS_OUTPUT_FILE_NAME, + NULL); + notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L); + result = 1; + } else if (!xmlStrnCmp(arg, "ftp://", 6) || !xmlStrnCmp(arg, "http://", 7)){ + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("output")); + return 0; + } else { + /* assume that we were provided a local file name + * that may need expanding + */ + xmlChar *expandedName = filesExpandName(arg); + + // The output file must not be the same as our SOURCE or DATA file + if (expandedName && + (!xmlStrEqual(optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME), expandedName)) && + (!xmlStrEqual(optionsGetStringOption(OPTIONS_DATA_FILE_NAME), expandedName)) ){ + optionsSetStringOption(OPTIONS_OUTPUT_FILE_NAME, expandedName); + notifyXsldbgApp(XSLDBG_MSG_FILE_CHANGED, 0L); + xmlFree(expandedName); + result = 1; + }else{ + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("output")); + } + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("output")); + } + + return result; +} + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/files.cpp b/kxsldbg/kxsldbgpart/libxsldbg/files.cpp new file mode 100644 index 00000000..73d3713b --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/files.cpp @@ -0,0 +1,1420 @@ + +/*************************************************************************** + files.h - define file related functions + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* We want skip most of these includes when building documentation */ +#ifndef BUILD_DOCS + +#include "xsldbg.h" +#include <stdio.h> +#include <libxml/entities.h> +#include <libxml/tree.h> +#include <libxml/catalog.h> +#include <libxml/parserInternals.h> +#include <libxml/encoding.h> /* needed by filesTranslate, filesEncoding functions */ +#include <libxml/uri.h> /* needed for xmlURIUnescapeString */ +#include "debugXSL.h" +#include "files.h" +#include "utils.h" +#include "options.h" +#include "xsldbgthread.h" +#ifdef WIN32 +#include <direct.h> +#endif + +#endif /* BUILD_DOCS */ + + +/* top xml document */ +static xmlDocPtr topDocument; + +/* temporary xml document */ +static xmlDocPtr tempDocument; + +/* used as a scratch pad for temporary results*/ +static xmlChar filesBuffer[DEBUG_BUFFER_SIZE]; + +/* top stylsheet */ +static xsltStylesheetPtr topStylesheet; + +/* what is the base path for top stylesheet */ +static xmlChar *stylePathName = NULL; + +/* what is the path for current working directory*/ +static xmlChar *workingDirPath = NULL; + +static arrayListPtr entityNameList = NULL; + +/* Current encoding to use for standard output*/ +static xmlCharEncodingHandlerPtr stdoutEncoding = NULL; + +/* input and output buffers for encoding*/ +static xmlBufferPtr encodeInBuff = NULL; +static xmlBufferPtr encodeOutBuff = NULL; + +/* Current line number and URI for xsldbg*/ +static int currentLineNo = -1; +static xmlChar *currentUrl = NULL; + +/* ----------------------------------------- + Private function declarations for files.c + -------------------------------------------*/ + +/** + * guessStylesheetHelper: + * @payload: valid xsltStylesheetPtr + * @data: valid searchInfoPtr of type SEARCH_NODE + * @name: not used + * + * Try to guess what the complete file/URI is. If successful the search + * info will be set to found and the search data will contain the + * file name found. We are given our payload via walkStylesheets + */ +static void guessStylesheetHelper(void *payload, void *data, + xmlChar * name); + + +/** + * guessStylesheetHelper2: + * @payload: valid xmlNodePtr of the included stylesheet + * @data: valid searchInfoPtr of type SEARCH_NODE + * @name: not used + * + * Try to guess what the complete file/URI is. If successful the search + * info will be set to found and the search data will contain the + * file name found. We are given our payload via walkIncludes + */ +static void guessStylesheetHelper2(void *payload, void *data, + xmlChar * name); + + +entityInfoPtr filesNewEntityInfo(const xmlChar * SystemID, + const xmlChar * PublicID); + +void filesFreeEntityInfo(entityInfoPtr info); + +void filesAddEntityName(const xmlChar * SystemID, + const xmlChar * PublicID); + + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + +FILE *terminalIO; + +/* No longer needed + static FILE *oldStdin, *oldStdout, *oldStderr;*/ + + +//static char *ttyName = NULL; /* what is the name of the default terminal */ +static char *termName = NULL; /* what is the name of terminal we are redirected to */ + + +/** + * redirectToTerminal: + * @device: terminal to redirect i/o to , will not work under win32 + * + * Open communications to the terminal device @device + * + * Returns 1 if sucessful + * 0 otherwise + */ +int +openTerminal(xmlChar * device) +{ + int result = 0; + + if (!device) { /* Failed; there's no device */ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + /* + * On RISC OS, you get one terminal - the screen. + * we assume that the parameter is meant to be an output device as + * per normal - we can use vdu:, rawvdu: or :tt, or a filename for + * normal VDU output, VDU output without newline expansion, + * C terminal output with control code escaping, or a raw file + * respectively. + * The name passed is expected to be in native file format - no + * URI escaping here. + * One assumes that you might use a socket or a pipe here. + */ + + if (terminalIO) { + fclose(terminalIO); + terminalIO = NULL; + } + + + switch (device[0]) { + case '\0': + case '0': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* look like we are supposed to close the terminal + * but we've already done that + */ + break; + + case '1': + if (termName) { + terminalIO = fopen((char *) termName, "w"); + if (terminalIO != NULL) { + xmlFree(termName); + termName = xmlMemStrdup((char *) device); + result = 1; + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to open terminal %1.\n").arg(xsldbgText(termName))); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Did not previously open terminal.\n")); + } + break; + + case '2': +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Warning: Terminal level 2 not implemented\n"); +#endif + break; + + + default: + terminalIO = fopen((char *) device, "w"); + if (terminalIO != NULL) { + if (termName) + xmlFree(termName); + termName = xmlMemStrdup((char *) device); + result = 1; + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to open terminal %1.\n").arg(xsldbgText(device))); + } + + } + + return result; +} + + +/** + * guessStylesheetHelper: + * @payload: valid xsltStylesheetPtr + * @data: valid searchInfoPtr of type SEARCH_NODE + * @name: not used + * + * Try to guess what the complete file/URI is. If successful the search + * info will be set to found and the search data will contain the + * file name found. We are given our payload via walkStylesheets + */ +void +guessStylesheetHelper(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + xsltStylesheetPtr style = (xsltStylesheetPtr) payload; + searchInfoPtr searchCriteria = (searchInfoPtr) data; + nodeSearchDataPtr searchData = NULL; + /* where did the directory/URI separator occur */ + char *lastSlash; + + if (!style || !style->doc || !searchCriteria || !searchCriteria->data + || (searchCriteria->type != SEARCH_NODE)) + return; + + searchData = (nodeSearchDataPtr) searchCriteria->data; + if (searchData->nameInput && (searchData->absoluteNameMatch == NULL)) { + /* at this point we know that we have not made an absolute match + * but we may have made a relative match */ + if (xmlStrCmp(style->doc->URL, searchData->nameInput) == 0) { + /* absolute path match great! */ + searchData->absoluteNameMatch = + (xmlChar *) xmlMemStrdup((char *) style->doc->URL); + searchData->node = (xmlNodePtr) style->doc; + searchCriteria->found = 1; + return; + } + + + /* try to guess we assume that the files are unique */ + xmlStrCpy(filesBuffer, "__#!__"); + /* try relative to top stylesheet directory */ + if (stylePath()) { + xmlStrCpy(filesBuffer, stylePath()); + xmlStrCat(filesBuffer, searchData->nameInput); + } + if (xmlStrCmp(style->doc->URL, filesBuffer) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) filesBuffer); + searchData->node = (xmlNodePtr) style->doc; + searchCriteria->found = 1; + return; + } + + if (workingPath()) { + /* try relative to working directory */ + xmlStrCpy(filesBuffer, workingPath()); + xmlStrCat(filesBuffer, searchData->nameInput); + } + if (xmlStrCmp(style->doc->URL, filesBuffer) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) filesBuffer); + searchData->node = (xmlNodePtr) style->doc; + searchCriteria->found = 1; + return; + } + + + /* Find the last separator of the stylsheet's URL */ + lastSlash = xmlStrChr(style->doc->URL, URISEPARATORCHAR); + if (!lastSlash) + lastSlash = xmlStrChr(style->doc->URL, PATHCHAR); + + if (lastSlash) { + /* Last try, assume nameInput contains only a file name + * Strip of the file name at end of the stylesheet doc URL */ + lastSlash++; /* skip the slash */ + if (xmlStrCmp(lastSlash, searchData->nameInput) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) style->doc->URL); + searchData->node = (xmlNodePtr) style->doc; + searchCriteria->found = 1; + } + } + } +} + + +/** + * guessStylesheetHelper2: + * @payload: valid xmlNodePtr of the included stylesheet + * @data: valid searchInfoPtr of type SEARCH_NODE + * @name: not used + * + * Try to guess what the complete file/URI is. If successful the search + * info will be set to found and the search data will contain the + * file name found. We are given our payload via walkIncludes + */ +void +guessStylesheetHelper2(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + xmlNodePtr node = (xmlNodePtr) payload; + searchInfoPtr searchCriteria = (searchInfoPtr) data; + nodeSearchDataPtr searchData = NULL; + /* where did the directory/URI separator occur */ + char *lastSlash; + + if (!node || !node->doc || !searchCriteria || !searchCriteria->data || + (searchCriteria->type != SEARCH_NODE)) + return; + + searchData = (nodeSearchDataPtr) searchCriteria->data; + if (searchData->nameInput && (searchData->absoluteNameMatch == NULL)) { + /* at this point we know that we have not made an absolute match + * but we may have made a relative match */ + if (xmlStrCmp(node->doc->URL, searchData->nameInput) == 0) { + /* absolute path match great! */ + searchData->absoluteNameMatch = + (xmlChar *) xmlMemStrdup((char *) node->doc->URL); + searchData->node = node; + searchCriteria->found = 1; + return; + } + + + /* try to guess we assume that the files are unique */ + xmlStrCpy(filesBuffer, "__#!__"); + /* try relative to top stylesheet directory */ + if (stylePath()) { + xmlStrCpy(filesBuffer, stylePath()); + xmlStrCat(filesBuffer, searchData->nameInput); + } + if (xmlStrCmp(node->doc->URL, filesBuffer) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) filesBuffer); + searchData->node = node; + searchCriteria->found = 1; + return; + } + + if (workingPath()) { + /* try relative to working directory */ + xmlStrCpy(filesBuffer, workingPath()); + xmlStrCat(filesBuffer, searchData->nameInput); + } + if (xmlStrCmp(node->doc->URL, filesBuffer) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) filesBuffer); + searchData->node = node; + searchCriteria->found = 1; + return; + } + + + /* Find the last separator of the stylsheet's URL */ + lastSlash = xmlStrChr(node->doc->URL, URISEPARATORCHAR); + if (!lastSlash) + lastSlash = xmlStrChr(node->doc->URL, PATHCHAR); + + if (lastSlash) { + /* Last try, assume nameInput contains only a file name + * Strip of the file name at end of the stylesheet doc URL */ + lastSlash++; /* skip the slash */ + if (xmlStrCmp(lastSlash, searchData->nameInput) == 0) { + /* guessed right! */ + searchData->guessedNameMatch = + (xmlChar *) xmlMemStrdup((char *) node->doc->URL); + searchData->node = node; + searchCriteria->found = 1; + } + } + } +} + + +/** + * guessStylesheetName: + * @searchInf: Is valid + * + * Try to find a matching stylesheet name + * Sets the values in @searchinf depending on outcome of search + */ +void +guessStylesheetName(searchInfoPtr searchCriteria) +{ + nodeSearchDataPtr searchData; + + if (!searchCriteria) + return; + + searchData = (nodeSearchDataPtr) searchCriteria->data; + if (searchData->nameInput == NULL) + return; /* must supply name of file to look for */ + + walkStylesheets((xmlHashScanner) guessStylesheetHelper, + searchCriteria, filesGetStylesheet()); + if (!searchCriteria->found) { + /* try looking in the included stylesheets */ + walkIncludes((xmlHashScanner) guessStylesheetHelper2, + searchCriteria, filesGetStylesheet()); + } +} + + +/** + * stylePath: + * + * Return The base path for the top stylesheet ie + * ie URL minus the actual file name + * + * Returns The base path for the top stylesheet ie + * ie URL minus the actual file name + */ +xmlChar * +stylePath(void) +{ + return stylePathName; +} + + +/** + * workingPath: + * + * Return the working directory as set by changeDir function + * + * Returns The working directory as set by changeDir function + */ +xmlChar * +workingPath(void) +{ + return workingDirPath; +} + + +/** + * changeDir: + * @path: The path to adopt as new working directory + * + * Change working directory to path + * + * Returns 1 on success, + * 0 otherwise + */ +int +changeDir(const xmlChar * path) +{ + int result = 0; + int charIndex; + const char endString[2] = { PATHCHAR, '\0' }; + xmlChar *expandedName = NULL; + + + if (path && (xmlStrLen(path) > 0)) { + expandedName = filesExpandName(path); + } else { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Empty path provided to changeDir"); +#endif + return result; + } + + if (!expandedName) + return result; /* out of memory ? */ + + if (xmlStrLen(expandedName) + 1 > sizeof(filesBuffer)) { + xsldbgGenericErrorFunc(i18n("Error: The file name \"%1\" is too long.\n").arg(xsldbgText(path))); + return result; + } + + xmlStrCpy(filesBuffer, expandedName); + /* strip off any extra PATHCHAR's as win32's chdir function + * fails if we don't */ + charIndex = xmlStrLen(filesBuffer) - 1; + while (charIndex && (filesBuffer[charIndex] == PATHCHAR)) { + charIndex--; + } + filesBuffer[charIndex + 1] = '\0'; + + + if (chdir((char *) filesBuffer) == 0) { + if (workingDirPath) + xmlFree(workingDirPath); + /* must have path char at end of path name */ + xmlStrCat(filesBuffer, endString); + workingDirPath = (xmlChar *) xmlMemStrdup((char *) filesBuffer); + result = 1; + } + xmlFree(expandedName); /* this will always be valid time */ + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Unable to change to directory %1.\n").arg(xsldbgText(path))); + } else { + if (xslDebugStatus != DEBUG_NONE) + xsldbgGenericErrorFunc(i18n("Changed to directory %1.\n").arg(xsldbgText(path))); + } + return result; +} + + +/** + * filesLoadXmlFile: + * @path: xml file to load + * @fileType: A valid FileTypeEnum + * + * Load specified file type, freeing any memory previously used + * + * Returns 1 on success, + * 0 otherwise + */ +int +filesLoadXmlFile(const xmlChar * path, FileTypeEnum fileType) +{ + int result = 0; + + if (!filesFreeXmlFile(fileType)) + return result; + + switch (fileType) { + case FILES_XMLFILE_TYPE: + if (path && xmlStrLen(path)) { + if (optionsGetIntOption(OPTIONS_SHELL)) { + xsldbgGenericErrorFunc(i18n("Setting XML Data file name to %1.\n").arg(xsldbgText(path))); + } + optionsSetStringOption(OPTIONS_DATA_FILE_NAME, path); + } + topDocument = xsldbgLoadXmlData(); + if (topDocument) + result = 1; + break; + + case FILES_SOURCEFILE_TYPE: + if (path && xmlStrLen(path)) { + if (optionsGetIntOption(OPTIONS_SHELL)) { + xsldbgGenericErrorFunc(i18n("Setting stylesheet file name to %1.\n").arg(xsldbgText(path))); + } + optionsSetStringOption(OPTIONS_SOURCE_FILE_NAME, path); + } + topStylesheet = xsldbgLoadStylesheet(); + if (topStylesheet && topStylesheet->doc) { + /* look for last slash (or baskslash) of URL */ + char *lastSlash = xmlStrrChr(topStylesheet->doc->URL, + PATHCHAR); + const char *docUrl = + (const char *) topStylesheet->doc->URL; + + result = 1; + if (docUrl && lastSlash) { + stylePathName = (xmlChar *) xmlMemStrdup(docUrl); + stylePathName[lastSlash - docUrl + 1] = '\0'; + if (optionsGetIntOption(OPTIONS_SHELL)) { + xsldbgGenericErrorFunc(i18n("Setting stylesheet base path to %1.\n").arg(xsldbgText(stylePathName))); + } + } else { + const char cwd[4] = { '.', PATHCHAR, '\0' }; + + /* ie for *nix this becomes "./" */ + stylePathName = xmlStrdup(BAD_CAST cwd); + } + + /* try to find encoding for this stylesheet */ + if (optionsGetIntOption(OPTIONS_AUTOENCODE)) + filesSetEncoding((char *) topStylesheet->encoding); + } + break; + + case FILES_TEMPORARYFILE_TYPE: + if (!path || !xmlStrLen(path)) { + xsldbgGenericErrorFunc(i18n("Missing file name.\n")); + break; + } + topDocument = xsldbgLoadXmlTemporary(path); + if (tempDocument) + result = 1; + break; + } + return result; +} + + +/** + * filesFreeXmlFile: + * @fileType: A valid FileTypeEnum + * + * Free memory associated with the xml file + * + * Returns 1 on success, + * 0 otherwise + */ +int +filesFreeXmlFile(FileTypeEnum fileType) +{ + int result = 0, type = fileType; + + switch (type) { + case FILES_XMLFILE_TYPE: + if (topDocument) + xmlFreeDoc(topDocument); + topDocument = NULL; + result = 1; + break; + + case FILES_SOURCEFILE_TYPE: + if (topStylesheet) + xsltFreeStylesheet(topStylesheet); + if (stylePathName) + xmlFree(stylePathName); + stylePathName = NULL; + topStylesheet = NULL; + result = 1; + break; + + case FILES_TEMPORARYFILE_TYPE: + if (tempDocument) + xmlFreeDoc(tempDocument); + tempDocument = NULL; + result = 1; + break; + } + return result; +} + + +/** + * filesGetStylesheet: + * + * Return The topmost stylesheet non-null on success, + * NULL otherwise + * + * Returns The topmost stylesheet non-null on success, + * NULL otherwise + */ +xsltStylesheetPtr +filesGetStylesheet(void) +{ + return topStylesheet; +} + + +/** + * filesGetTemporaryDoc: + * + * Return The current "temporary" document + * + * Returns The current "temporary" document + */ +xmlDocPtr +filesGetTemporaryDoc(void) +{ + return tempDocument; +} + + +/** + * filesGetMainDoc: + * + * Return The main docment + * + * Returns The main docment + */ +xmlDocPtr +filesGetMainDoc(void) +{ + return topDocument; +} + + +/** + * filesReloaded: + * @reloaded: if = -1 then ignore @reloaded + * otherwise change the status of files to value of @reloaded + * + * Returns 1 if stylesheet or its xml data file has been "flaged" as reloaded, + * 0 otherwise + */ +int +filesReloaded(int reloaded) +{ + static int changed = 0; + + if (reloaded >= 0) { + changed = reloaded; + } + + return changed; +} + + + +/** + * filesInit: + * + * Initialize the file related structures + * Returns 1 on success, + * 0 otherwise + */ +int +filesInit(void) +{ + int result = 0; + + terminalIO = NULL; +#ifdef __riscos + ttyName = ":tt"; /* Default tty */ +#endif +#ifdef HAVE_UNISTD + ttyName = ttyname(fileno(stdin)); + /* save out io for when/if we send debugging to a terminal */ + oldStdin = stdin; + oldStdout = stdout; + oldStderr = stderr; +#endif + topDocument = NULL; + tempDocument = NULL; + topStylesheet = NULL; + entityNameList = arrayListNew(4, (freeItemFunc) filesFreeEntityInfo); +#if defined(HAVE_INCLUDE_FIX) && (LIBXML_VERSION < 20508) + xmlSetEntityReferenceFunc(filesEntityRef); +#endif + + /* setup the encoding */ + encodeInBuff = xmlBufferCreate(); + encodeOutBuff = xmlBufferCreate(); + + /* check the result so far and lastly perform platform specific + * initialization */ + if (entityNameList && encodeInBuff && encodeOutBuff && + filesPlatformInit()) + result = 1; + return result; +} + +/** + * filesFree: + * + * Free memory used by file related structures + */ +void +filesFree(void) +{ + int result; + + if (terminalIO) { + fclose(terminalIO); + terminalIO = NULL; + } + if (termName) { + xmlFree(termName); + termName = NULL; + } + + result = filesFreeXmlFile(FILES_SOURCEFILE_TYPE); + if (result) + result = filesFreeXmlFile(FILES_XMLFILE_TYPE); + if (result) + result = filesFreeXmlFile(FILES_TEMPORARYFILE_TYPE); + if (!result){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to free memory used by XML/XSLT files\n"); +#endif + } + if (stylePathName) { + xmlFree(stylePathName); + stylePathName = NULL; + } + + if (workingDirPath) { + xmlFree(workingDirPath); + workingDirPath = NULL; + } + + if (entityNameList) { + arrayListFree(entityNameList); + entityNameList = NULL; + } + + /* Free memory used by encoding related structures */ + if (encodeInBuff) + xmlBufferFree(encodeInBuff); + + if (encodeOutBuff) + xmlBufferFree(encodeOutBuff); + + /* close current encoding */ + filesSetEncoding(NULL); + + if (currentUrl) + xmlFree(currentUrl); + + /* free any memory used by platform specific files module */ + filesPlatformFree(); +} + + +/** + * filesIsSourceFile: + * @fileName : is valid + * + * Returns true if @name has the ".xsl" externsion + */ +int +filesIsSourceFile(xmlChar * fileName) +{ + return strstr((char *) fileName, ".xsl") || + strstr((char *) fileName, ".Xsl") || + strstr((char *) fileName, ".XSL"); +} + + + +entityInfoPtr +filesNewEntityInfo(const xmlChar * SystemID, const xmlChar * PublicID) +{ + + entityInfoPtr result = (entityInfoPtr) xmlMalloc(sizeof(entityInfo)); + + if (result) { + if (SystemID) + result->SystemID = xmlStrdup(SystemID); + else + result->SystemID = xmlStrdup(BAD_CAST ""); + + if (PublicID) + result->PublicID = xmlStrdup(PublicID); + else + result->PublicID = xmlStrdup(BAD_CAST ""); + } + return result; +} + +void +filesFreeEntityInfo(entityInfoPtr info) +{ + if (!info) + return; + + if (info->SystemID) + xmlFree(info->SystemID); + + if (info->PublicID) + xmlFree(info->PublicID); + xmlFree(info); +} + +/** + * filesAddEntityName: + * @name : is valid + * + * Add name to entity name list of know external entities if + * it does not already exist in list + */ +void + +filesAddEntityName(const xmlChar * SystemID, const xmlChar * PublicID) +{ + int entityIndex = 0; + entityInfoPtr tempItem; + + if (!SystemID || !filesEntityList()) + return; + + for (entityIndex = 0; + entityIndex < arrayListCount(filesEntityList()); entityIndex++) { + tempItem = + (entityInfoPtr) arrayListGet(filesEntityList(), entityIndex); + if (tempItem && xmlStrEqual(SystemID, tempItem->SystemID)) { + /* name aready exits so don't add it */ + return; + } + + } + + tempItem = filesNewEntityInfo(SystemID, PublicID); + arrayListAdd(filesEntityList(), tempItem); +} + + +/** + * filesEntityRef : + * @ent : Is valid as provided by libxslt + * @firstNode : Is valid + * @lastNode : Is Valid + * + * Fixes the nodes from firstNode to lastNode so that debugging can occur + */ +void + +filesEntityRef(xmlEntityPtr ent, xmlNodePtr firstNode, xmlNodePtr lastNode) +{ + xmlNodePtr node = firstNode; + if (!firstNode || !ent || !ent->SystemID || + (ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ) + return; + + if (ent->ExternalID) + filesAddEntityName(ent->SystemID, ent->ExternalID); + else + filesAddEntityName(ent->URI, BAD_CAST ""); + while (node){ + filesSetBaseUri(node, ent->URI); + if (node != lastNode) + node = node->next; + else + node = NULL; + } +} + + + + /** + * filesSetBaseUri: + * @node : Is valid and has a doc parent + * @uri : Is Valid + * + * Set the base uri for this node. Function is used when xml file + * has external entities in its DTD + * + * Returns 1 if successful, + * 0 otherwise + */ + +int +filesSetBaseUri(xmlNodePtr node, const xmlChar * uri) +{ + int result = 0; + + if (!node || !uri) + return result; + else { + if (node->type == XML_ELEMENT_NODE){ + xmlChar *xsldbgUrlCopy = xmlGetProp(node, BAD_CAST "xsldbg:uri"); + if (!xsldbgUrlCopy) + xmlNewProp(node, BAD_CAST "xsldbg:uri", uri); + else + xmlFree(xsldbgUrlCopy); + } + result = 1; + } + return result; +} + + + /** + * filesGetBaseUri: + * @node : Is valid and has a doc parent + * + * Get a copy of the base uri for this node. Function is most usefull + * used when xml file has external entities in its DTD + * + * Returns the a copy of the base uri for this node, + * NULL otherwise + */ +xmlChar * +filesGetBaseUri(xmlNodePtr node) +{ + xmlChar *result = NULL; + + if (!node || !node->doc) + return result; + + while (node && node->parent) { + /* + * result = xmlGetNsProp(node, BAD_CAST "uri", XSLDBG_XML_NAMESPACE); + */ + if (node->type == XML_ELEMENT_NODE) { + result = xmlGetProp(node, BAD_CAST "xsldbg:uri"); + if (result) + break; + } + node = node->parent; + } + + if (!result && node->doc && node->doc->URL) + result = xmlStrdup(node->doc->URL); + + return result; +} + + + + +/** + * filesEntityList: + * + * Return the list entity names used for documents loaded + * + * Returns the list entity names used for documents loaded + */ +arrayListPtr +filesEntityList(void) +{ + return entityNameList; +} + +extern int intVolitileOptions[OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID + 1]; + +/** + * filesLoadCatalogs: + * + * Load the catalogs specifed by OPTIONS_CATALOG_NAMES if + * OPTIONS_CATALOGS is enabled + * Returns 1 if sucessful + * 0 otherwise + */ +int +filesLoadCatalogs(void) +{ + int result = 0; + const char *catalogs = NULL; + + xmlCatalogCleanup(); + if (optionsGetIntOption(OPTIONS_CATALOGS)) { + if (optionsGetStringOption(OPTIONS_CATALOG_NAMES) == NULL) { + /* use the SGML catalog */ +#ifdef __riscos + catalogs = getenv("SGML$CatalogFiles"); +#else + catalogs = getenv("SGML_CATALOG_FILES"); +#endif + if (catalogs == NULL) { +#ifdef __riscos + xsldbgGenericErrorFunc("Warning: Environment variable SGML$CatalogFiles is not set.\n"); +#else + xsldbgGenericErrorFunc("Warning: Environment variabe SGML_CATALOG_FILES FILES not set.\n"); +#endif + } else + /* copy the current catalog name(s) for user to see */ + optionsSetStringOption(OPTIONS_CATALOG_NAMES, + (xmlChar *) catalogs); + } else + /* Use the current catalog settings from users*/ + catalogs = (char *) + optionsGetStringOption(OPTIONS_CATALOG_NAMES); + + result = 1; + } + + if (catalogs){ + /* Load the new cataog selection */ + xmlLoadCatalogs(catalogs); + }else{ + /* Use default catalogs */ + xmlInitializeCatalog(); + } + return result; +} + + + + + /** + * filesEncode: + * @text: Is valid, text to translate from UTF-8, + * + * Return A new string of converted @text + * + * Returns A new string of converted @text, may be NULL + */ +xmlChar * +filesEncode(const xmlChar * text) +{ + xmlChar *result = NULL; + + if (!text) + return result; + + if (!stdoutEncoding || !encodeInBuff || !encodeOutBuff) + return xmlStrdup(text); /* no encoding active return as UTF-8 */ + + xmlBufferEmpty(encodeInBuff); + xmlBufferEmpty(encodeOutBuff); + xmlBufferCat(encodeInBuff, text); + + if (xmlCharEncOutFunc(stdoutEncoding, encodeOutBuff, encodeInBuff) + >= 0) { + result = xmlStrdup(xmlBufferContent(encodeOutBuff)); + } else { + xsldbgGenericErrorFunc(i18n("Encoding of text failed.\n")); + return xmlStrdup(text); /* panic, return as UTF-8 */ + } + return result; +} + + + + /** + * filesDeccode: + * @text: Is valid, text to translate from current encoding to UTF-8, + * + * Return A string of converted @text + * + * Returns A string of converted @text, may be NULL + */ +xmlChar * +filesDecode(const xmlChar * text) +{ + xmlChar *result = NULL; + + if (!text) + return result; + + if (!stdoutEncoding || !encodeInBuff || !encodeOutBuff) + return xmlStrdup(text); /* no encoding active return as UTF-8 */ + + xmlBufferEmpty(encodeInBuff); + xmlBufferEmpty(encodeOutBuff); + xmlBufferCat(encodeInBuff, text); + + if (xmlCharEncInFunc(stdoutEncoding, encodeOutBuff, encodeInBuff) + >= 0) { + result = xmlStrdup(xmlBufferContent(encodeOutBuff)); + } else { + xsldbgGenericErrorFunc(i18n("Encoding of text failed.\n")); + return xmlStrdup(text); /* panic, return @text unchanged */ + } + return result; +} + + + /* + * filesSetEncoding: + * @encoding : Is a valid encoding supported by the iconv library or NULL + * + * Opens encoding for all standard output to @encoding. If @encoding + * is NULL then close current encoding and use UTF-8 as output encoding + * + * Returns 1 if successful in setting the encoding of all standard output + * to @encoding + * 0 otherwise + */ +int +filesSetEncoding(const char *encoding) +{ + int result = 0; + + if (encoding) { + /* don't switch encoding unless we've found a valid encoding */ + xmlCharEncodingHandlerPtr tempEncoding = + xmlFindCharEncodingHandler(encoding); + if (tempEncoding) { + filesSetEncoding(NULL); /* re-use code to close encoding */ + stdoutEncoding = tempEncoding; + result = + (xmlCharEncOutFunc(stdoutEncoding, encodeOutBuff, NULL) + >= 0); + if (!result) { + xmlCharEncCloseFunc(stdoutEncoding); + stdoutEncoding = NULL; + xsldbgGenericErrorFunc(i18n("Unable to initialize encoding %1.").arg(xsldbgText(encoding))); + } else + optionsSetStringOption(OPTIONS_ENCODING, + (xmlChar *) encoding); + } else { + xsldbgGenericErrorFunc(i18n("Invalid encoding %1.\n").arg(xsldbgText(encoding))); + } + } else { + /* close encoding and use UTF-8 */ + if (stdoutEncoding) + result = (xmlCharEncCloseFunc(stdoutEncoding) >= 0); + else + result = 1; + stdoutEncoding = NULL; + } + return result; +} + + + + /** + * filesMoreFile: + * @fileName : May be NULL + * @file : May be NULL + * + * Do a "more" like print of file specified by @fileName OR + * @file. If both are provided @file will be used. The content + * of file chosen must be in UTF-8, and will be printed in + * the current encoding selected.The function will pause output + * after FILES_NO_LINES lines have been printed waiting for + * user to enter "q" to quit or any other text to continue. + * + * Returns 1 if successful, + * 0 otherwise + */ +int +filesMoreFile(const xmlChar * fileName, FILE * file) +{ + int result = 0; + int openedFile = 0; + int lineCount; + int reachedEof = 0; + + if (fileName && !file) { +#ifdef __riscos + /* convert into RISC OS format a *nix style file name */ + fileName = (const xmlChar *) riscosfilename((char *) fileName); +#endif + file = fopen((char *) fileName, "r"); + openedFile = 1; /* since we opened the file we must close it */ + } + if (file) { + while (!feof(file) && !reachedEof) { + lineCount = 0; + while (!feof(file) && (lineCount < FILES_NO_LINES) && + !reachedEof) { + if (fgets((char *) filesBuffer, sizeof(filesBuffer), file)) { + xsltGenericError(xsltGenericErrorContext, "%s", + filesBuffer); + lineCount++; + } else { + reachedEof = 1; + } + } + + if (!feof(file) && !reachedEof) { + xsldbgGenericErrorFunc(i18n(" ----- more ---- \n")); + fflush(stderr); + if (fgets((char *) filesBuffer, sizeof(filesBuffer), stdin)) { + if ((*filesBuffer == 'q') || (*filesBuffer == 'Q')) + reachedEof = 1; + } else { + reachedEof = 1; + } + } + } + + if (openedFile) { + fclose(file); + } + xsltGenericError(xsltGenericErrorContext, "\n"); + result = 1; + } else { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: No valid file provided to print\n"); +#endif + } + + + return result; +} + + + /** + * filesSearchResultsPath: + * + * Get the base path to be used for storing search results + * + * Returns The base path to be used for storing search results + */ +const xmlChar * +filesSearchResultsPath() +{ + const xmlChar *result; + + if (optionsGetStringOption(OPTIONS_SEARCH_RESULTS_PATH)) + result = optionsGetStringOption(OPTIONS_SEARCH_RESULTS_PATH); + else + result = stylePath(); + + return result; +} + + + /** + * filesURItoFileName: + * @uri : A valid URI that uses the "file://" prefix + * + * Return A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" prefix, or unable to convert to a valid file name + * + * Returns A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" prefix, or unable to convert to a valid file name + * + */ +xmlChar *filesURItoFileName(const xmlChar* uri) +{ + xmlChar *result = NULL; + xmlChar *unescapedFileName = NULL; + const xmlChar* tempName = NULL; + + if (uri){ + if (!xmlStrnCmp(uri, "file://localhost", 16 )){ + tempName = uri + 16; + }else{ +#if defined(WIN32) && ! defined(CYGWIN) + if (!xmlStrnCmp(uri, "file:///", 8)) + tempName = uri + 8; +#else + if (!xmlStrnCmp(uri, "file:/", 6)) + tempName = uri + 5; // we need the leading '/'*/ + while (tempName[0] == '/' && tempName[1] == '/' ) + tempName++; +#endif + } + + /* If we've found something check to see if the file name + found is to be valid */ + if (tempName) + result = (xmlChar*) xmlStrdup(tempName); + unescapedFileName = (xmlChar*) xmlStrdup(tempName); + if (result && unescapedFileName){ + if (PATHCHAR != URISEPARATORCHAR){ + /* Must convert path separators first */ + xmlChar *probe = result; + while(*probe != '\0'){ + if (*probe == (xmlChar)URISEPARATORCHAR) + *probe = (xmlChar)PATHCHAR; + probe++; + } + } + /* Now unescape the file name in result so far + * NB: An unescaped name takes less memory that an escaped name + */ + xmlURIUnescapeString((char*)result, -1, (char*)unescapedFileName); + xmlFree(result); + /* success we've got an local unescaped file name */ + result = unescapedFileName; + }else{ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + if (result){ + xmlFree(result); + } + if (unescapedFileName) /* not needed, here for completeness */ + xmlFree(unescapedFileName); + + result = NULL; + } + }else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to convert %1 to local file name.\n").arg(xsldbgText(uri))); + } + + + return result; +} + + +/* TODO in xsldbg 3.x rename these to use files prefix */ + +/** + * xsldbgUpdateFileDetails: + * @node : A valid node + * + * Update the URL and line number that we stoped at + */ +void +xsldbgUpdateFileDetails(xmlNodePtr node) +{ + if ((node != NULL) && (node->doc != NULL)){ + if (currentUrl != NULL) + xmlFree(currentUrl); + currentUrl = filesGetBaseUri(node); + currentLineNo = xmlGetLineNo(node); + } +} + + +/** + * xsldbgLineNo: + * + * What line number are we at + * + * Returns The current line number of xsldbg, may be -1 + **/ +int +xsldbgLineNo(void) +{ + return currentLineNo; +} + + +/** + * xsldbgUrl: + * + * What URL did we stop at + * + * Returns A NEW copy of URL stopped at. Caller must free memory for URL. + * May be NULL + */ +xmlChar * +xsldbgUrl(void) +{ + if (currentUrl != NULL) + return (xmlChar *) xmlMemStrdup((char *) currentUrl); + else + return NULL; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/files.h b/kxsldbg/kxsldbgpart/libxsldbg/files.h new file mode 100644 index 00000000..05e49828 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/files.h @@ -0,0 +1,981 @@ + +/*************************************************************************** + files.h - define file related functions + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef FILES_H +#define FILES_H + +#ifndef BUILD_DOCS + +#include "search.h" +#include "arraylist.h" + +#endif + +#ifdef USE_KDE_DOCS + +/** + * Provide a file support + * + * @short file support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + + +#ifdef HAVE_UNISTD_H +#include <unistd.h> /* need chdir function */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + extern FILE *terminalIO; + +#define XSLDBG_XML_NAMESPACE \ + (const xmlChar *) "http://xsldbg.sourceforge.net/namespace" + + typedef struct _entityInfo entityInfo; + typedef entityInfo *entityInfoPtr; + struct _entityInfo { + xmlChar *SystemID; + xmlChar *PublicID; + }; + + + /* how many lines do we print before pausing when + * performing "more" on a UTF-8 file. See function filesMoreFile */ +#define FILES_NO_LINES 20 + + /* Define the types of file names that we are intested in when creating + * search results */ +#ifndef USE_KDOC + typedef enum { + FILES_SEARCHINPUT, + FILES_SEARCHXSL, + FILES_SEARCHRESULT + } FilesSearchFileNameEnum; +#else + /* keep kdoc happy */ + enum FilesSearchFileNameEnum { + FILES_SEARCHINPUT, + FILES_SEARCHXSL, + FILES_SEACHRESULT + }; +#endif + + + + /*----------------------------------------------------------- + General function for working with files + -----------------------------------------------------------*/ + +#ifdef USE_GNOME_DOCS + + /** + * filesEntityRef : + * @ent : Is valid as provided by libxslt + * @firstNode : Is valid + * @lastNode : Is Valid + * + * Fixes the nodes from firstNode to lastNode so that debugging can occur + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Fixes the nodes from firstNode to lastNode so that debugging can occur + * + * @param uri Is valid as provided by libxslt + * @param firstNode Is valid + * @param lastNode Is Valid + */ +#endif +#endif + void filesEntityRef(xmlEntityPtr ent, xmlNodePtr firstNode, + xmlNodePtr lastNode); + + +#ifdef USE_GNOME_DOCS + + /** + * filesEntityList: + * + * Return the list entity names used for documents loaded + * + * Returns The list entity names used for documents loaded + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the list entity names used for documents loaded + * + * @returns The list entity names used for documents loaded + */ +#endif +#endif + arrayListPtr filesEntityList(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesSetBaseUri: + * @node : Is valid and has a doc parent + * @uri : Is Valid + * + * Set the base uri for this node. Function is used when xml file + * has external entities in its DTD + * + * Returns 1 if successful, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Set the base uri for this node. Function is used when xml file + * has external entities in its DTD + * + * @param node Is valid and has a doc parent + * @param uri Is Valid + * + * @returns 1 if successful, + * 0 otherwise + */ +#endif +#endif + int filesSetBaseUri(xmlNodePtr node, const xmlChar * uri); + + +#ifdef USE_GNOME_DOCS + + /** + * filesGetBaseUri: + * @node : Is valid and has a doc parent + * + * Get a copy of the base uri for this node. Function is most usefull + * used when xml file has external entities in its DTD + * + * Returns the a copy of the base uri for this node, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Get a copy of the base uri for this node. Function is most usefull + * used when xml file has external entities in its DTD + * + * @param node : Is valid and has a doc parent + * + * @returns The a copy of the base uri for this node, + * NULL otherwise + */ +#endif +#endif + xmlChar *filesGetBaseUri(xmlNodePtr node); + + +#ifdef USE_GNOME_DOCS + + /** + * filesTempFileName: + * @fleNumber : Number of temp file required + * where @fileNumber is + * 0 : file name used by cat command + * 1 : file name used by profiling output + * + * Return the name of tempfile requirested + * + * This is a platform specific interface + * + * Returns The name of temp file to be used for temporary results if sucessful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the name of tempfile requested. + * @param fleNumber : Number of temp file required + * where @p fileNumber is + * 0 : file name used by cat command + * 1 : file name used by profiling output + * + * This is a platform specific interface + * + * Returns The name of temp file to be used for temporary results if sucessful, + * NULL otherwise + */ +#endif +#endif + const char *filesTempFileName(int fileNumber); + + +#ifdef USE_GNOME_DOCS + + /** + * filesLoadCatalogs: + * + * Load the catalogs specifed by OPTIONS_CATALOG_NAMES if + * OPTIONS_CATALOGS is enabled + * + * Returns 1 if sucessful + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Load the catalogs specifed by OPTIONS_CATALOG_NAMES if + * OPTIONS_CATALOGS is enabled + * + * @returns 1 if sucessful + * 0 otherwise + */ +#endif +#endif + int filesLoadCatalogs(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesEncode: + * @text: Is valid, text to translate from UTF-8, + * + * Return A string of converted @text + * + * Returns A string of converted @text, may be NULL + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return A string of converted @text + * + * @param text Is valid, text to translate from UTF-8, + * + * Returns A string of converted @text, may be NULL + */ +#endif +#endif + xmlChar *filesEncode(const xmlChar * text); + + +#ifdef USE_GNOME_DOCS + + /** + * filesDeccode: + * @text: Is valid, text to translate from current encoding to UTF-8, + * + * Return A string of converted @text + * + * Returns A string of converted @text, may be NULL + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return A string of converted @text + * + * @param test Is valid, text to translate from current encoding to UTF-8, + * + * Returns A string of converted @text, may be NULL + */ +#endif +#endif + xmlChar *filesDecode(const xmlChar * text); + + +#ifdef USE_GNOME_DOCS + + /** + * filesSetEncoding: + * @encoding : Is a valid encoding supported by the iconv library or NULL + * + * Opens encoding for all standard output to @encoding. If @encoding + * is NULL then close current encoding and use UTF-8 as output encoding + * + * Returns 1 if successful in setting the encoding of all standard output + * to @encoding + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Opens encoding for all standard output to @p encoding. If @p encoding + * is NULL then close current encoding and use UTF-8 as output encoding + * + * @param encoding Is a valid encoding supported by the iconv library or NULL + * + * Returns 1 if successful in setting the encoding of all standard output + * to @p encoding + * 0 otherwise + */ +#endif +#endif + int filesSetEncoding(const char *encoding); + + +#ifndef USE_KDOC + /* used by filesLoadXmlFile, filesFreeXmlFile functions */ + typedef enum { + FILES_XMLFILE_TYPE = 100, /* pick a unique starting point */ + FILES_SOURCEFILE_TYPE, + FILES_TEMPORARYFILE_TYPE + } FileTypeEnum; +#else + + /* used by filesLoadXmlFile, filesFreeXmlFile functions */ + enum FileTypeEnum { + FILES_XMLFILE_TYPE = 100, /* pick a unique starting point */ + FILES_SOURCEFILE_TYPE, + FILES_TEMPORARYFILE_TYPE + }; +#endif + + +#ifdef USE_GNOME_DOCS + + /** + * openTerminal + * @device: terminal to redirect i/o to , will not work under win32 + * + * Open communications to the terminal device @device + * Returns 1 if sucessful + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Open communications to the terminal device @p device + * + * @param device Terminal to redirect i/o to , will not work under win32 + * + * @returns 1 if sucessful + * 0 otherwise + */ +#endif +#endif + int openTerminal(xmlChar * device); + + +#ifdef USE_GNOME_DOCS + + /** + * guessStyleSheetName: + * @searchInf : Is valid + * + * Try to find a matching stylesheet name + * Sets the values in @searchinf depending on outcome of search + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Try to find a matching stylesheet name + * Sets the values in @p searchinf depending on outcome of search + * + * @param searchInf Is valid + */ +#endif +#endif + void guessStylesheetName(searchInfoPtr searchInf); + + +#ifdef USE_GNOME_DOCS + + /** + * stylePath: + * + * Returns the base path for the top stylesheet ie + * ie URL minus the actual file name + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the base path for the top stylesheet ie + * ie URL minus the actual file name + * + * @returns The base path for the top stylesheet ie + * ie URL minus the actual file name + */ +#endif +#endif + xmlChar *stylePath(void); + + +#ifdef USE_GNOME_DOCS + + /** + * workingPath: + * + * Return the working directory as set by changeDir function + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the working directory as set by changeDir function + * + * @return the working directory as set by changeDir function + */ +#endif +#endif + xmlChar *workingPath(void); + + +#ifdef USE_GNOME_DOCS + + /** + * changeDir: + * @path : path to adopt as new working directory + * + * Change working directory to path + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Change working directory to path + * + * @param path The operating system path(directory) to adopt as + * new working directory + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int changeDir(const xmlChar * path); + + +#ifdef USE_GNOME_DOCS + + /** + * filesLoadXmlFile: + * @path : xml file to load + * @fileType : A valid FileTypeEnum + * + * Load specified file type, freeing any memory previously used + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Load specified file type, freeing any memory previously used + * + * @returns 1 on success, + * 0 otherwise + * + * @param path The xml file to load + * @param fileType A valid FileTypeEnum + */ +#endif +#endif + int filesLoadXmlFile(const xmlChar * path, FileTypeEnum fileType); + + +#ifdef USE_GNOME_DOCS + + /** + * filesFreeXmlFile: + * @fileType : A valid FileTypeEnum + * + * Free memory associated with the xml file + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Free memory associated with the xml file + * + * @returns 1 on success, + * 0 otherwise + * + * @param fileType : A valid FileTypeEnum + */ +#endif +#endif + int filesFreeXmlFile(FileTypeEnum fileType); + + +#ifdef USE_GNOME_DOCS + + /** + * filesGetStylesheet: + * + * Return the topmost stylesheet + * + * Returns non-null on success, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the topmost stylesheet + * + * @returns Non-null on success, + * NULL otherwise + */ +#endif +#endif + xsltStylesheetPtr filesGetStylesheet(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesGetTemporaryDoc: + * + * Return the current "temporary" document + * + * Returns the current "temporary" document + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the current "temporary" document + * + * @returns non-null on success, + * NULL otherwise + */ +#endif +#endif + xmlDocPtr filesGetTemporaryDoc(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesGetMainDoc: + * + * Returns the main docment + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return the main docment + * + * @returns the main document + */ +#endif +#endif + xmlDocPtr filesGetMainDoc(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesReloaded: + * @reloaded : if = -1 then ignore @reloaded + * otherwise change the status of files to value of @reloaded + * + * Returns 1 if stylesheet or its xml data file has been "flaged" as reloaded, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * @returns 1 if stylesheet or its xml data file has been "flaged" as reloaded, + * 0 otherwise + * + * @param reloaded If = -1 then ignore @p reloaded + * otherwise change the status of files to value of @p reloaded + */ +#endif +#endif + int filesReloaded(int reloaded); + + +#ifdef USE_GNOME_DOCS + + /** + * filesInit: + * + * Initialize the file module + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Initialize the file module + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int filesInit(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesFree: + * + * Free memory used by file related structures + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Free memory used by file related structures + */ +#endif +#endif + void filesFree(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesIsSourceFile: + * @fileName : Is valid + * + * Test if filename could be a stylesheet + * + * Returns true if @name has the ".xsl" extension + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Test if filename could be a stylesheet + * + * @returns True if @name has the ".xsl" extension + * + * @param fileName Is valid + */ +#endif +#endif + int filesIsSourceFile(xmlChar * fileName); + + + +#ifdef USE_GNOME_DOCS + + /** + * filesMoreFile: + * @fileName : May be NULL + * @file : May be NULL + * + * Do a "more" like print of file specified by @fileName OR + * @file. If both are provided @file will be used. The content + * of file chosen must be in UTF-8, and will be printed in + * the current encoding selected.The function will pause output + * after FILES_NO_LINES lines have been printed waiting for + * user to enter "q" to quit or any other text to continue. + * + * Returns 1 if successful, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Do a "more" like print of file specified by @fileName OR + * @file. If both are provided @file will be used. The content + * of file chosen must be in UTF-8, and will be printed in + * the current encoding selected. The function will pause output + * after FILES_NO_LINES lines have been printed waiting for + * user to enter "q" to quit or any other text to continue. + * + * @returns 1 if successful, + * 0 otherwise + * + * @param fileName May be NULL + * @param file May be NULL + * + */ +#endif +#endif + int filesMoreFile(const xmlChar * fileName, FILE * file); + +#ifdef USE_GNOME_DOCS + + /** + * filesSearchResultsPath: + * + * Get the base path to be used for storing search results + * + * Returns The base path to be used for storing search results + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Get the base path to be used for storing search results + * + * @returns The base path to be used for storing search results + */ +#endif +#endif + const xmlChar *filesSearchResultsPath(void); + + + +#ifdef USE_GNOME_DOCS + + /** + * filesURItoFileName: + * @uri : A valid URI that uses the "file://" prefix + * + * Return A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" prefix, or unable to convert to a valid file name + * + * Returns A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" prefix, or unable to convert to a valid file name + * + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" protocol, or unable to convert to a valid file name + * + * Returns A copy of the conversion of @uri to a file name + * that is suitable to be used with the fopen function. + * May be NULL, if out of memory, @uri does not use the + * "file://" prefix, or unable to convert to a valid file name + * + * @param uri A valid URI that uses the "file://" prefix + * + */ +#endif +#endif + xmlChar *filesURItoFileName(const xmlChar* uri); + + +#ifdef USE_GNOME_DOCS + +/** + * xsldbgUpdateFileDetails: + * @node : A valid node + * + * Update the URL and line number that we stoped at + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Update the URL and line number that we stoped at + * + * @param node A valid node + */ +#endif +#endif + void xsldbgUpdateFileDetails(xmlNodePtr node); + + + +#ifdef USE_GNOME_DOCS + + /** + * xsldbgLineNo: + * + * What line number are we at + * + * Returns The current line number of xsldbg, may be -1 + **/ +#else +#ifdef USE_KDE_DOCS + + /** + * What line number are we at + * + * @returns The current line number of xsldbg, may be -1 + **/ +#endif +#endif + int xsldbgLineNo(void); + + +#ifdef USE_GNOME_DOCS + + /** + * xsldbgUrl: + * + * What URL did we stop at + * + * Returns A NEW copy of URL stopped at. Caller must free memory for URL, + * may be NULL + */ +#else +#ifdef USE_KDE_DOCS + + /** + * What URL did we stop at + * + * @returns A NEW copy of URL stopped at. Caller must free memory for URL, + * may be NULL + */ +#endif +#endif + xmlChar *xsldbgUrl(void); + + /*----------------------------------------------------------- + Platform specific file functions + -----------------------------------------------------------*/ + + +#ifdef USE_GNOME_DOCS + + /** + * filesPlatformInit: + * + * Intialize the platform specific files module + * + * This is a platform specific interface + * + * Returns 1 if sucessful + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Intialize the platform specific files module + * + * This is a platform specific interface + * + * @returns 1 if sucessful + * 0 otherwise + */ +#endif +#endif + int filesPlatformInit(void); + + +#ifdef USE_GNOME_DOCS + + /** + * filesPlatformFree: + * + * Free memory used by the platform specific files module + * + * This is a platform specific interface + * + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Free memory used by the platform specific files module + * + * This is a platform specific interface + * + */ +#endif +#endif + void filesPlatformFree(void); + + + +#ifdef USE_GNOME_DOCS + + /** + * filesExpandName: + * @fileName : A valid fileName + * + * Converts a fileName to an absolute path + * If operating system supports it a leading "~" in the fileName + * will be converted to the user's home path. Otherwise + * the same name will be returned + * + * Returns A copy of the converted @fileName or a copy of + * the @fileName as supplied. May return NULL + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Converts a fileName to an absolute path + * If operating system supports it a leading "~" in the fileName + * will be converted to the user's home path. Otherwise + * the same name will be returned + * + * Returns A copy of the converted @p fileName or a copy of + * the @p fileName as supplied. May return NULL + * + * @param fileName A valid fileName + */ +#endif +#endif + xmlChar *filesExpandName(const xmlChar * fileName); + + + +#ifdef USE_GNOME_DOCS + + /** + * filesSearchFileName: + * @fileType : Is valid + * + * Return a copy of the file name to use as an argument to searching + * + * Returns A copy of the file name to use as an argument to searching + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Return a copy of the file name to use as an argument to searching + * + * @returns A copy of the file name to use as an argument to searching + * + * @param fileType Is valid + * + */ +#endif +#endif + xmlChar *filesSearchFileName(FilesSearchFileNameEnum fileType); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/files_unix.cpp b/kxsldbg/kxsldbgpart/libxsldbg/files_unix.cpp new file mode 100644 index 00000000..5c1bcbff --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/files_unix.cpp @@ -0,0 +1,225 @@ + +/*************************************************************************** + files_unix.c - file functions *nix platform + specific + ------------------- + begin : Tue Jan 29 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "files.h" +#include "utils.h" +#include "options.h" + +static char *tempNames[2] = { NULL, NULL }; + + /** + * filesPlatformInit: + * + * Intialize the platform specific files module + * + * This is a platform specific interface + * + * + * Returns 1 if sucessful + * 0 otherwise + */ +int +filesPlatformInit(void) +{ + const char *namePrefix = "/tmp/"; + int nameIndex; + int result = 1; + + /* The "base" names for files files to use */ + const char *names[] = { + "_xsldbg_tmp1.txt", + "_xsldbg_tmp2.txt" + }; + + if (getenv("USER")) { + for (nameIndex = 0; nameIndex < 2; nameIndex++) { + tempNames[nameIndex] = (char*) + xmlMalloc(strlen(namePrefix) + strlen(getenv("USER")) + + strlen(names[nameIndex]) + 1); + if (tempNames[nameIndex]) { + xmlStrCpy(tempNames[nameIndex], namePrefix); + xmlStrCat(tempNames[nameIndex], getenv("USER")); + xmlStrCat(tempNames[nameIndex], names[nameIndex]); + } else { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + break; + result = 0; + } + } + } else { + xsldbgGenericErrorFunc(i18n("Error: USER environment variable is not set.\n")); + } + return result; +} + + + /** + * filesPlatformFree: + * + * Free memory used by the platform specific files module + * + * This is a platform specific interface + * + */ +void +filesPlatformFree(void) +{ + int nameIndex; + + for (nameIndex = 0; nameIndex < 2; nameIndex++) { + if (tempNames[nameIndex]) + xmlFree(tempNames[nameIndex]); + } +} + + /** + * filesTempFileName: + * @fileNumber : Number of temp file required + * + * Return the name of tempfile. For each call to this function + * with the same @fileNumber the same file name will be returned + * File number : 0 is used by cat command + * File number : 1 is used by profiling output + * + * This is a platform specific interface + * + * Returns The name of temp file to be used for temporary results, + * NULL otherwise + */ +const char * +filesTempFileName(int fileNumber) +{ + + const char *result = NULL; + + if ((fileNumber < 0) || ((fileNumber + 1) > 2)){ //don't use > (int) sizeof(tempNames), it depends on the platform and is wrong even on i586 +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to allocate temporary file %d for xsldbg\n", + fileNumber); +#endif + }else{ + result = tempNames[fileNumber]; + } + + return result; +} + + + + /** + * filesExpandName: + * @fileName : A valid fileName + * + * Converts a fileName to an absolute path + * If operating system supports it a leading "~" in the fileName + * will be converted to the user's home path. Otherwise + * the same name will be returned + * + * Returns A copy of the converted @fileName or a copy of + * the @fileName as supplied. May return NULL + */ +xmlChar * +filesExpandName(const xmlChar * fileName) +{ + xmlChar *result = NULL; + + if (fileName) { + if ((fileName[0] == '~') && getenv("HOME")) { + result = + (xmlChar *) xmlMalloc(xmlStrLen(fileName) + + strlen(getenv("HOME")) + 1); + if (result) { + xmlStrCpy(result, getenv("HOME")); + xmlStrCat(result, &fileName[1]); + } else { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + } else if (!xmlStrnCmp(fileName, "file:/", 6)){ + /* return a copy of the corrected path */ + result = filesURItoFileName(fileName); + }else{ + /* return a copy only */ + result = xmlStrdup(fileName); + } + } + return result; +} + + + /** + * filesSearchFileName: + * @fileType : Is valid + * + * Return a copy of the file name to use as an argument to searching + * + * Returns A copy of the file name to use as an argument to searching + */ +xmlChar * +filesSearchFileName(FilesSearchFileNameEnum fileType) +{ + xmlChar *result = NULL; + int type = fileType; + int preferHtml = optionsGetIntOption(OPTIONS_PREFER_HTML); + const xmlChar *baseDir = NULL; + const xmlChar *name = NULL; + static const char *searchNames[] = { + /* Note: File names here are in native format, to be appended to the + * help directory name or search results path + */ + /* First list names when prefer html is false */ + "searchresult.xml", /* input */ + "search.xsl", /* stylesheet to use */ + "searchresult.txt", /* where to put the result */ + /*Now for the names to use when prefer html is true */ + "searchresult.xml", /* input */ + "searchhtml.xsl", /* stylesheet to use */ + "searchresult.html" /* where to put the result */ + }; + + if (!optionsGetStringOption(OPTIONS_DOCS_PATH) + || !filesSearchResultsPath()) { + xsldbgGenericErrorFunc(i18n("Error: The value of the option docspath or searchresultspath is empty. See help on setoption or options command for more information.\n")); + return result; + } + + + name = (xmlChar *) searchNames[(preferHtml * 3) + type]; + switch (type) { + case FILES_SEARCHINPUT: + baseDir = filesSearchResultsPath(); + break; + + case FILES_SEARCHXSL: + baseDir = optionsGetStringOption(OPTIONS_DOCS_PATH); + break; + + case FILES_SEARCHRESULT: + baseDir = filesSearchResultsPath(); + break; + } + + result = (xmlChar*)xmlMalloc(xmlStrLen(baseDir) + xmlStrLen(name) + 1); + if (result) { + xmlStrCpy(result, baseDir); + xmlStrCat(result, name); + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/help.h b/kxsldbg/kxsldbgpart/libxsldbg/help.h new file mode 100644 index 00000000..de77a71d --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/help.h @@ -0,0 +1,73 @@ + +/*************************************************************************** + help.h - describe the help support functions + ------------------- + begin : Sun Sep 16 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef XSLDBG_HELP_H +#define XSLDBG_HELP_H + +#ifdef USE_KDE_DOCS + +/** + * Provide a help system for user + * + * @short help system support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef USE_GNOME_DOCS + +/** + * helpTop: + * @args : Is valid command or empty string + * + * Display help about the command in @arg + * + * This is a platform specific interface + * + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Display help about the command in @p arg + * + * + * This is a platform specific interface + * + * @param args Is valid or empty string + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int helpTop(const xmlChar * args); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/help_unix.cpp b/kxsldbg/kxsldbgpart/libxsldbg/help_unix.cpp new file mode 100644 index 00000000..d3e91f92 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/help_unix.cpp @@ -0,0 +1,115 @@ + +/*************************************************************************** + help.c - help system for *nix platform + ------------------- + begin : Tue Jan 29 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + * Uses docs/xsldoc.xsl docs/xsldoc.xml and xslproc to generate text + */ + +#include "xsldbg.h" +#include "options.h" +#include "utils.h" +#include "debugXSL.h" +#include "help.h" +#include "files.h" +#include <stdlib.h> +#include <kglobal.h> +#include <kstandarddirs.h> + +/** + * helpTop: + * @args : Is valid command or empty string + * + * Display help about the command in @args + * + * This is a platform specific interface + * + * Returns 1 on success, + * 0 otherwise + */ +int +helpTop(const xmlChar * args) +{ + + //Extra phrases to support translation of help display see kdewebdev/doc/xsldbg/xsldbghelp.xml and kdewebdev/kxsldbg/xsldbghelp.xsl + static const char* xsldbghelp_translations[] = + { + I18N_NOOP("xsldbg version"), + I18N_NOOP("Help document version"), + I18N_NOOP("Help not found for command") + }; + + QString xsldbgVerTxt(i18n("xsldbg version")); + QString helpDocVerTxt(i18n("Help document version")); + QString helpErrorTxt(i18n("Help not found for command")); + + + char buff[500], helpParam[100]; + + const char *docsDirPath = + (const char *) optionsGetStringOption(OPTIONS_DOCS_PATH); + int result = 0; + + if (xmlStrLen(args) > 0) { + snprintf(helpParam, 100, "--param help:%c'%s'%c", QUOTECHAR, args, + QUOTECHAR); + } else + xmlStrCpy(helpParam, ""); + if (docsDirPath && filesTempFileName(0)) { + snprintf((char *) buff, sizeof(buff), "%s %s" + " --param xsldbg_version:%c'%s'%c " + " --param xsldbgVerTxt:%c'%s'%c " + " --param helpDocVerTxt:%c'%s'%c " + " --param helpErrorTxt:%c'%s'%c " + " --output %s " + " --cd %s " + "xsldbghelp.xsl xsldbghelp.xml", + XSLDBG_BIN, helpParam, + QUOTECHAR, VERSION, QUOTECHAR, + QUOTECHAR, xsldbgVerTxt.utf8().data(), QUOTECHAR, + QUOTECHAR, helpDocVerTxt.utf8().data(), QUOTECHAR, + QUOTECHAR, helpErrorTxt.utf8().data(), QUOTECHAR, + filesTempFileName(0), + docsDirPath); + if (xslDbgShellExecute((xmlChar *) buff, optionsGetIntOption(OPTIONS_VERBOSE)) == 0) { + if (docsDirPath) + xsldbgGenericErrorFunc(i18n("Error: Unable to display help. Help files not found in %1 or xsldbg not found in path.\n").arg(docsDirPath)); /* FIXME: Comments not correct - the command is that invoked */ + else + xsldbgGenericErrorFunc(i18n("Error: Unable to find xsldbg or help files.\n")); + } else { + if (filesMoreFile((xmlChar*)filesTempFileName(0), NULL) == 1) { + result = 1; + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to print help file.\n")); + } + } + + } else { + xsldbgGenericErrorFunc(i18n("Error: No path to documentation; aborting help.\n")); +#ifdef WITH_XSLDBG_DEBUG_PROCESS +#ifdef USE_DOCS_MACRO + xsltGenericError(xsltGenericErrorContext,"MACRO has been defined look at Makefile.am\n"); +#else + xsltGenericError(xsltGenericErrorContext, + "Error: Environment variable %s is not set to the directory of xsldbg documentation.\n", + XSLDBG_DOCS_DIR_VARIABLE); +#endif +#endif + } + return result; +} + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp new file mode 100644 index 00000000..5fcbef00 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/nodeview_cmds.cpp @@ -0,0 +1,609 @@ + +/*************************************************************************** + nodeview_cmds.c - node viewing commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include <libxml/xpathInternals.h> +#include <libxml/HTMLparser.h> +#include <libxml/HTMLtree.h> +#include <ctype.h> /* for isspace*/ +#include "debugXSL.h" +#include "arraylist.h" +#include "breakpoint.h" +#include "xsldbgmsg.h" +#include "xsldbgthread.h" /* for getThreadStatus */ +#include "files.h" +#include "options.h" + + +/* ----------------------------------------- + Private function declarations for nodeview_cmds.c + -------------------------------------------*/ +static xmlChar nodeViewBuffer[500]; +static int printVariableValue = 0; + +/* + * xslDbgShellPrintNames: + * Print a name of variable found by scanning variable table + * It is used by print_variable function. + * @payload : not used + * @data : not used + * @name : the variable name + */ +void *xslDbgShellPrintNames(void *payload, + void *data, xmlChar * name); + +/** + * xslDbgCatToFile: + * @node : Is valid + * @file : Is valid + * + * Send the results of cat command in @node to @file + */ +static void xslDbgCatToFile(xmlNodePtr node, FILE * file); + + +/** + * printXPathObject: + * @item : XPath object to print + * @xPath : The XPath used to find item + * + * Print an XPath object + * + * Returns 1 on success, + * 0 otherwise + */ +static int printXPathObject(xmlXPathObjectPtr item, xmlChar* xPath); + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + +/** + * xslDbgShellPrintList: + * @ctxt: The current shell context + * @arg: What xpath to display and in UTF-8 + * @dir: If 1 print in dir mode?, + * otherwise ls mode + * + * Print list of nodes in either ls or dir format + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellPrintList(xmlShellCtxtPtr ctxt, xmlChar * arg, int dir) +{ + xmlXPathObjectPtr list; + int result = 0; + + if (!ctxt || !arg) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL arguments provided\n"); +#endif + return result; + } + + if (arg[0] == 0) { + if (dir) + xmlShellDir(ctxt, NULL, ctxt->node, NULL); + else + xmlShellList(ctxt, NULL, ctxt->node, NULL); + result = 1; /*assume that this worked */ + } else { + ctxt->pctxt->node = ctxt->node; + ctxt->pctxt->node = ctxt->node; + if (!xmlXPathNsLookup(ctxt->pctxt, (xmlChar *) "xsl")) + xmlXPathRegisterNs(ctxt->pctxt, (xmlChar *) "xsl", + XSLT_NAMESPACE); + list = xmlXPathEval(arg, ctxt->pctxt); + if (list != NULL) { + switch (list->type) { + case XPATH_NODESET:{ + int indx; + + for (indx = 0; + indx < list->nodesetval->nodeNr; indx++) { + if (dir) + xmlShellList(ctxt, NULL, + list->nodesetval-> + nodeTab[indx], NULL); + else + xmlShellList(ctxt, NULL, + list->nodesetval-> + nodeTab[indx], NULL); + } + result = 1; + break; + } + default: + xmlShellPrintXPathError(list->type, (char *) arg); + } + xmlXPathFreeObject(list); + } else { + xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(arg))); + } + ctxt->pctxt->node = NULL; + } + return result; +} + + + +/** + * xslDbgCatToFile: + * @node : Is valid + * @file : Is valid + * + * Send the results of cat command in @node to @file + */ +void +xslDbgCatToFile(xmlNodePtr node, FILE * file) +{ + if (!node || !file) + return; + + /* assume that HTML usage is enabled */ + if (node->doc->type == XML_HTML_DOCUMENT_NODE) { + if (node->type == XML_HTML_DOCUMENT_NODE) + htmlDocDump(file, (htmlDocPtr) node); + else + htmlNodeDumpFile(file, node->doc, node); + } else if (node->type == XML_DOCUMENT_NODE) { + /* turn off encoding for the moment and just dump UTF-8 + * which will be converted by xsldbgGeneralErrorFunc */ + xmlDocPtr doc = (xmlDocPtr) node; + const xmlChar *encoding = doc->encoding; + + if (encoding) { + xsldbgGenericErrorFunc(i18n("Information: Temporarily setting document's encoding to UTF-8. Previously was %1.\n").arg(xsldbgText(encoding))); + } + doc->encoding = (xmlChar *) "UTF-8"; + xmlDocDump(file, (xmlDocPtr) node); + doc->encoding = encoding; + } else { + xmlElemDump(file, node->doc, node); + } +} + + +/** + * printXPathObject: + * @item : XPath object to print + * @xPath : The XPath used to find item + * + * Print an XPath object + * + * Returns 1 on success, + * 0 otherwise + */ + +static int +printXPathObject(xmlXPathObjectPtr item, xmlChar* xPath){ + int result = 0; + if (item){ + switch (item->type) { + case XPATH_BOOLEAN: + xsltGenericError(xsltGenericErrorContext, + "= %s\n%s\n", xPath, + xmlBoolToText(item->boolval)); + result = 1; + break; + + case XPATH_NUMBER: + xsltGenericError(xsltGenericErrorContext, + "= %s\n%0g\n", xPath, item->floatval); + result = 1; + break; + + /* case XPATH_NODESET:*/ + default:{ + /* We may need to convert this XPath to a string, + plus ensure that we print required the number of + lines of text */ + int indx; + + const char *fileName = filesTempFileName(0); + FILE *file = NULL; + + if (!fileName) + break; + file = fopen(fileName, "w+"); + if (!file) { + xsldbgGenericErrorFunc(i18n("Error: Unable to save temporary results to %1.\n").arg(xsldbgText(fileName))); + break; + } else { + fprintf(file, "= %s\n", xPath); + switch(item->type){ + + case XPATH_NODESET: + if (item->nodesetval){ + for (indx = 0; + indx < item->nodesetval->nodeNr; indx++){ + xslDbgCatToFile(item->nodesetval-> + nodeTab[indx], file); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(xPath))); + } + break; + + case XPATH_STRING: + if (item->stringval) + fprintf(file, "\'%s\'", item->stringval); + else + fprintf(file, "%s", i18n("NULL string value supplied.").utf8().data()); + break; + + default:{ + xmlXPathObjectPtr tempObj = + xmlXPathObjectCopy(item); + if (tempObj) + tempObj = xmlXPathConvertString(tempObj); + if (tempObj && tempObj->stringval){ + fprintf(file, "%s", tempObj->stringval); + }else{ + fprintf(file, "%s", i18n("Unable to convert XPath to string.").utf8().data()); + } + if (tempObj) + xmlXPathFreeObject(tempObj); + } + break; + fprintf(file,"\n"); + + } /* inner switch statement */ + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + fclose(file); + file = NULL; + /* send the data to application */ + notifyXsldbgApp(XSLDBG_MSG_FILEOUT, fileName); + } else { + int lineCount = 0, gdbModeEnabled = 0; + + /* save the value of option to speed things up + * a bit */ + gdbModeEnabled = + optionsGetIntOption(OPTIONS_GDB); + rewind(file); + + /* when gdb mode is enable then only print the first + * GDB_LINES_TO_PRINT lines */ + while (!feof(file)) { + if (fgets + ((char *) nodeViewBuffer, sizeof(nodeViewBuffer), + file)) + xsltGenericError + (xsltGenericErrorContext, "%s", + nodeViewBuffer); + if (gdbModeEnabled) { + lineCount++; + /* there is an overhead of two lines + * when print expression values */ + if (lineCount == + GDB_LINES_TO_PRINT + 2) { + xsltGenericError + (xsltGenericErrorContext, + "..."); + break; + } + } + } + xsltGenericError + (xsltGenericErrorContext, "\n"); + } + if (file) + fclose(file); + result = 1; + break; + } + } + } + } + return result; +} + + +/** + * xslDbgShellCat: + * @styleCtxt: the current stylesheet context + * @ctxt: The current shell context + * @arg: The xpath to print (in UTF-8) + * + * Print the result of an xpath expression. This can include variables + * if styleCtxt is not NULL + * + * Returns 1 on success, + * 0 otherwise + */ + +int +xslDbgShellCat(xsltTransformContextPtr styleCtxt, xmlShellCtxtPtr ctxt, + xmlChar * arg) +{ + xmlXPathObjectPtr list; + int result = 0; + static const char * QUIET_STR = "-q"; + bool silenceCtxtErrors = false; + + if ((arg == NULL) || (xmlStrLen(arg) == 0)) + arg = (xmlChar *) "."; + + /* Do we quietly ingore style context errors */ + if (strncasecmp((char*)arg, QUIET_STR, strlen(QUIET_STR))== 0){ + silenceCtxtErrors = true; + arg = arg + strlen(QUIET_STR); + while (isspace(*arg)){ + arg++; + } + } + + if (!styleCtxt || !ctxt || !ctxt->node) { + if (!(!xsldbgReachedFirstTemplate && silenceCtxtErrors)) + xsldbgGenericErrorFunc(i18n("Warning: Unable to print expression. No stylesheet was properly loaded.\n")); + return 0; + } + + if ((arg == NULL) || (xmlStrLen(arg) == 0)) + arg = (xmlChar *) "."; + + ctxt->pctxt->node = ctxt->node; + if (!styleCtxt) { + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); + } else { + xmlNodePtr savenode = styleCtxt->xpathCtxt->node; + + ctxt->pctxt->node = ctxt->node; + styleCtxt->xpathCtxt->node = ctxt->node; + if (!xmlXPathNsLookup(styleCtxt->xpathCtxt, (xmlChar *) "xsl")) + xmlXPathRegisterNs(styleCtxt->xpathCtxt, (xmlChar *) "xsl", + XSLT_NAMESPACE); + list = xmlXPathEval((xmlChar *) arg, styleCtxt->xpathCtxt); + styleCtxt->xpathCtxt->node = savenode; + } + if (list != NULL) { + result = printXPathObject(list, arg); + xmlXPathFreeObject(list); + } else { + xsldbgGenericErrorFunc(i18n("Error: XPath %1 results in an empty Node Set.\n").arg(xsldbgText(arg))); + } + ctxt->pctxt->node = NULL; + return result; +} + +/* only used by xslDbgPrintNames and xslDbgPrintVariable cound number of variables */ +static int varCount; + +/* + * xslDbgShellPrintNames: + * Print a name of variable found by scanning variable table + * It is used by print_variable function. + * @payload : Global variable of type xsltStackElemPtr + * @data : not used + * @name : the variable name + */ +void * +xslDbgShellPrintNames(void *payload, + void *data, xmlChar * name) +{ + Q_UNUSED(payload); + Q_UNUSED(data); + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListQueue(payload); + } else if (payload && name) { + xmlChar * fullQualifiedName = nodeViewBuffer; + xsltStackElemPtr item = (xsltStackElemPtr)payload; + if (item->nameURI == NULL){ + snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s", item->name); + }else{ + snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s:%s", + item->nameURI, item->name); + } + if (printVariableValue == 0){ + xsldbgGenericErrorFunc(i18n(" Global %1\n").arg(xsldbgText(fullQualifiedName))); + }else{ + if (item->computed == 1){ + xsldbgGenericErrorFunc(i18n(" Global ")); + printXPathObject(item->value, fullQualifiedName); + }else if (item->tree){ + xsldbgGenericErrorFunc(i18n(" Global = %1\n").arg(xsldbgText(fullQualifiedName))); + xslDbgCatToFile(item->tree, stderr); + }else if (item->select){ + xsldbgGenericErrorFunc(i18n(" Global = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(xsldbgText(item->select))); + }else{ + /* can't find a value give only a variable name an error message */ + xsldbgGenericErrorFunc(i18n(" Global = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(i18n("Warning: No value assigned to variable.\n"))); + } + xsltGenericError(xsltGenericErrorContext, "\n\032\032\n"); + } + varCount++; + } + return NULL; +} + + + +/** + * xslDbgShellPrintVariable: + * @styleCtxt: The current stylesheet context + * @arg: The name of variable to look for '$' prefix is optional and in UTF-8 + * @type: A valid VariableTypeEnum + * + * Print the value variable specified by args. + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellPrintVariable(xsltTransformContextPtr styleCtxt, xmlChar * arg, + VariableTypeEnum type) +{ + int result = 0; + /* command argument to include both name and its value */ + static const char * FULLNAME_STR = "-f"; + /* Quietly exit if an invalid stylesheet is provided */ + static const char * QUIET_STR = "-q"; + bool silenceCtxtErrors = false; + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + varCount = 0; + /* Do we quietly ingore style context errors */ + if (strncasecmp((char*)arg, QUIET_STR, strlen(QUIET_STR))== 0){ + silenceCtxtErrors = true; + arg = arg + strlen(QUIET_STR); + while (isspace(*arg)){ + arg++; + } + } + + if (!styleCtxt) { + if (!(!xsldbgReachedFirstTemplate && silenceCtxtErrors)) + xsldbgGenericErrorFunc(i18n("Error: Debugger has no files loaded or libxslt has not reached a template.\nTry reloading files or taking more steps.\n")); + return result; + } + + /* Do we include the name as well as its value */ + if (strncasecmp((char*)arg, FULLNAME_STR, strlen(FULLNAME_STR))== 0){ + printVariableValue = 1; + arg = arg + strlen(FULLNAME_STR); + while (isspace(*arg)){ + arg++; + } + } + if (arg[0] == 0) { + /* list variables of type requested */ + if (type == DEBUG_GLOBAL_VAR) { + if (styleCtxt->globalVars) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_GLOBALVAR_CHANGED); + /* list global variables */ + xmlHashScan(styleCtxt->globalVars, + (xmlHashScanner) xslDbgShellPrintNames, + NULL); + notifyListSend(); + } else + /* list global variables */ + xmlHashScan(styleCtxt->globalVars, + (xmlHashScanner) xslDbgShellPrintNames, + NULL); + result = 1; + /* ensure that the locals follow imediately after the + * globals when in gdb mode */ + if (optionsGetIntOption(OPTIONS_GDB) == 0) + xsltGenericError(xsltGenericErrorContext, "\n"); + } else { + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) { + /* Don't show this message when running as a thread as it + * is annoying */ + xsldbgGenericErrorFunc(i18n("Error: Libxslt has not initialized variables yet; try stepping to a template.\n")); + } else { + /* send an empty list */ + notifyListStart(XSLDBG_MSG_GLOBALVAR_CHANGED); + notifyListSend(); + result = 1; + } + } + } else { + /* list local variables */ + if (styleCtxt->varsNr && styleCtxt->varsTab) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_LOCALVAR_CHANGED); + for (int i = styleCtxt->varsNr; i > styleCtxt->varsBase; i--) { + xsltStackElemPtr item = styleCtxt->varsTab[i-1]; + while (item) { + notifyListQueue(item); + item = item->next; + } + } + notifyListSend(); + } else { + xmlChar * fullQualifiedName = nodeViewBuffer; + for (int i = styleCtxt->varsNr; i > styleCtxt->varsBase; i--) { + xsltStackElemPtr item = styleCtxt->varsTab[i-1]; + while (item) { + if (item->name) { + if (item->nameURI == NULL){ + snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s", + item->name); + }else{ + + snprintf((char*)fullQualifiedName, sizeof(nodeViewBuffer), "$%s:%s", + item->nameURI, item->name); + } + if (printVariableValue == 0){ + xsldbgGenericErrorFunc(i18n(" Local %1").arg(xsldbgText(fullQualifiedName))); + }else{ + if (item->computed == 1){ + xsldbgGenericErrorFunc(i18n(" Local ")); + printXPathObject(item->value, fullQualifiedName); + }else if (item->tree){ + xsldbgGenericErrorFunc(i18n(" Local = %1\n").arg(xsldbgText(fullQualifiedName))); + xslDbgCatToFile(item->tree, stderr); + }else if (item->select){ + xsldbgGenericErrorFunc(i18n(" Local = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(xsldbgText(item->select))); + }else{ + /* can't find a value give only a variable name and an error */ + xsldbgGenericErrorFunc(i18n(" Local = %1\n%2").arg(xsldbgText(fullQualifiedName)).arg(i18n("Warning: No value assigned to variable.\n"))); + } + } + xsltGenericError(xsltGenericErrorContext, "\n\032\032\n"); + } + item = item->next; + } + } + } + result = 1; + xsltGenericError(xsltGenericErrorContext, "\n"); + } else { + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) { + /* Don't show this message when running as a thread as it + * is annoying */ + xsldbgGenericErrorFunc(i18n("Error: Libxslt has not initialized variables yet; try stepping past the xsl:param elements in the template.\n")); + } else { + /* send an empty list */ + notifyListStart(XSLDBG_MSG_LOCALVAR_CHANGED); + notifyListSend(); + result = 1; + } + } + } + } else { + /* Display the value of variable */ + if (arg[0] == '$') { + printXPathObject(xmlXPathEval(arg, styleCtxt->xpathCtxt), arg); + xsltGenericError(xsltGenericErrorContext, "\032\032\n"); + } else { + xmlStrCpy(nodeViewBuffer, "$"); + xmlStrCat(nodeViewBuffer, arg); + printXPathObject(xmlXPathEval((xmlChar*)nodeViewBuffer,styleCtxt->xpathCtxt), + (xmlChar*)nodeViewBuffer); + xsltGenericError(xsltGenericErrorContext, "\032\032\n"); + } + + } + + printVariableValue = 0; + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/option_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/option_cmds.cpp new file mode 100644 index 00000000..0bc54364 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/option_cmds.cpp @@ -0,0 +1,299 @@ + +/*************************************************************************** + option_cmds.c - implementation for option + related commands + + ------------------- + begin : Fri Feb 1 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "utils.h" +#include "options.h" +#include "xsldbgmsg.h" +#include "xsldbgthread.h" +#include "debugXSL.h" + + +/** + * xslDbgShellSetOption: + * @arg : Is valid, and in the format <NAME> <VALUE> + * + * Set the value of an option + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellSetOption(xmlChar * arg) +{ + int result = 0; + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + if (xmlStrLen(arg) > 0) { + xmlChar *opts[2]; + long optValue; + long optID; + + + if (splitString(arg, 2, opts) == 2) { + bool invertOption = false; + optID = optionsGetOptionID(opts[0]); + if ((optID == -1) && (opts[0][0] == 'n') && (opts[0][1] == 'o')){ + optID = optionsGetOptionID(&opts[0][2]); + if (optID != -1){ + // invert the value the user provides + invertOption = true; + } + } + + if (optID >= OPTIONS_FIRST_INT_OPTIONID) { + if (optID <= OPTIONS_LAST_INT_OPTIONID) { + /* handle setting integer option */ + if ((xmlStrlen(opts[1]) == 0) || + !sscanf((char *) opts[1], "%ld", &optValue)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as an option value.\n").arg(xsldbgText(opts[1]))); + } else { + if (invertOption) + optValue = !optValue; + result = optionsSetIntOption(OptionTypeEnum(optID), optValue); + } + } else { + /* handle setting a string option */ + result = optionsSetStringOption(OptionTypeEnum(optID), opts[1]); + + } + } else { + static xmlExternalEntityLoader xsldbgDefaultEntLoader = 0; + bool invertOption = false; + bool enableNet = false; + + if (!xsldbgDefaultEntLoader) + xsldbgDefaultEntLoader = xmlGetExternalEntityLoader(); + + if (xmlStrEqual(opts[0], (const xmlChar *)"nonet" )) + invertOption = true; + + if (xmlStrEqual(&opts[0][2*invertOption], (const xmlChar *)"net" )){ + if (sscanf((char *) opts[1], "%ld", &optValue)) { + if (invertOption) + optValue = !optValue; + if (optValue) + enableNet = true; + result = true; + if (enableNet) + xmlSetExternalEntityLoader(xsldbgDefaultEntLoader); + else + xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as an option value.\n").arg(xsldbgText(opts[1]))); + } + } else + xsldbgGenericErrorFunc(i18n("Error: Unknown option name %1.\n").arg(xsldbgText(opts[0]))); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("setoption")); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("setoption")); + } + + return result; +} + + + +/** + * xslDbgShellOptions: + * + * Prints out values for user options + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellOptions(void) +{ + int result = 1; + int optionIndex; + const xmlChar *optionName, *optionValue; + + /* Print out the integer options and thier values */ + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) { + for (optionIndex = OPTIONS_XINCLUDE; + optionIndex <= OPTIONS_VERBOSE; optionIndex++) { + /* skip any non-user options */ + optionName = optionsGetOptionName(OptionTypeEnum(optionIndex)); + if (optionName && (optionName[0] != '*')) { + xsldbgGenericErrorFunc(i18n("Option %1 = %2\n").arg(xsldbgText(optionName)).arg(optionsGetIntOption(OptionTypeEnum(optionIndex)))); + + } + } + /* Print out the string options and thier values */ + for (optionIndex = OPTIONS_OUTPUT_FILE_NAME; + optionIndex <= OPTIONS_DATA_FILE_NAME; optionIndex++) { + optionName = optionsGetOptionName(OptionTypeEnum(optionIndex)); + if (optionName && (optionName[0] != '*')) { + optionValue = optionsGetStringOption(OptionTypeEnum(optionIndex)); + if (optionValue) { + xsldbgGenericErrorFunc(i18n("Option %1 = \"%2\"\n").arg(xsldbgText(optionName)).arg((char*)optionValue)); + } else { + xsldbgGenericErrorFunc(i18n("Option %1 = \"\"\n").arg(xsldbgText(optionName))); + + } + } + + } + xsldbgGenericErrorFunc("\n"); + } else { + /* we are now notifying the application of the value of options */ + parameterItemPtr paramItem; + + notifyListStart(XSLDBG_MSG_INTOPTION_CHANGE); + /* send the integer options and their values */ + for (optionIndex = OPTIONS_XINCLUDE; + optionIndex <= OPTIONS_VERBOSE; optionIndex++) { + /* skip any non-user options */ + optionName = optionsGetOptionName(OptionTypeEnum(optionIndex)); + if (optionName && (optionName[0] != '*')) { + paramItem = optionsParamItemNew(optionName, 0L); + if (!paramItem) { + notifyListSend(); /* send what ever we've got so far */ + return 0; /* out of memory */ + } + paramItem->intValue = optionsGetIntOption(OptionTypeEnum(optionIndex)); + notifyListQueue(paramItem); /* this will be free later */ + } + } + + notifyListSend(); + notifyListStart(XSLDBG_MSG_STRINGOPTION_CHANGE); + /* Send the string options and thier values */ + for (optionIndex = OPTIONS_OUTPUT_FILE_NAME; + optionIndex <= OPTIONS_DATA_FILE_NAME; optionIndex++) { + optionName = optionsGetOptionName(OptionTypeEnum(optionIndex)); + if (optionName && (optionName[0] != '*')) { + paramItem = + optionsParamItemNew(optionName, + optionsGetStringOption + (OptionTypeEnum(optionIndex))); + if (!paramItem) { + notifyListSend(); /* send what ever we've got so far */ + return 0; /* out of memory */ + } else + notifyListQueue(paramItem); /* this will be freed later */ + } + } + notifyListSend(); + } + + return result; +} + + + /** + * xslDbgShellShowWatches: + * @styleCtxt: the current stylesheet context + * @ctxt: The current shell context + * @showWarnings : If 1 then showWarning messages, + * otherwise do not show warning messages + * + * Print the current watches and their values + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellShowWatches(xsltTransformContextPtr styleCtxt, + xmlShellCtxtPtr ctx,int showWarnings) +{ + int result = 0, counter; + xmlChar* watchExpression; + if ((showWarnings == 1) && (arrayListCount(optionsGetWatchList()) == 0)){ + xsldbgGenericErrorFunc(i18n("\tNo expression watches set.\n")); + } + for ( counter = 0; + counter < arrayListCount(optionsGetWatchList()); + counter++){ + watchExpression = (xmlChar*)arrayListGet(optionsGetWatchList(), counter); + if (watchExpression){ + xsldbgGenericErrorFunc(i18n(" WatchExpression %1 ").arg(counter + 1)); + result = xslDbgShellCat(styleCtxt, ctx, watchExpression); + }else + break; + } + + return result; +} + + + /** + * xslDbgShellAddWatch: + * @arg : A valid xPath of expression to watch the value of + * + * Add expression to list of expressions to watch value of + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellAddWatch(xmlChar* arg) +{ + int result = 0; + if (arg){ + trimString(arg); + result = optionsAddWatch(arg); + if (!result) + xsldbgGenericErrorFunc(i18n("Error: Unable to add watch expression \"%1\". It already has been added or it cannot be watched.\n").arg(xsldbgText(arg))); + } + return result; +} + + /** + * xslDbgShellDeleteWatch: + * @arg : A watch ID to remove or "*" to remove all watches + * + * Delete a given watch ID from our list of expressions to watch + * + * Returns 1 on success, + * 0 otherwise + */ + int xslDbgShellDeleteWatch(xmlChar* arg) +{ + int result = 0; + long watchID; + if (arg){ + trimString(arg); + if (arg[0] == '*') { + arrayListEmpty(optionsGetWatchList()); + }else if ((xmlStrlen(arg) == 0) || + !sscanf((char *) arg, "%ld", &watchID)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a watchID.\n").arg(xsldbgText(arg))); + return result; + } else { + result = optionsRemoveWatch(watchID); + if (!result) + xsldbgGenericErrorFunc(i18n("Error: Watch expression %1 does not exist.\n").arg(watchID)); + } + } + return result; +} + + + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/options.cpp b/kxsldbg/kxsldbgpart/libxsldbg/options.cpp new file mode 100644 index 00000000..9f667eb3 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/options.cpp @@ -0,0 +1,902 @@ + +/*************************************************************************** + options.c - provide the implementation for option + related functions + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "xsldbgthread.h" +#include "options.h" +#include "arraylist.h" +#include "xsldbgmsg.h" +#include "utils.h" +#include <kglobal.h> +#include <kstandarddirs.h> +#include <qfileinfo.h> +#include <qstringlist.h> + + +/* keep track of our integer/boolean options */ +static int intOptions[OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID + 1]; + +/* make use that use of options are safe by only copying + critical values from intVolitleOptions just before stylesheet is started + */ +int intVolitileOptions[OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID + 1]; + +/* keep track of our string options */ +static xmlChar *stringOptions[OPTIONS_LAST_STRING_OPTIONID - + OPTIONS_FIRST_STRING_OPTIONID + 1]; + +/* keep track of our parameters */ +static arrayListPtr parameterList; + +/* what are the expressions to be printed out when xsldbg stops */ +static arrayListPtr watchExpressionList; + + +/* the names for our options + Items that start with *_ are options that CANNOT be used by the user + Once you set an option you need to give a run command to activate + new settings */ +const char *optionNames[] = { + "xinclude", /* Use xinclude during xml parsing */ + "docbook", /* Use of docbook sgml parsing */ + "timing", /* Use of timing */ + "profile", /* Use of profiling */ + "valid", /* Enable file validation */ + "out", /* Enable output to stdout */ + "html", /* Enable the use of html parsing */ + "debug", /* Enable the use of xml tree debugging */ + "shell", /* Enable the use of debugger shell */ + "gdb", /* Run in gdb modem prints more messages */ + "preferhtml", /* Prefer html output for search results */ + "autoencode", /* Try to use the encoding from the stylesheet */ + "utf8input", /* All input from "user" will be in UTF-8 */ + "stdout", /* Print all error messages to stdout, + * normally error messages go to stderr */ + "autorestart", /* When finishing the debug of a XSLT script + automaticly restart at the beginning */ + "verbose", /* Be verbose with messages */ + "repeat", /* The number of times to repeat */ + "*_trace_*", /* Trace execution */ + "*_walkspeed_*", /* How fast do we walk through code */ + "catalogs", /* do we use catalogs in SGML_CATALOG_FILES */ + "output", /* what is the output file name */ + "source", /* The stylesheet source to use */ + "docspath", /* Path of xsldbg's documentation */ + "catalognames", /* The names of the catalogs to use when the catalogs option is active */ + "encoding", /* What encoding to use for standard output */ + "searchresultspath", /* Where do we store the results of search */ + "data", /* The xml data file to use */ + NULL /* indicate end of list */ +}; + + + +// find the translated help documentation directory +// langLookupDir code modified from langLookup function in kdebase/khelpcenter/view.cpp + +static QString langLookupDir( const QString &fname ) +{ + QStringList search; + + // assemble the local search paths + QStringList localDoc = KGlobal::dirs()->resourceDirs("html"); + // also look in each of the KDEDIR paths + QString kdeDirs = getenv("KDEDIRS"); + QStringList kdeDirsList = QStringList::split(":", kdeDirs); + if (!kdeDirs.isEmpty() && !kdeDirsList.isEmpty()){ + for (QStringList::iterator it = kdeDirsList.begin(); it != kdeDirsList.end(); it++) + localDoc.append((*it) + "/share/doc/HTML/") ; + } + + // look up the different languages + for (uint id=0; id < localDoc.count(); id++) + { + QStringList langs = KGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( "C" ); + QStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(QString("%1%2/%3/%4").arg(localDoc[id]).arg(*lang).arg("xsldbg").arg(fname)); + } + + // try to locate the file + QStringList::Iterator it; + for (it = search.begin(); it != search.end(); ++it) + { + QString baseDir = (*it).left((*it).findRev('/')) ; + QFileInfo info(baseDir + "/"+ fname); + if (info.exists() && info.isFile() && info.isReadable()) + return baseDir; + } + + return QString::null; +} + + +/** + * optionsInit: + * + * Intialize the options module + * + * Returns 1 on success, + * 0 otherwise + */ +int +optionsInit(void) +{ + int optionId; + + for (optionId = 0; + optionId <= OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID; optionId++) { + intOptions[optionId] = 0; + intVolitileOptions[optionId] = 0; + } + + for (optionId = 0; + optionId <= OPTIONS_LAST_STRING_OPTIONID - OPTIONS_FIRST_STRING_OPTIONID; + optionId++) { + stringOptions[optionId] = NULL; + } + + /* init our parameter list */ + parameterList = arrayListNew(10, (freeItemFunc) optionsParamItemFree); + + /* setup the docs path */ + optionsSetStringOption(OPTIONS_DOCS_PATH, (const xmlChar*)(langLookupDir("xsldbghelp.xml").utf8().data())); + + optionsSetIntOption(OPTIONS_TRACE, TRACE_OFF); + optionsSetIntOption(OPTIONS_WALK_SPEED, WALKSPEED_STOP); + /* always try to use encoding if found */ + optionsSetIntOption(OPTIONS_AUTOENCODE, 1); + /* start up with auto restart turned off */ + optionsSetIntOption(OPTIONS_AUTORESTART, 0); + /* start up with gdb mode turned on */ + optionsSetIntOption(OPTIONS_GDB, 1); + /* start up with output mode turned on */ + optionsSetIntOption(OPTIONS_OUT, 1); + /* start up with validation turned on */ + optionsSetIntOption(OPTIONS_VALID, 1); + /* start up with xinclude turned on */ + optionsSetIntOption(OPTIONS_XINCLUDE, 1); + + /* set output default as standard output. Must be changed if not using + * xsldbg's command line. Or the tty command is used */ + optionsSetStringOption(OPTIONS_OUTPUT_FILE_NAME, NULL); + + /* init our list of expressions to watch which are only a list of + strings ie xmlChar*'s */ + watchExpressionList = arrayListNew(10, (freeItemFunc) xmlFree); + + return (parameterList && watchExpressionList); +} + + +/** + * optionsFree: + * + * Free memory used by the options module + */ +void +optionsFree(void) +{ + int string_option; + + for (string_option = OPTIONS_FIRST_STRING_OPTIONID; + string_option <= OPTIONS_LAST_STRING_OPTIONID; string_option++) { + optionsSetStringOption(OptionTypeEnum(string_option), NULL); + } + + /* Free up memory used by parameters and watches*/ + arrayListFree(parameterList); + arrayListFree(watchExpressionList); + parameterList = NULL; + watchExpressionList = NULL; +} + + + /** + * optionsGetOptionID: + * @optionName : A valid option name see documentation for "setoption" + * command and program usage documentation + * + * Find the option id for a given option name + * + * Returns The optionID for @optionName if successful, where + * OPTIONS_FIRST_OPTIONID<= optionID <= OPTIONS_LAST_OPTIONID, + * otherwise returns -1 + */ +int +optionsGetOptionID(xmlChar * optionName) +{ + int result = -1; + int optID = lookupName(optionName, (xmlChar **) optionNames); + + if (optID >= 0) { + result = optID + OPTIONS_FIRST_OPTIONID; + } + + return result; +} + + + /** + * optionsGetOptionName: + * @ID : A valid option ID + * + * Get the name text for an option + * + * Returns The name of option if @ID is valid, + * NULL otherwise + */ +const xmlChar * +optionsGetOptionName(OptionTypeEnum ID) +{ + const xmlChar *result = 0; + if ( (ID >= OPTIONS_FIRST_OPTIONID) && (ID <= OPTIONS_LAST_OPTIONID)){ + /* An option ID is always valid at the moment */ + result = (const xmlChar *) optionNames[ID - OPTIONS_FIRST_OPTIONID]; + } + + return result; +} + + +/** + * optionsSetIntOption: + * @optionType: A valid boolean option + * @value: 1 to enable, 0 otherwise + * + * Set the state of a boolean xsldbg option to @value + * + * Returns 1 on success, + * 0 otherwise + */ +int +optionsSetIntOption(OptionTypeEnum optionType, int value) +{ + int type = optionType, result = 1; + + if ((type >= OPTIONS_FIRST_INT_OPTIONID) && (type <= OPTIONS_LAST_INT_OPTIONID)) { + /* make sure that use of options are safe by only copying + * critical values from intVolitleOptions just before + * stylesheet is started + */ + intVolitileOptions[type - OPTIONS_FIRST_INT_OPTIONID] = value; + + /* the following types must be activated imediately */ + switch (type) { + + case OPTIONS_TRACE: + case OPTIONS_WALK_SPEED: + case OPTIONS_GDB: + intOptions[type - OPTIONS_FIRST_INT_OPTIONID] = value; + break; + + default: + break; + } + } else { + if ((type >= OPTIONS_FIRST_OPTIONID) && (type <= OPTIONS_LAST_OPTIONID)){ + xsldbgGenericErrorFunc(i18n("Error: Option %1 is not a valid boolean/integer option.\n").arg(xsldbgText(optionNames[type - OPTIONS_FIRST_OPTIONID]))); + }else{ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsldbgGenericErrorFunc(QString("Error: Invalid arguments for the command %1.\n").arg("setoption")); +#endif + } + result = 0; + } + return result; +} + + +/** + * optionsGetIntOption: + * @optionType: A valid boolean option to query + * + * Return the state of a boolean option + * + * Returns The state of a boolean xsldbg option. + * ie 1 for enabled , 0 for disabled + */ +int +optionsGetIntOption(OptionTypeEnum optionType) +{ + int type = optionType, result = 0; + + if ((type >= OPTIONS_FIRST_INT_OPTIONID) && (type <= OPTIONS_LAST_INT_OPTIONID)) { + result = intOptions[type - OPTIONS_FIRST_INT_OPTIONID]; + } else { + if ((type >= OPTIONS_FIRST_OPTIONID) && (type <= OPTIONS_LAST_OPTIONID)){ + xsldbgGenericErrorFunc(i18n("Error: Option %1 is not a valid boolean/integer option.\n").arg(xsldbgText(optionNames[type - OPTIONS_FIRST_OPTIONID]))); + }else{ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsldbgGenericErrorFunc(QString("Error: Invalid arguments for the command %1.\n").arg("options")); +#endif + } + } + return result; +} + + + +/** + * optionsSetStringOption: + * @optionType: A valid string option + * @value: The value to copy + * + * Set value for a string xsldbg option to @value. + * Any memory used currently by option @optionType will be freed + * + * Returns 1 on success, + * 0 otherwise + */ +int +optionsSetStringOption(OptionTypeEnum optionType, const xmlChar * value) +{ + int type = optionType, result = 0; + + if ((type >= OPTIONS_FIRST_STRING_OPTIONID) && + (type <= OPTIONS_LAST_STRING_OPTIONID)) { + int optionId = type - OPTIONS_FIRST_STRING_OPTIONID; + + if (stringOptions[optionId]) + xmlFree(stringOptions[optionId]); + if (value) + stringOptions[optionId] = + (xmlChar *) xmlMemStrdup((char *) value); + else /* we want to be able to provide a NULL value */ + stringOptions[optionId] = NULL; + result = 1; + } else{ + if ((type >= OPTIONS_FIRST_OPTIONID) && (type <= OPTIONS_LAST_OPTIONID)){ + xsldbgGenericErrorFunc(i18n("Error: Option %1 is not a valid string xsldbg option.\n").arg(xsldbgText(optionNames[type - OPTIONS_LAST_OPTIONID]))); + }else{ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsldbgGenericErrorFunc(QString("Error: Invalid arguments for the command %1.\n").arg("setoption")); +#endif + } + } + return result; +} + + +/** + * optionsGetStringOption: + * @optionType: A valid string option + * + * Get value for a string xsldbg option of @optionType + + * Returns current option value which may be NULL + */ +const xmlChar * +optionsGetStringOption(OptionTypeEnum optionType) +{ + int type = optionType; + xmlChar *result = NULL; + + if ((type >= OPTIONS_FIRST_STRING_OPTIONID) && + (type <= OPTIONS_LAST_STRING_OPTIONID)) { + int optionId = type - OPTIONS_FIRST_STRING_OPTIONID; + result = stringOptions[optionId]; + } else{ + if ((type >= OPTIONS_FIRST_OPTIONID) && (type <= OPTIONS_LAST_OPTIONID)){ + xsldbgGenericErrorFunc(i18n("Error: Option %1 is not a valid string xsldbg option.\n").arg(xsldbgText(optionNames[type - OPTIONS_FIRST_OPTIONID]))); + }else{ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsldbgGenericErrorFunc(QString("Error: Invalid arguments for the command %1.\n").arg("options")); +#endif + } + } + return result; +} + + + /** + * optionsCopyVolitleOptions: + * + * Copy volitile options to the working area for xsldbg to be used + * just after xsldbg starts its processing loop + */ +void +optionsCopyVolitleOptions(void) +{ + int optionId; + + for (optionId = 0; + optionId <= OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID; optionId++) { + intOptions[optionId] = intVolitileOptions[optionId]; + } +} + + +/** + * optionsParamItemNew: + * @name: Is valid + * @value: Is valid + * + * Create a new libxslt parameter item + * Returns non-null if sucessful + * NULL otherwise + */ +parameterItemPtr +optionsParamItemNew(const xmlChar * name, const xmlChar * value) +{ + parameterItemPtr result = NULL; + + if (name) { + result = (parameterItem *) xmlMalloc(sizeof(parameterItem)); + if (result) { + result->name = (xmlChar *) xmlMemStrdup((char *) name); + if (value) + result->value = (xmlChar *) xmlMemStrdup((char *) value); + else + result->value = (xmlChar *) xmlMemStrdup(""); + result->intValue = -1; + } + } + return result; +} + + +/** + * optionsParamItemFree: + * @item: Is valid + * + * Free memory used by libxslt parameter item @item + */ +void +optionsParamItemFree(parameterItemPtr item) +{ + if (item) { + if (item->name) + xmlFree(item->name); + if (item->value) + xmlFree(item->value); + xmlFree(item); + } + +} + + +/** + * optionsGetParamItemList: + * + * Return the list of libxlt parameters + * + * Returns The list of parameters to provide to libxslt when doing + * stylesheet transformation if successful + * NULL otherwise + */ +arrayListPtr +optionsGetParamItemList(void) +{ + return parameterList; +} + + +/** + * optionsPrintParam: + * @paramId: 0 =< paramID < arrayListCount(getParamList()) + * + * Print parameter information + * + * Returns 1 on success, + * 0 otherwise + */ +int +optionsPrintParam(int paramId) +{ + int result = 0; + parameterItemPtr paramItem = + (parameterItemPtr) arrayListGet(optionsGetParamItemList(), + paramId); + + if (paramItem && paramItem->name && paramItem->value) { + xsldbgGenericErrorFunc(i18n(" Parameter %1 %2=\"%3\"\n").arg(paramId).arg(xsldbgText(paramItem->name)).arg(xsldbgText(paramItem->value))); + result = 1; + } + return result; +} + + +/** + * optionsPrintParamList: + * + * Prints all items in parameter list + * + * Returns 1 on success, + * 0 otherwise + */ +int +optionsPrintParamList(void) +{ + int result = 1; + int paramIndex = 0; + int itemCount = arrayListCount(optionsGetParamItemList()); + + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + if (itemCount > 0) { + while (result && (paramIndex < itemCount)) { + result = optionsPrintParam(paramIndex++); + } + } + } else { + if (itemCount > 0) { + xsltGenericError(xsltGenericErrorContext, "\n"); + while (result && (paramIndex < itemCount)) { + result = optionsPrintParam(paramIndex++); + } + } else + xsldbgGenericErrorFunc(i18n("\nNo parameters present.\n")); + } + return result; +} + + + /** + * optionsNode: + * @optionType : Is valid, option to convert to a xmlNodePtr + * + * Convert option into a xmlNodePtr + * + * Returns the option @optionType as a xmlNodePtr if successful, + * NULL otherwise + */ +xmlNodePtr +optionsNode(OptionTypeEnum optionType) +{ + xmlNodePtr node = NULL; + char numberBuffer[10]; + int result = 1; + + numberBuffer[0] = '\0'; + if (optionType <= OPTIONS_VERBOSE) { + /* integer option */ + node = xmlNewNode(NULL, (xmlChar *) "intoption"); + if (node) { + snprintf(numberBuffer, sizeof(numberBuffer), "%d", + optionsGetIntOption(optionType)); + result = result && (xmlNewProp + (node, (xmlChar *) "name", + (xmlChar *) optionNames[optionType - + OPTIONS_XINCLUDE]) + != NULL); + if (result) + result = result && (xmlNewProp(node, (xmlChar *) "value", + (xmlChar *) numberBuffer) != + NULL); + if (!result) { + xmlFreeNode(node); + node = NULL; + } + + } + } else { + /* string option */ + node = xmlNewNode(NULL, (xmlChar *) "stringoption"); + if (node) { + result = result && (xmlNewProp + (node, (xmlChar *) "name", + (xmlChar *) optionNames[optionType - + OPTIONS_XINCLUDE]) + != NULL); + if (result) { + if (optionsGetStringOption(optionType)) + result = result && (xmlNewProp + (node, (xmlChar *) "value", + optionsGetStringOption + (optionType)) != NULL); + else + result = result && (xmlNewProp + (node, (xmlChar *) "value", + (xmlChar *) "") != NULL); + } + + if (!result) { + xmlFreeNode(node); + node = NULL; + } + + } + } + return node; +} + + + /** + * optionsReadDoc: + * @doc : Is valid xsldbg config document, in the format as indicated + * by config.dtd + * + * Read options from document provided. + * + * Returns 1 if able to read @doc and load options found, + * 0 otherwise + */ +int +optionsReadDoc(xmlDocPtr doc) +{ + int result = 1; + xmlChar *name, *value; + int optID; + xmlNodePtr node; + + /* very primative search for config node + * we skip the DTD and then go straight to the first child of + * config node */ + if (doc && doc->children->next && doc->children->next->children) { + /* find the first configuration option */ + node = doc->children->next->children; + while (node && result) { + if (node->type == XML_ELEMENT_NODE) { + if (xmlStrCmp(node->name, "intoption") == 0) { + name = xmlGetProp(node, (xmlChar *) "name"); + value = xmlGetProp(node, (xmlChar *) "value"); + if (name && value && (atoi((char *) value) >= 0)) { + optID = lookupName(name, (xmlChar **) optionNames); + if (optID >= 0) + result = + optionsSetIntOption(OptionTypeEnum(optID + OPTIONS_XINCLUDE), + atoi((char *) value)); + } + if (name) + xmlFree(name); + if (value) + xmlFree(value); + } else if (xmlStrCmp(node->name, "stringoption") == 0) { + name = xmlGetProp(node, (xmlChar *) "name"); + value = xmlGetProp(node, (xmlChar *) "value"); + if (name && value) { + optID = lookupName(name, (xmlChar **) optionNames); + if (optID >= 0) + result = + optionsSetStringOption(OptionTypeEnum(optID + OPTIONS_XINCLUDE), + value); + } + if (name) + xmlFree(name); + if (value) + xmlFree(value); + } + } + node = node->next; + } + } + return result; +} + + + +/** + * optionsSavetoFile: + * @fileName : Must be NON NULL be a local file that can be written to + * + * Save configuation to file specified + * + * Returns 1 if able to save options to @fileName, + * 0 otherwise + */ +int +optionsSavetoFile(xmlChar * fileName) +{ + int result = 0; + int optionIndex = 0; + xmlDocPtr configDoc; + xmlNodePtr rootNode; + xmlNodePtr node = NULL; + + if (!fileName) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL file name provided\n"); +#endif + return result; + } + + configDoc = xmlNewDoc((xmlChar *) "1.0"); + rootNode = xmlNewNode(NULL, (xmlChar *) "config"); + + if (configDoc && rootNode) { + xmlCreateIntSubset(configDoc, (xmlChar *) "config", (xmlChar *) + "-//xsldbg//DTD config XML V1.0//EN", + (xmlChar *) "config.dtd"); + xmlAddChild((xmlNodePtr) configDoc, rootNode); + + /*now to do the work of adding configuration items */ + for (optionIndex = OPTIONS_XINCLUDE; + optionIndex <= OPTIONS_DATA_FILE_NAME; optionIndex++) { + result = 1; + if (optionNames[optionIndex - OPTIONS_XINCLUDE][0] == '*') + continue; /* don't save non user options */ + + node = optionsNode(OptionTypeEnum(optionIndex)); + if (node) + xmlAddChild(rootNode, node); + else { + result = 0; + break; + } + } + + if (result) { + /* so far so good, now to serialize it to disk */ + if (!xmlSaveFormatFile((char *) fileName, configDoc, 1)) + result = 0; + } + + xmlFreeDoc(configDoc); + } else { + + if (configDoc) + xmlFreeDoc(configDoc); + + if (rootNode) + xmlFreeNode(rootNode); + + } + + return result; +} + + + + /** + * optionsConfigState: + * @value : Is valid + * + * Set/Get the state of configuration loading/saving + * + * Returns The current/new value of configuration flag. Where + * @value means: + * OPTIONS_CONFIG_READVALUE : No change return current + * value of read configuration flag + * OPTIONS_CONFIG_WRITING : Clear flag and return + * OPTIONS_CONFIG_WRITING which mean configuration + * file is being written + * OPTIONS_CONFIG_READING : Set flag and return + * OPTIONS_CONFIG_READING, which means configuration + * file is being read + * OPTIONS_CONFIG_IDLE : We are neither reading or writing + * configuration and return OPTIONS_CONFIG_IDLE + */ +int +optionsConfigState(OptionsConfigState value) +{ + int result = OPTIONS_CONFIG_IDLE; + + /* work around as some compiler refuse to switch on enums */ + int configValue = value; + + /* hold the current state of configuration reading/writing */ + static int configState = OPTIONS_CONFIG_IDLE; + + switch (configValue) { + case OPTIONS_CONFIG_READVALUE: + /* read the current value only */ + result = configState; + break; + + case OPTIONS_CONFIG_READING: + case OPTIONS_CONFIG_WRITING: + /* update the value */ + result = configValue; + configState = configValue; + break; + } + + return result; +} + + /** + * optionsAddWatch: + * @xPath : A valid xPath to evaluate in a context and + * has not already been addded + * + * Add xPath to be evaluated and printed out each time the debugger stops + * + * Returns 1 if able to add xPath to watched + * 0 otherwise + */ + int optionsAddWatch(const xmlChar* xPath) +{ + int result = 0; + if (!xPath || (xmlStrlen(xPath) == 0)){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Invalid XPath supplied\n"); +#endif + } else{ + if (optionsGetWatchID(xPath) == 0){ + xmlChar * nameCopy = xmlStrdup(xPath); + if (nameCopy){ + arrayListAdd(watchExpressionList, nameCopy); + result = 1; + } + } + } + + return result; +} + + + /** + * optionsGetWatchID: + * @xPath : A valid watch expression that has already been added + * + * Finds the ID of watch expression previously added + * + * Returns 0 if not found, + * otherwise returns the ID of watch expression + */ + int optionsGetWatchID(const xmlChar* xPath) +{ + int result = 0, counter; + xmlChar* watchExpression; + if (!xPath){ +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Invalid xPath supplied\n"); +#endif + } else{ + for ( counter = 0; + counter < arrayListCount(watchExpressionList); + counter++){ + watchExpression = (xmlChar*)arrayListGet(watchExpressionList, counter); + if (watchExpression){ + if (xmlStrEqual(xPath, watchExpression)){ + result = counter + 1; + break; + } + }else{ + break; + } + } + } + + return result; +} + + /** + * optionsRemoveWatch: + * @watchID : A valid watchID as indicated by last optionsPrintWatches + * @showWarnings : Print more error messages if 1, + * print less if 0 + * + * Remove the watch with given ID from our list of expressions to watch + * + * Returns 1 if able to remove to watch expression + * 0 otherwise + */ + int optionsRemoveWatch(int watchID) +{ + return arrayListDelete(watchExpressionList, watchID - 1); +} + + /** + * optionsGetWatchList: + * + * Return the current list of expressions to watch + * + * Return the current list of expressions to watch + */ + arrayListPtr optionsGetWatchList() +{ + return watchExpressionList; +} + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/options.h b/kxsldbg/kxsldbgpart/libxsldbg/options.h new file mode 100644 index 00000000..60ab69d3 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/options.h @@ -0,0 +1,476 @@ + +/*************************************************************************** + options.h - define option related functions + ------------------- + begin : Sat Nov 10 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include "arraylist.h" + +/** + * Provide a mechanism to change option. The Options structure is not in use, + * it has been added so that kdoc puts all option related + * functions together + * + * @short file support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ + +/* We want skip most of these includes when building documentation */ +#ifndef BUILD_DOCS +#include <libxslt/xslt.h> +#endif + +/* --------------------------------------- + Misc options +-------------------------------------------*/ + +/** The largest number lines of text can be print print printing documents + This is equivant to gdb shorting of evaluation values + */ +#define GDB_LINES_TO_PRINT 3 + + + enum OptionsConfigState { + OPTIONS_CONFIG_READVALUE = -1, /* Read configuration flag */ + OPTIONS_CONFIG_READING = 1, /* Configuration file is being read */ + OPTIONS_CONFIG_WRITING, /* Configuration file is being written */ + OPTIONS_CONFIG_IDLE /* We are neither reading or writing */ + }; + + enum OptionTypeEnum { + OPTIONS_XINCLUDE = 500, /* Use xinclude during xml parsing */ + OPTIONS_FIRST_BOOL_OPTIONID = OPTIONS_XINCLUDE, + OPTIONS_FIRST_INT_OPTIONID = OPTIONS_XINCLUDE, + OPTIONS_FIRST_OPTIONID = OPTIONS_XINCLUDE, + OPTIONS_DOCBOOK, /* Use of docbook sgml parsing */ + OPTIONS_TIMING, /* Use of timing */ + OPTIONS_PROFILING, /* Use of profiling */ + OPTIONS_VALID, /* Enables file validation */ + OPTIONS_OUT, /* Enables output to stdout */ + OPTIONS_HTML, /* Enable the use of html parsing */ + OPTIONS_DEBUG, /* Enable the use of xml tree debugging */ + OPTIONS_SHELL, /* Enable the use of debugger shell */ + OPTIONS_GDB, /* Run in gdb modem prints more messages) */ + OPTIONS_PREFER_HTML, /* Prefer html output for search results */ + OPTIONS_AUTOENCODE, /* try to use the encoding from the stylesheet */ + OPTIONS_UTF8_INPUT, /* All input from user is in UTF-8.This normaly + * used when xsldbg is running as a thread */ + OPTIONS_STDOUT, /* Print all error messages to stdout, + * normally error messages go to stderr */ + OPTIONS_AUTORESTART, /* When finishing the debug of a XSLT script + automaticly restart at the beginning */ + OPTIONS_VERBOSE, /* Be verbose with messages */ + OPTIONS_LAST_BOOL_OPTIONID = OPTIONS_VERBOSE, + OPTIONS_REPEAT, /* The number of times to repeat */ + OPTIONS_TRACE, /* Trace execution */ + OPTIONS_WALK_SPEED, /* How fast do we walk through code */ + OPTIONS_CATALOGS, /* Get the catalogs from SGML_CATALOG_FILES and + * store it in OPTIONS_CATALOG_NAMES */ + OPTIONS_LAST_INT_OPTIONID = OPTIONS_CATALOGS, + OPTIONS_OUTPUT_FILE_NAME, /* what is the output file name */ + OPTIONS_FIRST_STRING_OPTIONID = OPTIONS_OUTPUT_FILE_NAME, + OPTIONS_SOURCE_FILE_NAME, /* the stylesheet source to use */ + OPTIONS_DOCS_PATH, /* path of xsldbg's documentation */ + OPTIONS_CATALOG_NAMES, /* the names of the catalogs to use when catalogs option is active */ + OPTIONS_ENCODING, /* What encoding to use for standard output */ + OPTIONS_SEARCH_RESULTS_PATH, /* Where do we store the results of searching */ + OPTIONS_DATA_FILE_NAME, /* xml data file to use */ + OPTIONS_LAST_STRING_OPTIONID = OPTIONS_DATA_FILE_NAME, + OPTIONS_LAST_OPTIONID = OPTIONS_DATA_FILE_NAME + }; + + /* define what tracing is used */ + enum TraceModeEnum { + TRACE_OFF = 600, /* disable tracing */ + TRACE_ON, /* enable tracing */ + TRACE_RUNNING, /* tracing is running */ + TRACE_FINISHED /* not needed but just in case */ + }; + + /* what speeds can we walk through a stylesheet */ + /* must start walkSpeed enums from zero !! */ + enum WalkSpeedEnum { + WALKSPEED_0 = 0, + WALKSPEED_STOP = WALKSPEED_0, + WALKSPEED_1, + WALKSPEED_FAST = WALKSPEED_1, + WALKSPEED_2, + WALKSPEED_3, + WALKSPEED_4, + WALKSPEED_5, + WALKSPEED_NORMAL = WALKSPEED_5, + WALKSPEED_6, + WALKSPEED_7, + WALKSPEED_8, + WALKSPEED_9, + WALKSPEED_SLOW = WALKSPEED_9 + }; + +extern int intVolitileOptions[OPTIONS_LAST_INT_OPTIONID - OPTIONS_FIRST_INT_OPTIONID + 1]; + +/* how many microseconds is each speed increase worth*/ +#define WALKDELAY 250000 + + +/* for non win32 environments see the macro in xsldebugger/Makefile.am + Win32 type systems see macro in libxslt/xsltwin32config.h +*/ +#ifdef __riscos + +/* The environment variable name we are going to use is the readable version + of the application name */ +#define XSLDBG_DOCS_DIR_VARIABLE "XSLDebugDocs$Dir" +#else + +/* The environment variable name on normal systems */ +#define XSLDBG_DOCS_DIR_VARIABLE "XSLDBG_DOCS_DIR" +#endif + +/* used to keep track of libxslt paramters + see Parameter related options near end of file +*/ + typedef struct _parameterItem parameterItem; + typedef parameterItem *parameterItemPtr; + struct _parameterItem { + xmlChar *name; /* libxslt parameter name */ + xmlChar *value; /* libxslt parameter value */ + int intValue; /* reserved */ + }; + + + +/** + * Initialized the options module + * + * @returns 1 on success, + * 0 otherwise + */ + int optionsInit(void); + + + +/** + * Free memory used by the options module + */ + void optionsFree(void); + + + /** + * Find the option id for a given option name + * + * @returns The optionID for @optionName if successful, where + * OPTIONS_XINCLUDE<= optionID <= OPTIONS_DATA_FILE_NAME, + * otherwise returns -1 + * + * @param optionName A valid option name see documentation for "setoption" + * command and program usage documentation + * + */ + int optionsGetOptionID(xmlChar * optionName); + + + + /** + * Get the name text for an option + * + * Returns The name of option if @ID is valid, + * NULL otherwise + * + * @param ID A valid option ID + * + */ + const xmlChar *optionsGetOptionName(OptionTypeEnum ID); + + +/** + * Set the value of an integer xsldbg option to @p value + * + * @returns 1 on success, + * 0 otherwise + * + * @param optionType Is a valid integer option + * @param value Is the valid to adopt + */ + int optionsSetIntOption(OptionTypeEnum optionType, int value); + + +/** + * @returns The state of a integer xsldbg option + * + * @param optionType Is a valid integer option + */ + int optionsGetIntOption(OptionTypeEnum optionType); + + +/** + * Set value for a string xsldbg option to @p value. + * Any memory used currently by option @p optionType will be freed + * + * @returns 1 on success, + * 0 otherwise + * + * @param optionType A valid string option + * @param value The value to copy + */ + int optionsSetStringOption(OptionTypeEnum optionType, + const xmlChar * value); + + +/** + * Get value for a string xsldbg option of @p optionType + * + * @returns current option value which may be NULL + * + * @param optionType A valid string option + */ + const xmlChar *optionsGetStringOption(OptionTypeEnum optionType); + + + /** + * Copy volitile options to the working area for xsldbg to be used + * just after xsldbg starts its processing loop + */ + void optionsCopyVolitleOptions(void); + + + +/*--------------------------------------------- + Parameter related options +-------------------------------------------------*/ + + +/** + * Return the list of libxlt parameters + * + * @returns The list of parameters to provide to libxslt when doing + * stylesheet transformation if successful + * NULL otherwise + */ + arrayListPtr optionsGetParamItemList(void); + + + +/** + * Create a new libxslt parameter item + * + * @returns non-null if sucessful + * NULL otherwise + * + * @param name Is valid + * @param value Is valid + */ + parameterItemPtr optionsParamItemNew(const xmlChar * name, + const xmlChar * value); + + +/** + * Free memory used by libxslt parameter item @p item + * + * @param item Is valid + */ + void optionsParamItemFree(parameterItemPtr item); + + +/** + * Prints all items in parameter list + * + * @returns 1 on success, + * 0 otherwise + */ + int optionsPrintParam(int paramId); + + + +/** + * Prints all items in parameter list + * + * @returns 1 on success, + * 0 otherwise + */ + int optionsPrintParamList(void); + +/* --------------------------------------------- + Option serialization functions +-------------------------------------------------*/ + + /** + * Convert option into a xmlNodePtr + * + * @returns The option @p optionType as a xmlNodePtr if successful, + * NULL otherwise + * + * @param optionType Is valid, option to convert to a xmlNodePtr + * + */ + xmlNodePtr optionsNode(OptionTypeEnum optionType); + + + + /** + * Read options from document provided. + * + * @returns 1 if able to read @p doc and load options found, + * 0 otherwise + * + * @param doc Is valid xsldbg config document, in the format as indicated + * by config.dtd + */ + int optionsReadDoc(xmlDocPtr doc); + + + /** + * Save configuation to file specified + * + * @returns 1 if able to save options to @fileName, + * 0 otherwise + * + * @fileName : Must be NON NULL be a local file that can be written to + */ + int optionsSavetoFile(xmlChar * fileName); + + +/* --------------------------------------------- + Platform specific option functions +-------------------------------------------------*/ + + /** + * Intialize the platform specific options module + * + * This is a platform specific interface + * + * @returns 1 if sucessful + * 0 otherwise + */ + int optionsPlatformInit(void); + + + /** + * Free memory used by the platform specific options module + * + * This is a platform specific interface + * + */ + void optionsPlatformFree(void); + + + /** + * Return xsldbg's the configuration file name + * + * Returns A copy of the file name that will be used to load xsldbgs + * configuration from, + * NULL otherwise + * + * This is a platform specific interface + * + */ + xmlChar *optionsConfigFileName(void); + + + /** + * Load options from configuration file/registry + * + * This is a platform specific interface + * + * Returns 1 if able to load options + * 0 otherwise + */ + int optionsLoad(void); + + + /** + * Save options to configuration file/registry + * + * This is a platform specific interface + * + * Returns 1 if able to load options + * 0 otherwise + */ + int optionsSave(void); + + + /** + * Set/Get the state of configuration loading/saving. Normally only used + * by RISC OS + * + * + * Returns The current/new value of configuration flag. Where + * @p value means: + * OPTIONS_CONFIG_READVALUE : No change return current + * value of read configuration flag + * OPTIONS_CONFIG_WRITING : Clear flag and return + * OPTIONS_CONFIG_WRITING which mean configuration + * file is being written + * OPTIONS_CONFIG_READING : Set flag and return + * OPTIONS_CONFIG_READING, which means configuration + * file is being read + * OPTIONS_CONFIG_IDLE : We are neither reading or writing + * configuration and return OPTIONS_CONFIG_IDLE + * + * @param value Is valid + * + */ + int optionsConfigState(OptionsConfigState value); + + /** + * optionsAddWatch: + * @xPath : A valid xPath to evaluate in a context and + * has not already been addded + * + * Add xPath to be evaluated and printed out each time the debugger stops + * + * Returns 1 if able to add xPath to watched + * 0 otherwise + */ + int optionsAddWatch(const xmlChar* xPath); + + /** + * optionsGetWatchID: + * @xPath : A valid watch expression that has already been added + * + * Finds the ID of watch expression previously added + * + * Returns 0 if not found, + * otherwise returns the ID of watch expression + */ + int optionsGetWatchID(const xmlChar* xPath); + + + /** + * optionsRemoveWatch: + * @watchID : A valid watchID as indicated by last optionsPrintWatches + * + * Remove the watch with given ID from our list of expressions to watch + * + * Returns 1 if able to remove to watch expression + * 0 otherwise + */ + int optionsRemoveWatch(int watchID); + + + /** + * optionsGetWatchList: + * + * Return the current list of expressions to watch + * + * Return the current list of expressions to watch + */ + arrayListPtr optionsGetWatchList(void); + + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/options_unix.cpp b/kxsldbg/kxsldbgpart/libxsldbg/options_unix.cpp new file mode 100644 index 00000000..27c7d2f1 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/options_unix.cpp @@ -0,0 +1,118 @@ + +/*************************************************************************** + options_unix.c - *nix specific option functions + ------------------- + begin : Tue Jan 29 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <libxml/parser.h> +#include <stdlib.h> +#include <string.h> +#include "xsldbg.h" +#include "options.h" + + /** + * optionsPlatformInit: + * + * Intialize the platform specific options module + * + * This is a platform specific interface + * + * Returns 1 if sucessful + * 0 otherwise + */ +int +optionsPlatformInit(void) +{ + return 1; +} + + + /** + * optionsPlatformFree: + * + * Free memory used by the platform specific options module + * + * This is a platform specific interface + * + */ +void +optionsPlatformFree(void) +{ + /* empty */ +} + + /** + * optionsConfigFileName: + * + * Returns A copy of the file name that will be used to load xsldbgs + * configuration from, + * NULL otherwise + */ +xmlChar * +optionsConfigFileName(void) +{ + xmlChar *result = NULL; + const char *homeDir = getenv("HOME"); + const char *configName = "xsldbg.rc"; + int bufferSize = 0; + + if (homeDir) { + /* give ourselves a bit of room to move */ + bufferSize = strlen(homeDir) + strlen(configName) + 10; + result = (xmlChar *) xmlMalloc(bufferSize); + snprintf((char *) result, bufferSize, "%s/%s", homeDir, + configName); + } + return result; +} + + + /** + * optionsLoad: + * + * Load options from configuration file/registry + * + * This is a platform specific interface + * + * Returns 1 if able to load options + * 0 otherwise + */ +int +optionsLoad(void) +{ + int result = 0; + xmlDocPtr doc = xmlParseFile((char *) optionsConfigFileName()); + + if (doc) + result = optionsReadDoc(doc); + return 0; +} + + + /** + * optionsSave: + * + * Save options to configuration file/registry + * + * This is a platform specific interface + * + * Returns 1 if able to save options + * 0 otherwise + */ +int +optionsSave(void) +{ + return optionsSavetoFile(optionsConfigFileName()); +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/os_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/os_cmds.cpp new file mode 100644 index 00000000..dac5bb0f --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/os_cmds.cpp @@ -0,0 +1,100 @@ + +/*************************************************************************** + os_cmds.c - operating system commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "files.h" + +/* ----------------------------------------- + + Operating system related commands + + ------------------------------------------- */ + + +/** + * xslDbgShellChangeWd: + * @path: The path to change to + * + * Change the current working directory of the operating system + * + * Returns 1 if able to change xsldbg's working directory to @path + * 0 otherwise + */ +int +xslDbgShellChangeWd(xmlChar * path) +{ + int result = 0; + + if (xmlStrLen(path)) { + /* call function in files.c to do the work */ + result = changeDir(path); + } else + xsldbgGenericErrorFunc(i18n("Error: Missing arguments for the command %1.\n").arg("chdir")); + return result; +} + + +/** + * xslDbgShellExecute: + * @name: The name of command string to be executed by operating system shell + * @verbose: If 1 then print extra debugging messages, + * normal messages otherwise + * + * Execute an operating system command + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellExecute(xmlChar * name, int verbose) +{ + int result = 0; + + /* Quick check to see if we have a command processor; embedded systems + * may not have such a thing */ + if (system(NULL) == 0) { + xsldbgGenericErrorFunc(i18n("Error: No command processor available for shell command \"%1\".\n").arg(xsldbgText(name))); + } else { + int return_code; + + if (verbose) + xsldbgGenericErrorFunc(i18n("Information: Starting shell command \"%1\".\n").arg(xsldbgText(name))); + + return_code = system((char *) name); + /* JRF: Strictly system returns an implementation defined value - + * we are interpreting that value here, so we need + * implementation specific code to handle each case */ + +#ifdef __riscos + /* on RISC OS -2 means 'system call failed', otherwise it is the + * return code from the sub-program */ + if (return_code != -2) { +#else + if (return_code == 0) { +#endif + if (verbose) + xsldbgGenericErrorFunc(i18n("Information: Finished shell command.\n")); + result = 1; + } else { + if (verbose) + xsldbgGenericErrorFunc(i18n("Error: Unable to run command. System error %1.\n").arg(return_code)); + } + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/param_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/param_cmds.cpp new file mode 100644 index 00000000..e4255797 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/param_cmds.cpp @@ -0,0 +1,175 @@ + +/*************************************************************************** + param_cmds.c - libxslt parameter commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "options.h" + +#include "xsldbgmsg.h" +#include "xsldbgthread.h" /* for get thread status */ + + +/* ----------------------------------------- + + libxslt parameter related commands + + ------------------------------------------- */ + +/** + * xslDbgShellAddParam: + * @arg: A string comprised of two words separated by + * one or more spaces which are in UTF-8 + * + * Add a libxslt parameter to be sent to libxslt later on + * + * Returns 1 on success, + * 0 otherwise +*/ +int +xslDbgShellAddParam(xmlChar * arg) +{ + int result = 0; + parameterItemPtr paramItem = NULL; + static const char *errorPrompt = I18N_NOOP("Failed to add parameter"); + xmlChar *opts[2]; + + if (!arg) { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("addparam")); + }else{ + if ((xmlStrLen(arg) > 1) && splitString(arg, 2, opts) == 2) { + int count; + for (count = 0; count < arrayListCount(optionsGetParamItemList()); count++){ + paramItem = (parameterItemPtr)arrayListGet(optionsGetParamItemList(), count); + if (paramItem != NULL){ + if (xmlStrCmp(opts[0], paramItem->name) == 0){ + /* parameter exist just update its value */ + if (paramItem->value) + xmlFree(paramItem->value); + paramItem->value = xmlStrdup(opts[1]); + return 1; + } + } + } + paramItem = optionsParamItemNew(opts[0], opts[1]); + result = arrayListAdd(optionsGetParamItemList(), paramItem); + } else { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("addparam")); + } + } + if (!result) + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + else { + xsldbgGenericErrorFunc("\n"); + } + return result; +} + + +/** + * xslDbgShellDelParam: + * @arg: A single white space trimmed parameter number to look for + * + * Delet a libxslt parameter to be sent to libxslt later on + * + * Returns 1 if able to delete parameter @name, + * 0 otherwise + */ +int +xslDbgShellDelParam(xmlChar * arg) +{ + int result = 0; + static const char *errorPrompt = I18N_NOOP("Failed to delete parameter"); + long paramId; + xmlChar *opts[2]; + + if (!arg) { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("delparam")); + }else{ + if (xmlStrLen(arg) > 0) { + if (splitString(arg, 1, opts) == 1) { + if ((xmlStrlen(opts[0]) == 0) || + !sscanf((char *) opts[0], "%ld", ¶mId)) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse %1 as a line number.\n").arg(xsldbgText(opts[0]))); + } else { + result = + arrayListDelete(optionsGetParamItemList(), paramId); + if (!result) + xsldbgGenericErrorFunc(i18n("Error: Unable to find parameter %1.\n").arg(paramId)); + } + } else { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments for the command %1.\n").arg("delparam")); + } + } else { + /* Delete all parameters */ + arrayListEmpty(optionsGetParamItemList()); + result = 1; + } + } + if (!result) + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + else + xsldbgGenericErrorFunc("\n"); + + return result; +} + + +/** + * xslDbgShellShowParam: + * @arg: Not used + * + * Print list of current paramters + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellShowParam(xmlChar * arg) +{ + Q_UNUSED(arg); + int result = 0; + static const char *errorPrompt = I18N_NOOP("Unable to print parameters"); + + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + int paramIndex = 0; + int itemCount = arrayListCount(optionsGetParamItemList()); + + notifyListStart(XSLDBG_MSG_PARAMETER_CHANGED); + + if (itemCount > 0) { + parameterItemPtr paramItem = NULL; + + while (paramIndex < itemCount) { + paramItem = (parameterItemPtr) + arrayListGet(optionsGetParamItemList(), paramIndex++); + if (paramItem != NULL) + notifyListQueue(paramItem); + } + } + notifyListSend(); + result = 1; + } else { + + if (optionsPrintParamList()) + result = 1; + else + xsldbgGenericErrorFunc(QString("Error: %1\n").arg(i18n(errorPrompt))); + xsldbgGenericErrorFunc("\n"); + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/qtnotifier2.h b/kxsldbg/kxsldbgpart/libxsldbg/qtnotifier2.h new file mode 100644 index 00000000..dfe57f0c --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/qtnotifier2.h @@ -0,0 +1,38 @@ +/*************************************************************************** + qtnotifier.h - notify the qt app of changes + ------------------- + begin : Sun Dec 23 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QTNOTIFIER_H +#define QTNOTIFIER_H + +#if defined WIN32 +#include <libxsldbg/xsldbgwin32config.h> +#endif + +#include "xsldbgnotifier.h" + + +class XsldbgDebuggerBase; + +extern "C" { + + void connectNotifier(XsldbgDebuggerBase *debugger); + int qtNotifyXsldbgApp(XsldbgMessageEnum type, const void *data); + int qtNotifyStateXsldbgApp(XsldbgMessageEnum type, int commandId, XsldbgCommandStateEnum commandState, const char *text); + int qtNotifyTextXsldbgApp(XsldbgMessageEnum type, const char *text); +} + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/search.cpp b/kxsldbg/kxsldbgpart/libxsldbg/search.cpp new file mode 100644 index 00000000..68fcd7e1 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/search.cpp @@ -0,0 +1,1584 @@ + +/*************************************************************************** + search.c - search implementation + ------------------- + begin : Fri Nov 2 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + + +#include "xsldbg.h" +#include "debugXSL.h" +#include "breakpoint.h" +#include "search.h" +#include "options.h" +#include "files.h" + +#ifdef __riscos + +/* Include for filename conversions */ +#include "libxml/riscos.h" +#endif + +/* our private function*/ +void scanForBreakPoint(void *payload, void *data, + xmlChar * name); + +/* store all data in this document so we can write it to file*/ +static xmlDocPtr searchDataBase; + +/* the topmost node in document*/ +static xmlNodePtr searchDataBaseRoot; + +/* what was the last query that was run */ +static xmlChar *lastQuery; + +#define BUFFER_SIZE 500 +static xmlChar searchBuffer[BUFFER_SIZE]; + +/* ----------------------------------------- + Private function declarations for dbgsearch.c + -------------------------------------------*/ + +/** + * findNodeByLineNoHelper: + * @payload: valid xsltStylesheetPtr + * @data: valid searchInfoPtr + * @name: not used + * + * We are walking through stylesheets looking for a match + */ +void + findNodeByLineNoHelper(void *payload, void *data, + xmlChar * name); + +/** + * globalVarHelper: + * @payload: valid xsltStylesheetPtr + * @data: is valid + * @name: not used + * + * Helper to find the global variables. We are given control via + * walkStylesheets globalWalkFunc will always be set to the + * walkFunc to call + */ +void + globalVarHelper(void **payload, void *data, + xmlChar * name); + +/** + * localVarHelper: + * @payload: valid xsltTemplatePtr + * @data: is valid + * @name: not used + * + * Helper to find the local variables. We are given control via walkTemplates + * globalWalkFunc will always be set to the walkFunc to call + * localWalkFunc will always be set to the walkFunc to call + */ +void + localVarHelper(void **payload, void *data, + xmlChar * name); + + +/* ------------------------------------- + End private functions + ---------------------------------------*/ + + +/** + * searchInit: + * + * Initialize the search module + * + * Returns 1 if search structures have been initialized properly and all + * memory required has been obtained, + * 0 otherwise +*/ +int +searchInit(void) +{ + searchDataBase = NULL; + searchDataBaseRoot = NULL; + lastQuery = NULL; + if (!searchEmpty()) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + return (searchRootNode() != NULL); +} + + +/** + * searchFree: + * + * Free all memory used by the search module + */ +void +searchFree(void) +{ + if (searchDataBase) { + xmlFreeDoc(searchDataBase); + searchDataBase = NULL; + searchDataBaseRoot = NULL; + } +} + + +/** + * searchNewInfo: + * @type: What type of search is required + * + * Create a new search + * + * Returns A valid search info pointer if successful + * NULL otherwise + */ +searchInfoPtr +searchNewInfo(SearchEnum type) +{ + searchInfoPtr result = NULL; + int searchType = type; + + switch (searchType) { + case SEARCH_BREAKPOINT: + result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo)); + if (result) { + breakPointSearchDataPtr searchData; + + result->type = SEARCH_BREAKPOINT; + searchData = (breakPointSearchDataPtr) + xmlMalloc(sizeof(breakPointSearchData)); + if (searchData) { + searchData->id = -1; + searchData->templateName = NULL; + searchData->breakPtr = NULL; + result->data = searchData; + } else { + xmlFree(result); + result = NULL; + } + } + break; + + case SEARCH_NODE: + result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo)); + if (result) { + nodeSearchDataPtr searchData; + + result->type = SEARCH_NODE; + searchData = + (nodeSearchDataPtr) xmlMalloc(sizeof(nodeSearchData)); + if (searchData) { + searchData->node = NULL; + searchData->lineNo = -1; + searchData->url = NULL; + searchData->nameInput = NULL; + searchData->guessedNameMatch = NULL; + searchData->absoluteNameMatch = NULL; + result->data = searchData; + } else { + xmlFree(result); + result = NULL; + } + } + break; + + case SEARCH_XSL: + break; + + case SEARCH_VARIABLE: + result = (searchInfoPtr) xmlMalloc(sizeof(searchInfo)); + if (result) { + variableSearchDataPtr searchData; + + result->type = SEARCH_VARIABLE; + searchData = (variableSearchDataPtr) + xmlMalloc(sizeof(variableSearchData)); + if (searchData) { + searchData->name = NULL; + searchData->nameURI = NULL; + searchData->select = NULL; + result->data = searchData; + } else { + xmlFree(result); + result = NULL; + } + } + break; + + } + if (result) { + result->found = 0; + result->error = 0; + } + return result; +} + + +/** + * searchFreeInfo: + * @info: valid search info + * + * Free memory used by @info + */ +void +searchFreeInfo(searchInfoPtr info) +{ + if (info) { + if (info->data) { + switch (info->type) { + case SEARCH_BREAKPOINT: + { + breakPointSearchDataPtr searchData = + (breakPointSearchDataPtr) info->data; + + if (searchData->templateName) + xmlFree(searchData->templateName); + } + break; + + case SEARCH_NODE: + { + nodeSearchDataPtr searchData = + (nodeSearchDataPtr) info->data; + + if (searchData->url) + xmlFree(searchData->url); + + if (searchData->nameInput) + xmlFree(searchData->nameInput); + + if (searchData->guessedNameMatch) + xmlFree(searchData->guessedNameMatch); + + if (searchData->absoluteNameMatch) + xmlFree(searchData->absoluteNameMatch); + + /* we never free searchData->node as we did not create it! */ + } + break; + + case SEARCH_XSL: + break; + + case SEARCH_VARIABLE: + { + variableSearchDataPtr searchData = + (variableSearchDataPtr) info->data; + + if (searchData->name) + xmlFree(searchData->name); + + if (searchData->nameURI) + xmlFree(searchData->nameURI); + + if (searchData->select) + xmlFree(searchData->select); + } + break; + + } + xmlFree(info->data); + } + xmlFree(info); + } +} + + +/** + * searchEmpty: + * + * Empty the seach dataBase of its contents + * + * Returns 1 on success, + * 0 otherwise + */ +int +searchEmpty(void) +{ + if (searchDataBase) { + xmlFreeDoc(searchDataBase); + } + searchDataBase = xmlNewDoc((xmlChar *) "1.0"); + searchDataBaseRoot = NULL; + if (searchDataBase) { + xmlCreateIntSubset(searchDataBase, + (xmlChar *) "search", (xmlChar *) + "-//xsldbg//DTD search XML V1.1//EN", + (xmlChar *) "search_v1_1.dtd"); + searchDataBaseRoot = xmlNewNode(NULL, (xmlChar *) "search"); + if (searchDataBaseRoot) + xmlAddChild((xmlNodePtr) searchDataBase, searchDataBaseRoot); + } + if (lastQuery) + xmlFree(lastQuery); + lastQuery = NULL; + if (searchRootNode() == NULL) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to clear old search results, memory error?\n"); +#endif + } + + return (searchRootNode() != NULL); +} + + +/** + * searchDoc: + * + * Return the document used for seaching ie the search dataBase + * + * Returns The document used for searching + * Dangerous function to use! Does NOT return a copy of + * search data so don't free it + */ +xmlDocPtr +searchDoc(void) +{ + return searchDataBase; +} + + +/** + * searchRootNode: + * + * Get the topmost node in the search dataBase + * + * Returns The topmost xml node in search dataBase. + * Dangerous function to use! Does NOT return a copy of + * search root node so don't free it + */ +xmlNodePtr +searchRootNode(void) +{ + return searchDataBaseRoot; +} + + +/** + * searchAdd: + * @node: Is valid + * + * Add a node to the search dataBase + * + * Returns 1 if able to add @node to top node in search dataBase, + * 0 otherwise + */ +int +searchAdd(xmlNodePtr node) +{ + int result = 0; + + if (node && searchDataBaseRoot + && xmlAddChild(searchDataBaseRoot, node)) { + result = 1; + } + + return result; +} + + +/** + * searchSave: + * @fileName: A valid file name, or NULL for the default + * + * Save the search dataBase to @fileName + * + * Returns 1 on success, + * 0 otherwise + */ +int +searchSave(const xmlChar * fileName) +{ + + int result = 0; + xmlChar *searchInput = NULL; + + if (fileName == NULL) + searchInput = filesSearchFileName(FILES_SEARCHINPUT); + else + searchInput = xmlStrdup(fileName); + + if (xmlSaveFormatFile((char *) searchInput, searchDataBase, 1) != -1){ + result = 1; + }else{ + xsldbgGenericErrorFunc(i18n("Error: Unable to write search Database to file %1. Try setting the \"searchresultspath\" option to a writable path.\n").arg(xsldbgText(searchInput))); + } + + if (searchInput) + xmlFree(searchInput); + + return result; +} + + +/** + * searchQuery: + * @query: The query to run . If NULL then query is "//search/ *" + * @tempFile: Where do we load the search dataBase from to execute + * query. If tempFile is NULL "searchresult.xml" is used + * @outputFile : Where do we store the result. If NULL + * then default to "searchresult.html" + * + * Send query as parameter for execution of search.xsl using + * data stored in @tempFile + * + * Returns 1 on success, + * 0 otherwise + */ +int +searchQuery(const xmlChar * tempFile, const xmlChar * outputFile, + const xmlChar * query) +{ + int result = 0; + + /* The file name of where the input is comming from */ + xmlChar *searchInput = NULL; + + /* The XSL file name to use during transformation of searchInput */ + xmlChar *searchXSL = NULL; + + /* Where to store the result of transformation */ + xmlChar *searchOutput = NULL; + + + /* if a tempFile if provided its up you to make sure that it is correct !! */ + if (tempFile == NULL) + searchInput = filesSearchFileName(FILES_SEARCHINPUT); + else + searchInput = xmlStrdup(tempFile); + + searchXSL = filesSearchFileName(FILES_SEARCHXSL); + + /* if a outputFile if provided its up you to make sure that it is correct */ + if (outputFile == NULL) + searchOutput = filesSearchFileName(FILES_SEARCHRESULT); + else + searchOutput = xmlStrdup(outputFile); + + if (!query || (xmlStrlen(query) == 0)) + query = (xmlChar *) "--param query //search/*"; + + /* see configure.in for the definition of XSLDBG_BIN, the name of our binary */ + if (searchInput && searchXSL && searchOutput) { + if (optionsGetIntOption(OPTIONS_CATALOGS) == 0) + snprintf((char *) searchBuffer, sizeof(searchBuffer), + "%s -o %s %s %s %s", XSLDBG_BIN, + searchOutput, query, searchXSL, searchInput); + else + /* assume that we are to use catalogs as well in our query */ + snprintf((char *) searchBuffer, sizeof(searchBuffer), + "%s --catalogs -o %s %s %s %s", XSLDBG_BIN, + searchOutput, query, searchXSL, searchInput); + result = xslDbgShellExecute(searchBuffer, 1); + + if (result && (optionsGetIntOption(OPTIONS_PREFER_HTML) == 0)) { + /* try printing out the file */ + result = filesMoreFile(searchOutput, NULL); + } + + xsldbgGenericErrorFunc(i18n("Information: Transformed %1 using %2 and saved to %3.\n").arg(xsldbgText(searchInput)).arg(xsldbgText(searchXSL)).arg(xsldbgText(searchOutput))); + } else { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to command %1.\n").arg("search")); + } + + if (searchInput) + xmlFree(searchInput); + + if (searchXSL) + xmlFree(searchXSL); + + if (searchOutput) + xmlFree(searchOutput); + + return result; +} + + +/** + * scanForBreakPoint: + * @payload: A valid breakPointPtr + * @data: The criteria to look for and a valid searchInfoPtr of + * type SEARCH_BREAKPOINT + * @name: Not used + * + * Test if break point matches criteria given by @data. If so then + * set @data->found to 1 and stores reference to break point found in + * @data->data->node + * otherwise @data is unchanged +*/ +void +scanForBreakPoint(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + breakPointPtr breakPtr = (breakPointPtr) payload; + searchInfoPtr searchInf = (searchInfoPtr) data; + breakPointSearchDataPtr searchData = NULL; + int found = 0; + + if (!payload || !searchInf || !searchInf->data + || (searchInf->type != SEARCH_BREAKPOINT) || searchInf->found) + return; + + searchData = (breakPointSearchDataPtr) searchInf->data; + + if (searchData->id && (breakPtr->id == searchData->id)) + found = 1; + else if (searchData->templateName && breakPtr->templateName && + (xmlStrCmp(breakPtr->templateName, searchData->templateName) + == 0)) + found = 1; + + if (found) { + searchInf->found = 1; + searchData->breakPtr = breakPtr; + } +} + + + +/** + * scanForNode: + * @payload: A valid xmlNodePtr + * @data: The criteria to look for and a valid searchInfo of + * type SEARCH_NODE + * @name: Not used + + * Test if node matches criteria given by @data if so then set @data->found + * to 1 and stores reference to node found in @data->data->node + * otherwise @data is unchanged + */ +void +scanForNode(void *payload, void *data, xmlChar * name) +{ + Q_UNUSED(name); + searchInfoPtr searchInf = (searchInfoPtr) data; + nodeSearchDataPtr searchData = NULL; + xmlNodePtr node = (xmlNodePtr) payload; + xmlChar *baseUri = NULL; + int match = 1; + + if (!node || !node->doc || !node->doc->URL || + !searchInf || (searchInf->type != SEARCH_NODE)) + return; + + searchData = (nodeSearchDataPtr) searchInf->data; + + if (searchData->lineNo >= 0) + match = searchData->lineNo == xmlGetLineNo(node); + + if (searchData->url) + baseUri = filesGetBaseUri(node); + if (baseUri) { + match = match && (xmlStrCmp(searchData->url, baseUri) == 0); + xmlFree(baseUri); + } else { + match = match && (xmlStrcmp(searchData->url, node->doc->URL) == 0); + } + + if (match) { + searchData->node = node; + searchInf->found = 1; + } + +} + + +/** + * findNodeByLineNoHelper: + * @payload: A valid xsltStylesheetPtr + * @data: A valid searchInfoPtr + * @name: Not used + * + * We are walking through stylesheets looking for a match + */ +void +findNodeByLineNoHelper(void *payload, void *data, + xmlChar * name) +{ + Q_UNUSED(name); + xsltStylesheetPtr style = (xsltStylesheetPtr) payload; + searchInfoPtr searchInf = (searchInfoPtr) data; + + if (!payload || !searchInf || !style->doc) + return; + + walkChildNodes((xmlHashScanner) scanForNode, searchInf, + (xmlNodePtr) style->doc); + + /* try the included stylesheets */ + if (!searchInf->found) + walkIncludes((xmlHashScanner) scanForNode, searchInf, style); +} + + +/** + * findNodeByLineNo: + * @ctxt: Valid ctxt to look into + * @url: Non-null, non-empty file name that has been loaded by debugger + * @lineNumber: @lineNumber >= 0 and is available in @url + * + * Finds the closest line number in file specified that can be a point + * + * Returns The node at line number number specified if successfull, + * NULL otherwise + */ +xmlNodePtr +findNodeByLineNo(xsltTransformContextPtr ctxt, + const xmlChar * url, long lineNumber) +{ + xmlNodePtr result = NULL; + searchInfoPtr searchInf = searchNewInfo(SEARCH_NODE); + nodeSearchDataPtr searchData = NULL; + + if (!searchInf) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Unable to create searchInfo in findNodeByLineNo\n"); +#endif + return result; + } + + if (!ctxt || !url || (lineNumber == -1)) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Invalid ctxt, url or line number to findNodeByLineNo\n"); +#endif + return result; + } + + searchData = (nodeSearchDataPtr) searchInf->data; + searchData->url = (xmlChar *) xmlMemStrdup((char *) url); + searchData->lineNo = lineNumber; + walkStylesheets((xmlHashScanner) findNodeByLineNoHelper, searchInf, + ctxt->style); + if (!searchInf->found) { + /* try searching the document set */ + xsltDocumentPtr document = ctxt->document; + + while (document && !searchInf->found) { + walkChildNodes((xmlHashScanner) scanForNode, searchInf, + (xmlNodePtr) document->doc); + document = document->next; + } + } + result = searchData->node; + searchFreeInfo(searchInf); + + return result; +} + + +/** + * findTemplateNode: + * @style: A valid stylesheet collection to look into + * @name: A valid template name to look for + * + * Find a template node + * + * Returns The template node found if successful, + * NULL otherwise + */ +xmlNodePtr +findTemplateNode(xsltStylesheetPtr style, const xmlChar * name) +{ + xmlNodePtr result = NULL; + xmlChar *templName; + xsltTemplatePtr templ; + + if (!style || !name) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Invalid stylesheet or template name : findTemplateNode\n"); +#endif + return result; + } + + while (style) { + templ = style->templates; + + while (templ) { + if (templ->match) + templName = (xmlChar *) templ->match; + else + templName = (xmlChar *) templ->name; + + if (templName) { + if (!xmlStrCmp((char *) templName, (char *) name)) { + return templ->elem; + } + } + templ = templ->next; + } + if (style->next) + style = style->next; + else + style = style->imports; + } + + if (!result) + xsldbgGenericErrorFunc(i18n("Error: XSLT template named \"%1\" was not found.\n").arg(xsldbgText(name))); + return result; +} + + +/** + * findBreakPointByName: + * @templateName: The template name to look for + * + * Find the breakpoint at template with "match" or "name" equal + * to templateName + * + * Returns The break point that matches @templateName + * NULL otherwise +*/ +breakPointPtr +findBreakPointByName(const xmlChar * templateName) +{ + breakPointPtr result = NULL; + searchInfoPtr searchInf = searchNewInfo(SEARCH_BREAKPOINT); + breakPointSearchDataPtr searchData; + + if (!searchInf || (searchInf->type != SEARCH_BREAKPOINT)) + return result; + + searchData = (breakPointSearchDataPtr) searchInf->data; + searchData->templateName = (xmlChar *) xmlStrdup(templateName); + if (templateName) { + walkBreakPoints((xmlHashScanner) scanForBreakPoint, searchInf); + if (!searchInf->found) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Breakpoint with template name of \"%s\" not found\n", + templateName); +#endif + } else + result = searchData->breakPtr; + } + + searchFreeInfo(searchInf); + + return result; +} + + +/** + * findBreakPointById: + * @id: The break point id to look for + * + * Find a break point by its id + * + * Returns The break point with given the break point id if found, + * NULL otherwise + */ +breakPointPtr +findBreakPointById(int id) +{ + breakPointPtr result = NULL; + searchInfoPtr searchInf = searchNewInfo(SEARCH_BREAKPOINT); + breakPointSearchDataPtr searchData; + + if (!searchInf || !searchInf->data) + return result; + + searchData = (breakPointSearchDataPtr) searchInf->data; + if (id >= 0) { + searchData->id = id; + walkBreakPoints((xmlHashScanner) scanForBreakPoint, searchInf); + if (!searchInf->found) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: Breakpoint id %d not found\n", id); +#endif + } else + result = searchData->breakPtr; + } + + searchFreeInfo(searchInf); + return result; +} + + +/** + * findNodesByQuery: + * @query: The xpath query to run, see docs/en/search.dtd for more details + * + * Find nodes in search dataBase using an xpath query + * + * Returns The nodes that match the given query on success, + * NULL otherwise + */ +xmlXPathObjectPtr +findNodesByQuery(const xmlChar * query) +{ + Q_UNUSED(query); + xmlXPathObjectPtr list = NULL; + + return list; +} + + + +/** + * walkBreakPoints: + * @walkFunc: The function to callback for each break point found + * @data: The extra data to pass onto walkFunc + * + * Walks through all break points calling walkFunc for each. The payload + * sent to walkFunc is of type breakPointPtr + */ +void +walkBreakPoints(xmlHashScanner walkFunc, void *data) +{ + int lineNo; + xmlHashTablePtr hashTable; + + if (!walkFunc) + return; + + for (lineNo = 0; lineNo < breakPointLinesCount(); lineNo++) { + hashTable = breakPointGetLineNoHash(lineNo); + if (hashTable) { + xmlHashScan(hashTable, walkFunc, data); + } + } +} + + +/** + * walkTemplates: + * @walkFunc: The function to callback for each template found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all templates calling walkFunc for each. The payload + * of walkFunc is of type xsltTemplatePtr + */ +void +walkTemplates(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style) +{ + xsltTemplatePtr templ; + + if (!walkFunc || !style) + return; + + while (style) { + templ = style->templates; + while (templ) { + (*walkFunc) (templ, data, NULL); + templ = templ->next; + } + if (style->next) + style = style->next; + else + style = style->imports; + } +} + + +/** + * walkStylesheets: + * @walkFunc: The function to callback for each stylesheet found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all templates calling walkFunc for each. The payload + * sent to walkFunc is of type xsltStylesheetPtr + */ +void +walkStylesheets(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style) +{ + xsltStylesheetPtr next; + + if (!walkFunc || !style) + return; + + next = style->next; + while (style) { + (*walkFunc) (style, data, NULL); + if (style->imports) + style = style->imports; + else + style = next; + } +} + + + +xmlHashScanner globalWalkFunc = NULL; + +/** + * globalVarHelper: + * @payload: valid xsltStylesheetPtr + * @data: is valid + * @name: not used + * + * Helper to find the global variables. We are given control via + * walkStylesheets globalWalkFunc will always be set to the + * walkFunc to call + */ +void +globalVarHelper(void **payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xsltStylesheetPtr style = (xsltStylesheetPtr) payload; + xsltStackElemPtr global; + + if (style) { + global = style->variables; + + while (global &&global->comp) { + (*globalWalkFunc) (global->comp->inst, data, NULL); + global = global->next; + } + } +} + + +/** + * walkGlobals: + * @walkFunc: The function to callback for each gobal variable found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Call walkFunc for each global variable. The payload + * sent to walkFunc is of type xmlNodePtr + */ +void +walkGlobals(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style) +{ + Q_UNUSED(data); + if (!walkFunc || !style) + return; + + globalWalkFunc = walkFunc; + + walkStylesheets((xmlHashScanner) globalVarHelper, data, style); +} + + + +xmlHashScanner localWalkFunc = NULL; + +/** + * localVarHelper: + * @payload: valid xsltTemplatePtr + * @data: is valid + * @name: not used + * + * Helper to find the local variables. We are given control via walkTemplates + * globalWalkFunc will always be set to the walkFunc to call + * localWalkFunc will always be set to the walkFunc to call + */ +void +localVarHelper(void **payload, void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xsltTemplatePtr templ = (xsltTemplatePtr) payload; + xmlNodePtr node; + + if (templ && templ->elem) { + node = templ->elem->children; + + while (node) { + if (IS_XSLT_NAME(node, "param") + || IS_XSLT_NAME(node, "variable")) { + (*localWalkFunc) (node, data, NULL); + node = node->next; + } else + break; + } + } +} + + +/** + * walkLocals: + * @walkFunc: The function to callback for each local variable found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all local variables calling walkFunc for each. The payload + * of walkFunc is of type xmlNodePtr + */ +void +walkLocals(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style) +{ + if (!walkFunc || !style) + return; + + localWalkFunc = walkFunc; + + walkTemplates((xmlHashScanner) localVarHelper, data, style); + +} + + +/** + * walkIncludes: + * @walkFunc: The function to callback for each included stylesheet + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all included stylesheets calling walkFunc for each. + * The payload of walkFunc is of type xmlNodePtr + */ + +void +walkIncludes(xmlHashScanner walkFunc, void *data, xsltStylesheetPtr style) +{ + xsltDocumentPtr document; /* included xslt documents */ + + if (!walkFunc || !style) + return; + + while (style) { + document = style->docList; + /* look at included documents */ + while (document) { + (*walkFunc) ((xmlNodePtr) document->doc, data, NULL); + document = document->next; + } + /* try next stylesheet */ + if (style->next) + style = style->next; + else + style = style->imports; + } +} + + +/** + * walkIncludeInst: + * @walkFunc: The function to callback for each xsl:include instruction found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all xsl:include calling walkFunc for each. The payload + * of walkFunc is of type xmlNodePtr + */ +void +walkIncludeInst(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style) +{ + xmlNodePtr node = NULL, styleChild = NULL; + + if (!walkFunc || !style) + return; + + while (style) { + /*look for stylesheet node */ + if (style->doc) { + node = (xmlNodePtr) style->doc->children; + while (node) { + /* not need but just in case :) */ + if (IS_XSLT_NAME(node, "stylesheet") + || IS_XSLT_NAME(node, "transform")) { + styleChild = node->children; /* get the topmost elements */ + break; + } else + node = node->next; + } + + /* look for includes */ + while (styleChild) { + if (IS_XSLT_NAME(styleChild, "include")) + (*walkFunc) (styleChild, data, NULL); + styleChild = styleChild->next; + } + } + /* try next stylesheet */ + if (style->next) + style = style->next; + else + style = style->imports; + } +} + + +/** + * walkChildNodes: + * @walkFunc: The function to callback for each child/sibling found + * @data: The extra data to pass onto walkFunc + * @node: Is valid + * + * Call walkFunc for each child of @node the payload sent to walkFunc is + * a xmlNodePtr + */ +void +walkChildNodes(xmlHashScanner walkFunc, void *data, xmlNodePtr node) +{ + xmlNodePtr child = NULL; + searchInfoPtr searchInf = (searchInfoPtr) data; + + if (!walkFunc || !searchInf || !searchInf->data) + return; + + while (node && !searchInf->found) { + (walkFunc) (node, data, NULL); + child = node->children; + if (child && !searchInf->found) { + walkChildNodes(walkFunc, data, child); + } + node = node->next; + } +} + + +/** + * searchBreakPointNode: + * @breakPtr: Is valid + * + * Convert @breakPtr into search dataBase format + * + * Returns @breakPtr as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchBreakPointNode(breakPointPtr breakPtr) +{ + + xmlNodePtr node = NULL; + int result = 1; + + if (breakPtr) { + node = xmlNewNode(NULL, (xmlChar *) "breakpoint"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + result = result + && (xmlNewProp(node, (xmlChar *) "url", breakPtr->url) != + NULL); + sprintf((char *) searchBuffer, "%ld", breakPtr->lineNo); + result = result + && + (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer) + != NULL); + if (breakPtr->templateName) { + result = result + && + (xmlNewProp + (node, (xmlChar *) "template", + breakPtr->templateName) != NULL); + } + sprintf((char *) searchBuffer, "%d", breakPtr->flags & BREAKPOINT_ENABLED); + result = result + && + (xmlNewProp + (node, (xmlChar *) "enabled", (xmlChar *) searchBuffer) + != NULL); + sprintf((char *) searchBuffer, "%d", breakPtr->type); + result = result + && + (xmlNewProp(node, (xmlChar *) "type", (xmlChar *) searchBuffer) + != NULL); + sprintf((char *) searchBuffer, "%d", breakPtr->id); + result = result + && (xmlNewProp(node, (xmlChar *) "id", (xmlChar *) searchBuffer) + != NULL); + } else + result = 0; + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + } + return node; +} + + +/** + * searchTemplateNode: + * @templNode: Is valid + * + * Convert @templateNode into search dataBase format + * + * Returns @templNode as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchTemplateNode(xmlNodePtr templNode) +{ + xmlNodePtr node = NULL; + xmlChar *value; + int result = 1; + + if (templNode) { + node = xmlNewNode(NULL, (xmlChar *) "template"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + value = xmlGetProp(templNode, (xmlChar *) "match"); + if (value) { + result = result + && (xmlNewProp(node, (xmlChar *) "match", value) != + NULL); + xmlFree(value); + } + value = xmlGetProp(templNode, (xmlChar *) "name"); + if (value) { + result = result + && (xmlNewProp(node, (xmlChar *) "name", value) != + NULL); + xmlFree(value); + } + if (templNode->doc) { + result = result + && + (xmlNewProp + (node, (xmlChar *) "url", + templNode->doc->URL) != NULL); + } + sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(templNode)); + result = result + && + (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer) + != NULL); + if (result) { + xmlNodePtr textNode = searchCommentNode(templNode); + + if (textNode && !xmlAddChild(node, textNode)) + result = 0; + } + } else + result = 0; + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + } + return node; +} + + +/** + * searchGlobalNode: + * @globalVariable: Is valid + * + * Convert @globalVariable into search dataBase format + * + * Returns @globalVariable as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchGlobalNode(xmlNodePtr variable) +{ + xmlNodePtr node = NULL; + int result = 1; + xmlChar *value; + + if (variable) { + node = xmlNewNode(NULL, (xmlChar *) "variable"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + if (variable->doc) { + result = result && + (xmlNewProp(node, (xmlChar *) "url", + variable->doc->URL) != NULL); + sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(variable)); + result = result + && (xmlNewProp(node, (xmlChar *) "line", + (xmlChar *) searchBuffer) != NULL); + } + value = xmlGetProp(variable, (xmlChar *) "name"); + if (value) { + result = result + && (xmlNewProp(node, (xmlChar *) "name", value) != + NULL); + xmlFree(value); + } + value = xmlGetProp(variable, (xmlChar *) "select"); + if (value) { + result = result + && (xmlNewProp(node, (xmlChar *) "select", value) != + NULL); + xmlFree(value); + } + if (result) { + xmlNodePtr textNode = searchCommentNode(variable); + + if (textNode && !xmlAddChild(node, textNode)) + result = 0; + } + } else + result = 0; + } + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + return node; +} + + +/** + * searchLocalNode: + * @localvariable: Is valid + * + * Convert @localVariable into search dataBase format + * + * Returns @localVariable as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchLocalNode(xmlNodePtr variable) +{ + xmlNodePtr node = NULL; + int result = 1; + xmlChar *value; + xmlNodePtr parent; + + if (variable) { + node = searchGlobalNode(variable); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + parent = variable->parent; + /* try to find out what template this variable belongs to */ + if (parent && IS_XSLT_NAME(parent, "template")) { + value = xmlGetProp(parent, (xmlChar *) "name"); + if (value) { + result = result + && + (xmlNewProp(node, (xmlChar *) "templname", value) + != NULL); + xmlFree(value); + } + value = xmlGetProp(parent, (xmlChar *) "match"); + if (value) { + result = result + && + (xmlNewProp(node, (xmlChar *) "templmatch", value) + != NULL); + xmlFree(value); + } + } + } else + result = 0; + } + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + return node; +} + + +/** + * searchSourceNode: + * @style: Is valid + * + * Convert @style into search dataBase format + * + * Returns @style as a new xmlNode in search dataBase format if successful, + * NULL otherwise + */ +xmlNodePtr +searchSourceNode(xsltStylesheetPtr style) +{ + xmlNodePtr node = NULL; + int result = 1; + + if (style) { + if (style->parent == NULL) + node = xmlNewNode(NULL, (xmlChar *) "source"); + else + node = xmlNewNode(NULL, (xmlChar *) "import"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + if (style->doc) { + result = result && + (xmlNewProp(node, (xmlChar *) "href", style->doc->URL) + != NULL); + if (style->parent && style->parent->doc) { + result = result && + (xmlNewProp(node, (xmlChar *) "parent", + style->parent->doc->URL) != NULL); + } + if (result) { + xmlNodePtr textNode = + searchCommentNode((xmlNodePtr) style->doc); + if (textNode && !xmlAddChild(node, textNode)) + result = 0; + } + } + } else + result = 0; + } + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + return node; +} + + +/** + * searchIncludeNode: + * @include: Is a valid xsl:include instruction + * + * Convert @include into search dataBase format + * + * Returns @include as a new xmlNode in search dataBase format if successful, + * NULL otherwise + */ +xmlNodePtr +searchIncludeNode(xmlNodePtr include) +{ + xmlNodePtr node = NULL; + int result = 1; + xmlChar *value; + + if (include) { + node = xmlNewNode(NULL, (xmlChar *) "include"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + if (include->doc) { + value = xmlGetProp(include, (xmlChar *) "href"); + if (value) { + result = result + && (xmlNewProp(node, (xmlChar *) "href", value) != + NULL); + xmlFree(value); + } + if (include->parent && include->parent->doc) { + result = result && + (xmlNewProp(node, (xmlChar *) "url", + include->parent->doc->URL) != NULL); + sprintf((char *) searchBuffer, "%ld", xmlGetLineNo(include)); + result = result + && (xmlNewProp(node, (xmlChar *) "line", + (xmlChar *) searchBuffer) != NULL); + } + if (result) { + xmlNodePtr textNode = searchCommentNode(include); + + if (textNode && !xmlAddChild(node, textNode)) + result = 0; + } + } + } else + result = 0; + } + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + return node; +} + + +/** + * searchCallStackNode: + * @callStackItem: Is valid + * + * Convert @callStackItem into search dataBase format + * + * Returns @callStackItem as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchCallStackNode(callPointPtr callStackItem) +{ + xmlNodePtr node = NULL; + int result = 1; + + if (callStackItem) { + node = xmlNewNode(NULL, (xmlChar *) "callstack"); + if (node) { + /* if unable to create any property failed then result will be equal to 0 */ + if (callStackItem->info && callStackItem->info->url) + result = result + && + (xmlNewProp + (node, (xmlChar *) "url", callStackItem->info->url) + != NULL); + sprintf((char *) searchBuffer, "%ld", callStackItem->lineNo); + result = result + && + (xmlNewProp(node, (xmlChar *) "line", (xmlChar *) searchBuffer) + != NULL); + if (callStackItem->info && callStackItem->info->templateName) { + result = result && + (xmlNewProp + (node, (xmlChar *) "template", + callStackItem->info->templateName) != NULL); + } + } else + result = 0; + if (!result) { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + } + return node; +} + + +static xmlChar *commentText(xmlNodePtr node); + +/* + * Returns A copy of comment text that applies to node, + * NULL otherwise + */ +xmlChar * +commentText(xmlNodePtr node) +{ + xmlChar *result = NULL; + + if (node) { + if (node->type == XML_COMMENT_NODE) + result = xmlNodeGetContent(node); + } + + return result; +} + +/** + * searchCommentNode: + * @sourceNode: Is valid + * + * Find documentation comment that applies to @node. If found convert comment + * into search dataBase format required + * + * Returns Documentation comment for @node as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +xmlNodePtr +searchCommentNode(xmlNodePtr sourceNode) +{ + xmlNodePtr node = NULL, textChild = NULL; + xmlChar *text = NULL; + int result = 0; + + if (sourceNode) { + text = commentText(sourceNode->prev); + if (!text) { + text = commentText(sourceNode->children); + } + + if (text) { + node = xmlNewNode(NULL, (xmlChar *) "comment"); + textChild = xmlNewText(text); + if (node && textChild && xmlAddChild(node, textChild)) { + result = 1; + } + if (!result) { + if (node) { + xmlFreeNode(node); + node = NULL; + } + if (textChild) + xmlFreeNode(textChild); + } + + xmlFree(text); + } + } + return node; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/search.h b/kxsldbg/kxsldbgpart/libxsldbg/search.h new file mode 100644 index 00000000..20fc82b4 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/search.h @@ -0,0 +1,1087 @@ + +/* ************************************************************************* + xslsearch.h - public functions for + searching + ------------------- + begin : Fri Dec 7 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ************************************************************************* */ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* */ + +#ifndef XSLSEARCH_H +#define XSLSEARCH_H + +#ifdef USE_KDE_DOCS + +/** + * Provide a searching support + * + * @short search support + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + +/* We want skip most of these includes when building documentation*/ +#ifndef BUILD_DOCS +#include "breakpoint.h" +#include "callstack.h" +#endif + + +#ifdef WITH_XSLT_DEBUG +#ifndef WITH_XSLT_DEBUG_BREAKPOINTS +#define WITH_XSLT_DEBUG_BREAKPOINTS +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* what types of searches are there */ +#ifndef USE_KDOC + typedef enum { + SEARCH_BREAKPOINT = 400, + SEARCH_NODE, + SEARCH_XSL, + SEARCH_VARIABLE + } SearchEnum; +#else + /* keep kdoc happy */ + enum SearchEnum { + SEARCH_BREAKPOINT = 400, + SEARCH_NODE, + SEARCH_XSL, + SEARCH_VARIABLE + }; +#endif + + /* define a common structure to be used when searching */ + typedef struct _searchInfo searchInfo; + typedef searchInfo *searchInfoPtr; + struct _searchInfo { + int found; /* found is 1 if search is finished */ + int type; /* what type of search see SearchEnum */ + int error; /* did an error occur */ + void *data; /* extra data to pass to walkFunc */ + }; + + + /* data to pass to via searchInfoPtr when searching for break points */ + typedef struct _breakPointSearchData breakPointSearchData; + typedef breakPointSearchData *breakPointSearchDataPtr; + struct _breakPointSearchData { + int id; /* what id to look for, + * if -1 then ignore */ + xmlChar *templateName; /* template to look for + * if NULL then ignore */ + breakPointPtr breakPtr; /* the break point found by search */ + }; + + + /* data to pass via searchInfoPtr when searching for nodes */ + typedef struct _nodeSearchData nodeSearchData; + typedef nodeSearchData *nodeSearchDataPtr; + struct _nodeSearchData { + long lineNo; /* what line number to look for + * if < 0 then ignore */ + xmlChar *url; /* what URl to look for + * if NULL then ignore */ + int fileSearch; /* if true then we are trying + * to match a file name */ + xmlChar *nameInput; /* what file/node name are we + * trying to match */ + xmlChar *guessedNameMatch; /* possible name match */ + xmlChar *absoluteNameMatch; /* full name match */ + xmlNodePtr node; /* the node that the match + * occured in */ + }; + + /* data to pass to via searchInfoPtr when searching for variables points */ + typedef struct _variableSearchData variableSearchData; + typedef variableSearchData *variableSearchDataPtr; + struct _variableSearchData { + xmlChar *name; + xmlChar *nameURI; + xmlChar *select; /* new value to adopt if any */ + }; + +#ifdef USE_GNOME_DOCS + +/** + * searchInit: + * + * Initialize the search module + * + * Returns 1 if search structures have been initialized properly and all + * memory required has been obtained, + * 0 otherwise +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Initialize the search module + * + * @returns 1 if search structures have been initialized properly and all + * memory required has been obtained, + * 0 otherwise +*/ +#endif +#endif + int searchInit(void); + + +#ifdef USE_GNOME_DOCS + +/** + * searchFree: + * + * Free all memory used by the search module + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free all memory used by the search module + */ +#endif +#endif + void searchFree(void); + + +#ifdef USE_GNOME_DOCS + +/** + * searchNewInfo: + * @type: What type of search is required + * + * Create a new search + * + * Returns A valid search info pointer if successful + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Create a new search + * + * @returns valid search info pointer if successful + * NULL otherwise + * + * @param type What type of search is required + */ +#endif +#endif + searchInfoPtr searchNewInfo(SearchEnum type); + + +#ifdef USE_GNOME_DOCS + +/** + * searchFreeInfo: + * @info: A valid search info + * + * Free memory used by @info + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Free memory used by @p info + * + * @param info A valid search info + * + */ +#endif +#endif + void searchFreeInfo(searchInfoPtr info); + + +#ifdef USE_GNOME_DOCS + +/** + * searchEmpty: + * + * Empty the seach data base of its contents + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Empty the seach dataBase of its contents + * + * @returns 1 on success, + * 0 otherwise + */ +#endif +#endif + int searchEmpty(void); + + +#ifdef USE_GNOME_DOCS + +/** + * searchDoc: + * + * Return the document used for seaching ie the search dataBase + * + * Returns The document used for searching + * Dangerous function to use! Does NOT return a copy of + * search data so don't free it + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Return the document used for seaching ie the search dataBase + * + * @returns the document used for searching + * Dangerous function to use! Does NOT return a copy of + * search data so don't free it + */ +#endif +#endif + xmlDocPtr searchDoc(void); + + +#ifdef USE_GNOME_DOCS + +/** + * searchRootNode: + * + * Get the topmost node in the search dataBase + * + * Returns The topmost xml node in search dataBase. + * Dangerous function to use! Does NOT return a copy of + * search root node so don't free it + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Get the topmost node in the search dataBase + * + * @returns The topmost xml node in search dataBase. + * Dangerous function to use! Does NOT return a copy of + * search root node so don't free it + */ +#endif +#endif + xmlNodePtr searchRootNode(void); + + +#ifdef USE_GNOME_DOCS + +/** + * searchAdd: + * @node: Is valid + * + * Add a node to the search dataBase + * + * Returns 1 if able to add @node to top node in search dataBase , + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Add a node to the search dataBase + * + * @returns 1 if able to add @p node to top node in search dataBase, + * 0 otherwise + * + * @param node Is valid + */ +#endif +#endif + int searchAdd(xmlNodePtr node); + + +#ifdef USE_GNOME_DOCS + +/** + * searchSave: + * @fileName: A valid file name, or NULL for the default + * + * Save the search dataBase to @fileName + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Save the search dataBase to @p fileName + * + * @returns 1 on success, + * 0 otherwise + * + * @param fileName Valid file name + */ +#endif +#endif + int searchSave(const xmlChar * fileName); + + +#ifdef USE_GNOME_DOCS + +/** + * searchQuery: + * @query: The query to run . If NULL then query is "//search/ *" + * @tempFile: Where do we load the search dataBase from to execute + * query. If tempFile is NULL "searchresult.xml" is used + * @outputFile : Where do we store the result. If NULL + * then default to "searchresult.html" + * + * Send query as parameter for execution of search.xsl using + * data stored in @tempFile + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Send query as parameter for execution of search.xsl using + * data stored in @p tempFile + * + * @returns 1 on success, + * 0 otherwise + * + * @param query The Query to run. If NULL then @p query defaults to "//search/ *" + * @param tempFile Where do we load the search dataBase from to execute + * query. If @p tempFile is NULL default is "search.data" + * @param outputFile Where do we store the result. If NULL + * then default to "searchresult.html" + */ +#endif +#endif + int searchQuery(const xmlChar * tempFile, const xmlChar * outputFile, + const xmlChar * query); + + +#ifdef USE_GNOME_DOCS + +/** + * updateSearchData: + * @styleCtxt: Not used + * @style: Is valid + * @data: Not used but MUST be NULL for the moment + * @variableTypes: What types of variables to look + * + * Update the searchDatabase + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Update the search dataBase + * + * @returns 1 if able to update the search dataBase, + * 0 otherwise + * @param styleCtxt Not used + * @param style Is valid + * @param data Not used but MUST be NULL for the moment + * @param variableTypes What types of variables to look + */ +#endif +#endif + int updateSearchData(xsltTransformContextPtr styleCtxt, + xsltStylesheetPtr style, + void *data, VariableTypeEnum variableTypes); + + +#ifdef USE_GNOME_DOCS + +/** + * scanForBreakPoint: + * @payload: A valid breakPointPtr + * @data: The criteria to look for and a valid searchInfoPtr of + * type SEARCH_BREAKPOINT + * @name: Not used + * + * Test if break point matches criteria given by @data. If so then + * set @data->found to 1 and stores reference to break point found in + * @data->data->node + * otherwise @data is unchanged +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Test if break point matches criteria given by @p data. If so then + * set @p data->found to 1 and stores reference to break point found in + * @p data->data->node + * otherwise @p data is unchanged + * + * @param payload A valid breakPointPtr + * @param data The criteria to look for and a valid searchInfoPtr of + * type SEARCH_BREAKPOINT + * @param name Not used + * +*/ +#endif +#endif + void scanForBreakPoint(void *payload, void *data, xmlChar * name); + + +#ifdef USE_GNOME_DOCS + +/** + * scanForNode: + * @payload: A valid xmlNodePtr + * @data: The criteria to look for and a valid searchInfo of + * type SEARCH_NODE + * @name: Not used + + * Test if node matches criteria given by @data if so then set @data->found + * to 1 and stores reference to node found in @data->data->node + * otherwise @data is unchanged + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Test if node matches criteria given by @p data if so then + * set @p data->found to 1 and stores reference to node found in + * @p data->data->node. + * otherwise @p data is unchanged + * + * @param payload A valid xmlNodePtr + * @param data The criteria to look for and a valid searchInfo of + * type SEARCH_NODE + * @param name Not used +*/ +#endif +#endif + void scanForNode(void *payload, void *data, xmlChar * name); + + +#ifdef USE_GNOME_DOCS + +/** + * findNodeByLineNo: + * @ctxt: Valid ctxt to look into + * @url: Non-null, non-empty file name that has been loaded by debugger + * @lineNumber: @lineNumber >= 0 and is available in @url + * + * Finds the closest line number in file specified that can be a point + * + * Returns The node at line number number specified if successfull, + * NULL otherwise + */ + +#else +#ifdef USE_KDE_DOCS + +/** + * Find the closest line number in file specified that can be a point + * + * @returns The node at line number specified if successful, + * NULL otherwise + * + * @param ctxt Valid ctxt to look into + * @param url Non-null, non-empty file name that has been loaded by + * debugger + * @param lineNumber @p lineNumber >= 0 and is available in @p url +*/ +#endif +#endif + xmlNodePtr findNodeByLineNo(xsltTransformContextPtr ctxt, + const xmlChar * url, long lineNumber); + + +#ifdef USE_GNOME_DOCS + +/** + * findTemplateNode: + * @style: A valid stylesheet collection to look into + * @name: A valid template name to look for + * + * Find a template node + * + * Returns The template node found if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Find a template node + * + * @returns The template node found if successful, + * NULL otherwise + * + * @param style A Valid stylesheet collection to look into + * @param name Valid template name to look for + */ +#endif +#endif + xmlNodePtr findTemplateNode(xsltStylesheetPtr style, + const xmlChar * name); + + +#ifdef USE_GNOME_DOCS + +/** + * findBreakPointByName: + * @templateName: The template name to look for + * + * Find the breakpoint at template with "match" or "name" equal + * to templateName + * + * Returns The break point that matches @templateName + * NULL otherwise +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Find the breakpoint at template with "match" or "name" equal + * to templateName + * + * @returns The break point that matches @p templateName + * NULL otherwise + * + * @param templateName Valid template name to look for +*/ +#endif +#endif + breakPointPtr findBreakPointByName(const xmlChar * templateName); + + +#ifdef USE_GNOME_DOCS + +/** + * findBreakPointById: + * @id: The break point id to look for + * + * Find a break point by its id + * + * Returns The break point with given the break point id if found, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Find a break point by its id + * + * @returns The break point with given the break point id if found, + * NULL otherwise + * + * @param id The break point id to look for + */ +#endif +#endif + breakPointPtr findBreakPointById(int id); + + +#ifdef USE_GNOME_DOCS + +/** + * findNodesByQuery: + * @query: The xpath query to run, see docs/en/search.dtd for more details + * + * Find nodes in search dataBase using an xpath query + * + * Returns The nodes that match the given query on success, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Find nodes in search dataBase using an xpath query + * + * @returns The nodes that match the given query on success, + * NULL otherwise + * + * @param query The xpath query to run, see docs/en/search.dtd for more details + */ +#endif +#endif + xmlXPathObjectPtr findNodesByQuery(const xmlChar * query); + + +#ifdef USE_GNOME_DOCS + +/** + * walkBreakPoints: + * @walkFunc: The function to callback for each break point found + * @data: The extra data to pass onto walkFunc + * + * Walks through all break points calling walkFunc for each. The payload + * sent to walkFunc is of type breakPointPtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all break points calling walkFunc for each. The payload + * sent to walkFunc is of type breakPointPtr + * + * @param walkFunc The function to callback for each break point found + * @param data The extra data to pass onto @p walkFunc + */ +#endif +#endif + void walkBreakPoints(xmlHashScanner walkFunc, void *data); + + +#ifdef USE_GNOME_DOCS + +/** + * walkTemplates: + * @walkFunc: The function to callback for each template found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all templates calling walkFunc for each. The payload + * of walkFunc is of type xsltTemplatePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all templates found in @p style calling walkFunc for each. + * The payload of walkFunc is of type xsltTemplatePtr + * + * @param walkFunc The function to callback for each template found + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkTemplates(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkStylesheets: + * @walkFunc: The function to callback for each stylesheet found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all templates calling walkFunc for each. The payload + * sent to walkFunc is of type xsltStylesheetPtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all stylesheets found in @p style calling walkFunc for + * each. The payload sent to walkFunc is of type xsltStylesheetPtr + * + * @param walkFunc The function to callback for each stylesheet found + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkStylesheets(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkGlobals: + * @walkFunc: The function to callback for each gobal variable found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Call walkFunc for each global variable. The payload + * sent to walkFunc is of type xmlNodePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Call walkFunc for each global variable found in @p style. The payload + * sent to walkFunc is of type xmlNodePtr + * + * @param walkFunc The function to callback for each gobal variable found + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkGlobals(xmlHashScanner walkFunc, + void *data, xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkLocals: + * @walkFunc: The function to callback for each local variable found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all local variables calling walkFunc for each. The payload + * of walkFunc is of type xmlNodePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all local variables found in @p style calling + * walkFunc for each. The payload of walkFunc is of type xmlNodePtr + * + * @param walkFunc The function to callback for each local variable found + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkLocals(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkIncludes: + * @walkFunc: The function to callback for each included stylesheet + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all included stylesheets calling walkFunc for each. + * The payload of walkFunc is of type xmlNodePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all included stylesheets found in @p style, + * calling walkFunc for each. The payload of walkFunc is of + * type xmlNodePtr + * + * @param walkFunc The function to callback for each included stylesheet + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkIncludes(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkIncludeInst: + * @walkFunc: The function to callback for each xsl:include instruction found + * @data: The extra data to pass onto walkFunc + * @style: The stylesheet to start from + * + * Walks through all xsl:include calling walkFunc for each. The payload + * of walkFunc is of type xmlNodePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Walks through all xsl:include calling walkFunc for each. The payload + * of walkFunc is of type xmlNodePtr + * + * @param walkFunc The function to callback for each xsl:include instruction found + * @param data The extra data to pass onto @p walkFunc + * @param style The stylesheet to start from + */ +#endif +#endif + void walkIncludeInst(xmlHashScanner walkFunc, void *data, + xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * walkChildNodes: + * @walkFunc: The function to callback for each child/sibling found + * @data: The extra data to pass onto walkFunc + * @node: Is valid + * + * Call walkFunc for each child of @node the payload sent to walkFunc is + * a xmlNodePtr + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Call walkFunc for each child of @p node the payload sent to walkFunc is + * a xmlNodePtr + * + * @param walkFunc The function to callback for each child/sibling found + * @param data The extra data to pass onto @p walkFunc + * @param node Valid xmlNodePtr + */ +#endif +#endif + void walkChildNodes(xmlHashScanner walkFunc, void *data, + xmlNodePtr node); + + + +#ifdef USE_GNOME_DOCS + +/** + * searchBreakPointNode: + * @breakPtr: Is valid + * + * Convert @breakPtr into search dataBase format + * + * Returns @breakPtr as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p breakPtr into search dataBase format + * + * @returns @p breakPtr as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + * + * @param breakPtr Is valid + */ +#endif +#endif + xmlNodePtr searchBreakPointNode(breakPointPtr breakPtr); + + +#ifdef USE_GNOME_DOCS + +/** + * searchTemplateNode: + * @templNode: Is valid + * + * Convert @templateNode into search dataBase format + * + * Returns @templNode as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p templateNode into search dataBase format + * + * @returns @p templNode as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + * + * @param templNode A valid template node + */ +#endif +#endif + xmlNodePtr searchTemplateNode(xmlNodePtr templNode); + + +#ifdef USE_GNOME_DOCS + +/** + * searchGlobalNode: + * @globalVariable: Is valid + * + * Convert @globalVariable into search dataBase format + * + * Returns @globalVariable as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p globalVariable into search dataBase format + * + * @returns @p globalVariable as a new xmlNode in search dataBase + * format if successful, + * NULL otherwise + * + * @param globalVariable A valid xmlNodePtr node + * + */ +#endif +#endif + xmlNodePtr searchGlobalNode(xmlNodePtr globalVariable); + + +#ifdef USE_GNOME_DOCS + +/** + * searchLocalNode: + * @localvariable: Is valid + * + * Convert @localVariable into search dataBase format + * + * Returns @localVariable as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p localVariable into search dataBase format + * + * @returns @p localVariable as a new xmlNode in search dataBase + * format if successful, + * NULL otherwise + * + * @param localVariable Is valid + * + */ +#endif +#endif + xmlNodePtr searchLocalNode(xmlNodePtr localVariable); + + +#ifdef USE_GNOME_DOCS + +/** + * searchSourceNode: + * @style: Is valid + * + * Convert @style into search dataBase format + * + * Returns @style as a new xmlNode in search dataBase format if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p style into search dataBase format + * + * @returns @p style as a new xmlNode in search dataBase format if successful, + * NULL otherwise + * + * @param style Is valid + */ +#endif +#endif + xmlNodePtr searchSourceNode(xsltStylesheetPtr style); + + +#ifdef USE_GNOME_DOCS + +/** + * searchIncludeNode: + * @include: Is a valid xsl:include instruction + * + * Convert @include into search dataBase format + * + * Returns @include as a new xmlNode in search dataBase format if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Convert @p include into search dataBase format + * + * @returns @p include as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + * + * @param include Is a valid xsl:include instruction + * + */ +#endif +#endif + xmlNodePtr searchIncludeNode(xmlNodePtr include); + + +#ifdef USE_GNOME_DOCS + +/** + * searchCallStackNode: + * @callStackItem: Is valid + * + * Convert @callStackItem into search dataBase format + * + * Returns @callStackItem as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + *Convert @p include into search dataBase format + * + * @returns @p callStackItem as a new xmlNode in search dataBase + * format if successful, + * NULL otherwise + * @param callStackItem Is valid + */ +#endif +#endif + xmlNodePtr searchCallStackNode(callPointPtr callStackItem); + + + +#ifdef USE_GNOME_DOCS + +/** + * searchCommentNode: + * @sourceNode: Is valid + * + * Find documentation comment that applies to @sourceNode. If found convert comment + * into search dataBase format required + * + * Returns Documentation comment for @node as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + + /** + * Find documentation comment that applies to @p sourceNode. If found convert comment + * into search dataBase format required + * + * Returns Documentation comment for @node as a new xmlNode in search dataBase format + * if successful, + * NULL otherwise + * + * @param node Is valid + */ +#endif +#endif + xmlNodePtr searchCommentNode(xmlNodePtr node); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/search_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/search_cmds.cpp new file mode 100644 index 00000000..1dc65190 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/search_cmds.cpp @@ -0,0 +1,88 @@ + +/*************************************************************************** + search_cmds.c - search related commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "options.h" +#include "search.h" + +/* ----------------------------------------- + + Seach related commands + + ------------------------------------------- */ + + +/** + * xslDbgShellSearch: + * @styleCtxt: Is valid + * @style: Is valid + * @arg: The xpath query to use for searching dataBase and in UTF-8 + * + * Displays the result of performing a query on the search dataBase + * + * Returns 1 if able to run query with @arg, + * 0 otherwise + */ +int +xslDbgShellSearch(xsltTransformContextPtr styleCtxt, + xsltStylesheetPtr style, xmlChar * arg) +{ + int result = 0; + xmlChar buff[DEBUG_BUFFER_SIZE]; + const xmlChar *sortOption = (xmlChar *) "-sort "; + int sortOptionLen = xmlStrLen(sortOption); + + if (optionsGetStringOption(OPTIONS_DOCS_PATH) == NULL) { + xsldbgGenericErrorFunc(i18n("Error: No path to documentation; aborting searching.\n")); +#ifdef USE_DOCS_MACRO + xsldbgGenericErrorFunc(i18n("Error: Error in value of USE_DOCS_MACRO; look at Makefile.am.\n")); +#else + xsldbgGenericErrorFunc(i18n("Error: Required environment variable %1 not set to the directory of xsldbg documentation.\n").arg((const char*)XSLDBG_DOCS_DIR_VARIABLE)); +#endif + return result; /* failed */ + } + + if (!styleCtxt || !style) { + xsldbgGenericErrorFunc(i18n("Error: Stylesheet not valid, files not loaded yet?\n")); + return result; + } + + result = updateSearchData(styleCtxt, style, NULL, DEBUG_ANY_VAR); + trimString(arg); + if (xmlStrLen(arg) == 0) { + arg = (xmlChar *) "//search/*"; + } + strncpy((char *) buff, (char *) arg, sortOptionLen); + if (xmlStrEqual(buff, sortOption)) { + /* yep do sorting as well */ + if (snprintf + ((char *) buff, DEBUG_BUFFER_SIZE, + "--param dosort 1 --param query \"%s\"", + &arg[sortOptionLen])) { + result = result && searchQuery(NULL, NULL, buff); + } + } else { + if (snprintf + ((char *) buff, DEBUG_BUFFER_SIZE, + "--param dosort 0 --param query \"%s\"", arg)) { + result = result && searchQuery(NULL, NULL, buff); + } + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/template_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/template_cmds.cpp new file mode 100644 index 00000000..10deb686 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/template_cmds.cpp @@ -0,0 +1,331 @@ + +/*************************************************************************** + template_cmds.c - template commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "files.h" +#include "utils.h" +#include "xsldbgmsg.h" +#include "xsldbgthread.h" /* for getThreadStatus */ + +static int printCounter; /* Dangerous name think of a better one */ + +/* ----------------------------------------- + Private function declarations for files.c + -------------------------------------------*/ + +/** + * xslDbgShellPrintStylesheetsHelper: + * @payload :valid xxsltStylesheetPtr + * @data : not used + * name : not used + * + * Print out the stylesheet name from the stylesheet given to + * us via walkStylesheets + */ +void + xslDbgShellPrintStylesheetsHelper(void *payload, + void *data, + xmlChar * name); + + +/** + * xslDbgShellPrintStylesheetsHelper2: + * @payload :valid xmlNodePtr of included stylesheet + * @data : not used + * name : not used + * + * Print out the stylesheet name from the stylesheet given to + * us via walkIncludes + */ +void + xslDbgShellPrintStylesheetsHelper2(void *payload, + void *data, + xmlChar * name); + + +/** + * printTemplateHelper: + * @templ: Is valid + * @verbose: Either 1 or 0 + * @templateCount: Is valid + * @count: Is valid + * @templateName: template name to print and in UTF-8, may be NULL + * + * This display the templates in the same order as they are in the + * stylesheet. If verbose is 1 then print more information + * For each template found @templateCount is increased + * For each printed template @printCount is increased + */ +void printTemplateHelper(xsltTemplatePtr templ, int verbose, + int *templateCount, int *count, + xmlChar * templateName); + +/* ------------------------------------- + End private functions +---------------------------------------*/ + + + +/** + * printTemplateHelper: + * @templ: Is valid + * @verbose: Either 1 or 0 + * @templateCount: Is valid + * @count: Is valid + * @templateName: template name to print, may be NULL + * + * This display the templates in the same order as they are in the + * stylesheet. If verbose is 1 then print more information + * For each template found @templateCount is increased + * For each printed template @printCount is increased + */ +void +printTemplateHelper(xsltTemplatePtr templ, int verbose, + int *templateCount, int *count, xmlChar * templateName) +{ + xmlChar *name, *defaultUrl = (xmlChar *) "<n/a>"; + const xmlChar *url; + + if (!templ) + return; + + *templateCount = *templateCount + 1; + printTemplateHelper(templ->next, verbose, + templateCount, count, templateName); + if (templ->elem && templ->elem->doc && templ->elem->doc->URL) { + url = templ->elem->doc->URL; + } else { + url = defaultUrl; + } + + if (templ->match) + name = xmlStrdup(templ->match); + else + name = fullQName(templ->nameURI, templ->name); + + if (name) { + if (templateName && + (xmlStrcmp(templateName, name) != 0)) { + /* search for template name supplied failed */ + /* empty */ + } else { + xmlChar *modeTemp = NULL; + *count = *count + 1; + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListQueue(templ); + } else { + modeTemp = fullQName(templ->modeURI, templ->mode); + if (verbose) + xsldbgGenericErrorFunc(i18n(" template: \"%1\" mode: \"%2\" in file \"%3\" at line %4\n").arg(xsldbgText(name)).arg(xsldbgText(modeTemp)).arg(xsldbgUrl(url)).arg(xmlGetLineNo(templ->elem))); + else + xsldbgGenericErrorFunc(QString("\"%s\" ").arg(xsldbgText(name))); + if (modeTemp) + xmlFree(modeTemp); + } + } + + xmlFree(name); + + } +} + + +/** + * xslDbgShellPrintTemplateNames: + * @styleCtxt: Is valid + * @ctxt: Not used + * @arg: Not used + * @verbose: If 1 then print extra messages about templates found, + * otherwise print normal messages only + * @allFiles: If 1 then look for all templates in stylsheets found in + * @styleCtxt + * otherwise look in the stylesheet found by + * debugXSLBreak function + * + * Print out the list of template names found that match critieria + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellPrintTemplateNames(xsltTransformContextPtr styleCtxt, + xmlShellCtxtPtr ctxt, + xmlChar * arg, int verbose, int allFiles) +{ + Q_UNUSED(ctxt); + int templateCount = 0, printedTemplateCount = 0; + int result = 0; + xsltStylesheetPtr curStyle; + xsltTemplatePtr templ; + + if (xmlStrLen(arg) == 0) { + arg = NULL; + } else { + allFiles = 1; /* make sure we find it if we can */ + } + + if (!styleCtxt) { + xsldbgGenericErrorFunc(i18n("Error: Stylesheet is not valid.\n")); + return result; + } + + if (allFiles) + curStyle = styleCtxt->style; + else { + /* try to find files in the current stylesheet */ + /* root copy is set to the stylesheet found by debugXSLBreak */ + if (debugXSLGetTemplate()) + curStyle = debugXSLGetTemplate()->style; + else + curStyle = NULL; + } + + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_TEMPLATE_CHANGED); + while (curStyle) { + templ = curStyle->templates; + /* print them out in the order their in the file */ + printTemplateHelper(templ, verbose, &templateCount, + &printedTemplateCount, arg); + if (curStyle->next) + curStyle = curStyle->next; + else + curStyle = curStyle->imports; + } + notifyListSend(); + } else { + xsltGenericError(xsltGenericErrorContext, "\n"); + while (curStyle) { + templ = curStyle->templates; + /* print them out in the order their in the file */ + printTemplateHelper(templ, verbose, &templateCount, + &printedTemplateCount, arg); + xsltGenericError(xsltGenericErrorContext, "\n"); + if (curStyle->next) + curStyle = curStyle->next; + else + curStyle = curStyle->imports; + } + if (templateCount == 0) { + xsldbgGenericErrorFunc(i18n("\tNo XSLT templates found.\n")); + } else { + xsldbgGenericErrorFunc(i18n("\tTotal of %n XSLT template found", "\tTotal of %n XSLT templates found", templateCount) + QString("\n")); + xsldbgGenericErrorFunc(i18n("\tTotal of %n XSLT template printed", "\tTotal of %n XSLT templates printed", printedTemplateCount) + QString("\n")); + } + } + + result = 1; + return result; +} + + +/** + * xslDbgShellPrintStylesheetsHelper: + * @payload :valid xsltStylesheetPtr + * @data : not used + * name : not used + * + * Print out the stylesheet name from the stylesheet given to + * us via walkStylesheets + */ +void +xslDbgShellPrintStylesheetsHelper(void *payload, + void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xsltStylesheetPtr style = (xsltStylesheetPtr) payload; + + if (style && style->doc && style->doc->URL) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) + notifyListQueue(payload); + else + /* display the URL of stylesheet */ + xsldbgGenericErrorFunc(i18n(" Stylesheet %1\n").arg(xsldbgUrl(style->doc->URL))); + printCounter++; + } +} + + +/** + * xslDbgShellPrintStylesheetsHelper2: + * @payload :valid xmlNodePtr of included stylesheet + * @data : not used + * name : not used + * + * Print out the stylesheet name from the stylesheet given to + * us via walkIncludes + */ +void +xslDbgShellPrintStylesheetsHelper2(void *payload, + void *data, + xmlChar * name) +{ + Q_UNUSED(data); + Q_UNUSED(name); + xmlNodePtr node = (xmlNodePtr) payload; + + if (node && node->doc && node->doc->URL) { + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) + notifyListQueue(payload); + else + /* display the URL of stylesheet */ + xsldbgGenericErrorFunc(i18n(" Stylesheet %1\n").arg(xsldbgUrl(node->doc->URL))); + printCounter++; + } +} + + +/** + * xslDbgShellPrintStyleSheets: + * @arg: The stylesheets of interests and in UTF-8, is NULL for all stylsheets + * + * Print stylesheets that can be found in loaded stylsheet + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellPrintStyleSheets(xmlChar * arg) +{ + Q_UNUSED(arg); + printCounter = 0; + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + notifyListStart(XSLDBG_MSG_SOURCE_CHANGED); + walkStylesheets((xmlHashScanner) xslDbgShellPrintStylesheetsHelper, + NULL, filesGetStylesheet()); + notifyListSend(); + notifyListStart(XSLDBG_MSG_INCLUDED_SOURCE_CHANGED); + walkIncludes((xmlHashScanner) xslDbgShellPrintStylesheetsHelper2, + NULL, filesGetStylesheet()); + notifyListSend(); + } else { + walkStylesheets((xmlHashScanner) xslDbgShellPrintStylesheetsHelper, + NULL, filesGetStylesheet()); + walkIncludes((xmlHashScanner) xslDbgShellPrintStylesheetsHelper2, + NULL, filesGetStylesheet()); + if (printCounter != 0) + xsldbgGenericErrorFunc(i18n("\tTotal of %n XSLT stylesheet found.", "\tTotal of %n XSLT stylesheets found.", printCounter) + QString("\n")); + else + /* strange but possible */ + xsldbgGenericErrorFunc(i18n("\tNo XSLT stylesheets found.\n")); + } + return 1; /* always succeed */ +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/trace_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/trace_cmds.cpp new file mode 100644 index 00000000..3893be67 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/trace_cmds.cpp @@ -0,0 +1,77 @@ + +/*************************************************************************** + oc_cmds.c - libxslt parameter commands for xsldbg + ------------------- + begin : Wed Nov 21 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" +#include "debugXSL.h" +#include "options.h" + + +/* ----------------------------------------- + + Tracing related commands + + ------------------------------------------- */ + + +/** + * xslDbgShellTrace: + * @arg: Not used + * + * Start the tracing of the stylesheet. First need to restart it. + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellTrace(xmlChar * arg) +{ + Q_UNUSED(arg); + xslDebugStatus = DEBUG_RUN_RESTART; + optionsSetIntOption(OPTIONS_TRACE, TRACE_ON); + return 1; +} + + +/** + * xslDbgShellWalk: + * @arg: An interger between 0 and 9 indicate the speed of walk + * + * Start walking through the stylesheet. + * + * Returns 1 on success, + * 0 otherwise + */ +int +xslDbgShellWalk(xmlChar * arg) +{ + int result = 0; + + long speed = WALKSPEED_NORMAL; + + if (xmlStrLen(arg) + && (!sscanf((char *) arg, "%ld", &speed) || ((speed < 0) || (speed > 9)))) { + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to command %1.\n").arg("walk")); + xsldbgGenericErrorFunc(i18n("Warning: Assuming normal speed.\n")); + speed = WALKSPEED_NORMAL; + } + result = 1; + optionsSetIntOption(OPTIONS_WALK_SPEED, speed); + xslDebugStatus = DEBUG_WALK; + + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/utils.cpp b/kxsldbg/kxsldbgpart/libxsldbg/utils.cpp new file mode 100644 index 00000000..c63c07fc --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/utils.cpp @@ -0,0 +1,187 @@ + +/************************************************************************** + utils.c - misc utils + + ------------------- + begin : Thur Jan 31 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + +#include "utils.h" + +/** + * trimString: + * @text : A valid string with leading or trailing spaces + * + * Remove leading and trailing spaces off @text + * stores result back into @text + * + * Returns 1 on success, + * 0 otherwise + */ +int +trimString(xmlChar * text) +{ + int result = 0; + xmlChar *start, *end; + + if (text && xmlStrlen(text)) { + start = text; + end = text + xmlStrLen(text) - 1; + while (_IS_BLANK(*start) && (start <= end)) + start++; + + while (_IS_BLANK(*end) && (end >= start)) + end--; + + /* copy to @text */ + while (start <= end) { + *text = *start; + text++; + start++; + } + + *text = '\0'; + result = 1; + } + return result; +} + + +/** + * splitString: + * @textIn: The string to split + * @maxStrings: The max number of strings to put into @out + * @out: Is valid and at least the size of @maxStrings + * + * Split string by white space and put into @out + * + * Returns 1 on success, + * 0 otherwise + */ +int +splitString(xmlChar * textIn, int maxStrings, xmlChar ** out) +{ + int wordCount = 0; + int foundQuote = 0; + + if (!textIn || !out) + return wordCount; + + + while ((*textIn != '\0') && (wordCount < maxStrings)) { + /*skip the first spaces ? */ + while (_IS_BLANK(*textIn)) + textIn++; + + if (*textIn == '\"') { + textIn++; + foundQuote = 1; + } + out[wordCount] = textIn; + + /* look for end of word */ + if (foundQuote == 0) { + while (!_IS_BLANK(*textIn) && (*textIn != '\0')) + textIn++; + + if (*textIn != '\0') { + *textIn = '\0'; + textIn++; + } + + if (xmlStrLen(out[wordCount]) > 0) { + wordCount++; + } + } else { + /* look for ending quotation mark */ + while ((*textIn != '\0') && (*textIn != '\"')) + textIn++; + if (*textIn == '\0') { + xsldbgGenericErrorFunc(i18n("Error: Unmatched quotes in input.\n")); + wordCount = 0; + break; + } + *textIn = '\0'; + textIn++; /* skip the '"' which is now a '\0' */ + foundQuote = 0; + wordCount++; + } + + } + + if (*textIn != '\0') + wordCount = 0; /* We have not processed all the text givent to us */ + return wordCount; +} + + + +/** + * lookupName: + * @name : Is valid + * @matchList : A NULL terminated list of names to use as lookup table + * + * Lookup and name in a list + * + * Returns The id of name found in @matchList, + * 0 otherwise +*/ +int +lookupName(xmlChar * name, xmlChar ** matchList) +{ + int result = -1, nameIndex; + + if (!name || !matchList) + return result; + + for (nameIndex = 0; matchList[nameIndex]; nameIndex++) { + if (xmlStrEqual(name, matchList[nameIndex])) { + result = nameIndex; + break; + } + } + + return result; +} + +/** + * fullQName: + * @nameURI : QName part of name + * @name : Local part of name + * + * Join nameURI to name + * + * Returns a copy of "nameURI:name" + * + */ + +xmlChar * fullQName(const xmlChar* nameURI, const xmlChar * name) +{ + xmlChar *result = NULL; + if (!nameURI && !name) + result = xmlStrdup((xmlChar*)""); + else{ + if (nameURI == NULL){ + result = xmlStrdup(name); + }else{ + result = (xmlChar*) xmlMalloc(sizeof(char) * ( + xmlStrLen(name) + + xmlStrLen(nameURI) + 3)); + if (result) + sprintf((char*)result, "%s:%s", (char*)nameURI, (char*)name); + } + } + return result; +} + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/utils.h b/kxsldbg/kxsldbgpart/libxsldbg/utils.h new file mode 100644 index 00000000..e5cd4bfc --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/utils.h @@ -0,0 +1,217 @@ + +/************************************************************************** + utils.c - declaration for misc utils this is + mixed bag of functions so it is + not realy a module hense no need + for a utils prefix its functions + + ------------------- + begin : Thur Jan 31 2002 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + **************************************************************************/ + +/************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + **************************************************************************/ + +#ifndef XSLDBG_UTILS_H +#define XSLDBG_UTILS_H + +#ifndef BUILD_DOCS +#include <stdio.h> +#include <string.h> +#include <libxml/tree.h> +#include <libxml/debugXML.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/xsltutils.h> +#include <libxml/xpath.h> +#endif + +#include "xsldbg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Make things simpler when working between char* and xmlChar* . + By definition a char is the same size as an xmlChar(unsigned char). +*/ + +#ifndef BUILD_DOCS +#define xmlStrLen(text) strlen((char*)(text)) +#define xmlStrCat(a, b) strcat((char*)(a), (char*)(b)) +#define xmlStrCmp(a, b) strcmp((char*)(a), (char*)(b)) +#define xmlStrnCmp(a, b, c) strncmp((char*)(a), (char*)(b), c) +#define xmlStrCpy(a, b) strcpy((char*)(a), (char*)(b)) +#define xmlStrnCpy(a, b, c) strncpy((char*)(a),(char*)(b), c) +#define xmlStrChr(a, b) strchr((char*)(a), b) +#define xmlStrrChr(a, b) strrchr((char*)(a), b) +#endif + +/* what char is use to separate directories in an URI*/ +#define URISEPARATORCHAR '/' + + /* Handle the differences in path and quote character between + * win32 and *nix systems */ +#ifdef WIN32 +#define QUOTECHAR ' ' +#define PATHCHAR '\\' +#else +#define QUOTECHAR '\"' +#define PATHCHAR '/' +#endif + + +/* JRF: Although RISC OS native paths use . as a separator, the arguments + to xsldbg are passed in unix or URI form, and thus the above + specification is correct. */ + + + +/** + * _IS_BLANK: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec + * + * [3] S ::= (#x20 | #x9 | #xD | #xA)+ + */ +#define _IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \ + ((c) == 0x0D)) + + + + +#ifdef USE_GNOME_DOCS + +/** + * trimString: + * @text : A valid string with leading or trailing spaces + * + * Remove leading and trailing spaces off @text + * stores result back into @text + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Remove leading and trailing spaces off @p text + * stores result back into @p text + * + * @returns 1 on success, + * 0 otherwise + * + * @param text A valid string with leading or trailing spaces + */ +#endif +#endif + int trimString(xmlChar * text); + + +#ifdef USE_GNOME_DOCS + +/** + * splitString: + * @textIn: The string to split + * @maxStrings: The max number of strings to put into @out + * @out: Is valid and at least the size of @maxStrings + * + * Split string by white space and put into @out + * + * Returns 1 on success, + * 0 otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Spit string by white space and put into @p out + * + * @returns 1 on success, + * 0 otherwise + * + * @param textIn The string to split + * @param maxStrings The max number of strings to put into @p out + * @param out Is valid and at least the size of @p maxStrings + */ +#endif +#endif + int splitString(xmlChar * textIn, int maxStrings, xmlChar ** out); + + + +#ifdef USE_GNOME_DOCS + +/** + * lookupName: + * @name : Is valid + * @matchList : A NULL terminated list of names to use as lookup table + * + * Lookup and name in a list + * + * Returns The id of name found in @matchList, + * 0 otherwise +*/ +#else +#ifdef USE_KDE_DOCS + +/** + * Lookup and name in a list + * + * + * @returns The id of name found in @p matchList + * 0 otherwise + * + * @param name Is valid + * @param matchList A NULL terminated list of names to use as lookup table + * +*/ +#endif +#endif + int lookupName(xmlChar * name, xmlChar ** matchList); + +#ifdef USE_GNOME_DOCS + +/** + * fullQName: + * @nameURI : QName part of name + * @name : Local part of name + * + * Join nameURI to name + * + * Returns a copy of "nameURI:name" + * + */ + +#else +#ifdef USE_KDE_DOCS + +/** + * Join nameURI to name + * + * @returns a copy of "nameURI:name" + + * fullQName: + * @param nameURI : QName part of name + * @param name : Local part of name + * + * + */ +#endif +#endif + + xmlChar * fullQName(const xmlChar* nameURI, const xmlChar * name); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/variable_cmds.cpp b/kxsldbg/kxsldbgpart/libxsldbg/variable_cmds.cpp new file mode 100644 index 00000000..a00769f4 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/variable_cmds.cpp @@ -0,0 +1,114 @@ + +/*************************************************************************** + variable_cmds.c - description + ------------------- + begin : Sun Dec 30 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <libxml/xpath.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/variables.h> /* needed for xsltVariablesComp */ +#include <libxml/valid.h> /* needed for xmlSplitQName2 */ +#include "xsldbg.h" +#include "debugXSL.h" +#include "search.h" + + +int +xslDbgShellSetVariable(xsltTransformContextPtr styleCtxt, xmlChar * arg) +{ + int result = 0, showUsage = 0; + xmlChar *name, *nameURI, *selectExpr, *opts[3]; + + if (!styleCtxt) { + + xsldbgGenericErrorFunc(i18n("Error: Stylesheet is not valid.\n")); + return result; + } + + if (!arg) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Error: NULL argument provided\n"); +#endif + return result; + } + + if (xmlStrLen(arg) > 1) { + if (splitString(arg, 2, opts) == 2) { + nameURI = NULL; + /* ignore any "$" prefix as user probably didn't mean that + "$" is part of variable name*/ + if (*opts[0] =='$'){ + opts[0] = opts[0] + 1; + } + name = xmlSplitQName2(opts[0], &nameURI); + if (name == NULL) + name = xmlStrdup(opts[0]); + selectExpr = xmlStrdup(opts[1]); + if (name && selectExpr) { + xsltStackElemPtr def = NULL; + + if (styleCtxt->varsNr && styleCtxt->varsTab) { + /* try finding varaible in stack */ + for (int i = styleCtxt->varsNr; i > styleCtxt->varsBase; i--) { + xsltStackElemPtr item = styleCtxt->varsTab[i-1]; + while (item) { + if ((xmlStrCmp(name, item->name) == 0) && + (item->nameURI == NULL + || (xmlStrCmp(name, item->nameURI) == 0))) { + def = item; + break; + } + item = item->next; + } + } + } + + if (def == NULL) + def = (xsltStackElemPtr) + xmlHashLookup2(styleCtxt->globalVars, + name, nameURI); + if (def != NULL) { + if (def->select) { + def->select = xmlDictLookup(styleCtxt->dict, selectExpr, -1); + def->tree = NULL; /* maybe a memory leak, but play it safe */ + def->computed = 1; + if (def->comp->comp) + xmlXPathFreeCompExpr(def->comp->comp); + def->comp->comp = xmlXPathCompile(def->select); + if (def->value) + xmlXPathFreeObject(def->value); + def->value = + xmlXPathEval(def->select, + styleCtxt->xpathCtxt); + result = 1; + } else { + xmlFree(selectExpr); + xsldbgGenericErrorFunc(i18n("Error: Cannot change a variable that does not use the select attribute.\n")); + } + } else + xsldbgGenericErrorFunc(i18n("Error: Variable %1 was not found.\n").arg(xsldbgText(name))); + xmlFree(name); + } else + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } else { + showUsage = 1; + } + + if (showUsage == 1) + xsldbgGenericErrorFunc(i18n("Error: Invalid arguments to command %1.\n").arg("set")); + } + return result; +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.cpp b/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.cpp new file mode 100644 index 00000000..2afdb828 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.cpp @@ -0,0 +1,1367 @@ + +/*************************************************************************** + xsldbg.c - description + ------------------- + begin : Sun Sep 16 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + * Based on file xsltproc.c + * + * by Daniel Veillard + * daniel@veillard.com + * + * xsltproc.c is part of libxslt + * + * + */ + +/* Justin's port version - do not merge into core!!! */ +#define RISCOS_PORT_VERSION "2.01" + +#include <kurl.h> +#include <kdebug.h> +#include "xsldbg.h" +#include "debug.h" +#include "options.h" +#include "utils.h" +#include "files.h" +#include "breakpoint.h" +#include "debugXSL.h" + +#include <libxml/xmlerror.h> +#include "xsldbgmsg.h" +#include "xsldbgthread.h" /* for getThreadStatus */ +#ifdef HAVE_READLINE +# include <readline/readline.h> +# ifdef HAVE_HISTORY +# include <readline/history.h> +# endif +#endif + +/* need to setup catch of SIGINT */ +#include <signal.h> + +/* needed by printTemplateNames */ +#include <libxslt/transform.h> + +/* standard includes from xsltproc*/ +#include <libxslt/xslt.h> +#include <libexslt/exslt.h> +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STDARG_H +#include <stdarg.h> +#endif +#include <libxml/xmlmemory.h> +#include <libxml/debugXML.h> +#include <libxml/xmlerror.h> +#include <libxml/HTMLtree.h> +#include <libxml/xmlIO.h> +#ifdef LIBXML_DOCB_ENABLED +#include <libxml/DOCBparser.h> +#endif +#ifdef LIBXML_XINCLUDE_ENABLED +#include <libxml/xinclude.h> +#endif + +#include <libxml/catalog.h> +#include <libxml/parserInternals.h> + +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> +#include <libxslt/extensions.h> +#include <libexslt/exsltconfig.h> + +#include <kcmdlineargs.h> +#include <kglobal.h> +#include <qfile.h> + +#ifdef WIN32 +#ifdef _MSC_VER +#include <winsock2.h> +#pragma comment(lib, "ws2_32.lib") +#define gettimeofday(p1,p2) +#define HAVE_TIME_H +#include <time.h> +#define HAVE_STDARG_H +#include <stdarg.h> +#endif /* _MS_VER */ +#else /* WIN32 */ +#if defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#elif defined(HAVE_TIME_H) +#include <time.h> +#endif + + +#endif /* WIN32 */ + +#ifndef HAVE_STAT +# ifdef HAVE__STAT + +/* MS C library seems to define stat and _stat. The definition + * is identical. Still, mapping them to each other causes a warning. */ +# ifndef _MSC_VER +# define stat(x,y) _stat(x,y) +# endif +# define HAVE_STAT +# endif +#endif + +#ifdef __riscos + +/* Global definition of our program name on invocation. + This is required such that we can invoke ourselves for processing + search or help messages where our executable does not exist on the + current run path */ +char *xsldbgCommand = NULL; +#endif + +xmlSAXHandler mySAXhdlr; + +FILE *errorFile = NULL; /* we'll set this just before starting debugger */ + +xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL, + const char *ID, + xmlParserCtxtPtr ctxt); + +/* ----------------------------------------- + Private function declarations for xsldbg.c + -------------------------------------------*/ + +/** + * xsldbgInit: + * + * Returns 1 if able to allocate memory needed by xsldbg + * 0 otherwise + */ +int xsldbgInit(void); + + +/** + * xsldbgFree: + * + * Free memory used by xsldbg + */ +void xsldbgFree(void); + + +/** + * printTemplates: + * @style : valid as parsed my xsldbg + * @doc : " " " " " + * + * print out list of template names + */ +void printTemplates(xsltStylesheetPtr style, xmlDocPtr doc); + + +/** + * catchSigInt: + * @value : not used + * + * Recover from a signal(SIGINT), exit if needed + */ +void catchSigInt(int value); + + +/** + * catchSigTerm: + * @value : not used + * + * Clean up and exit + */ +void + catchSigTerm(int value); + +/** + * xsldbgGenericErrorFunc: + * @ctx: Is Valid + * @msg: Is valid + * @...: other parameters to use + * + * Handles print output from xsldbg and passes it to the application if + * running as a thread otherwise send to stderr + */ +void + xsldbgGenericErrorFunc(void *ctx, const char *msg, ...); + +xmlEntityPtr (*oldGetEntity)( void * user_data, const xmlChar * name); + +static xmlEntityPtr xsldbgGetEntity( void * user_data, const xmlChar * name) +{ + xmlEntityPtr ent = NULL; + if (oldGetEntity){ + ent = (oldGetEntity)(user_data, name); + if (ent) + filesEntityRef(ent, ent->children, ent->last); + } + return ent; +} + +/* ------------------------------------- + End private functions + ---------------------------------------*/ + + +/* + * Internal timing routines to remove the necessity to have unix-specific + * function calls + */ + +#if defined(HAVE_GETTIMEOFDAY) +static struct timeval begin, end; + +/* + * startTimer: call where you want to start timing + */ +static void +startTimer(void) +{ + gettimeofday(&begin, NULL); +} + +/* + * endTimer: call where you want to stop timing and to print out a + * message about the timing performed; format is a printf + * type argument + */ +static void +endTimer(const QString& message) +{ + long msec; + + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + +#ifndef HAVE_STDARG_H +#error "endTimer required stdarg functions" +#endif + /* Display the time taken to complete this task */ + xsldbgGenericErrorFunc(i18n("%1 took %2 ms to complete.\n").arg(message).arg(msec)); +} +#elif defined(HAVE_TIME_H) + +/* + * No gettimeofday function, so we have to make do with calling clock. + * This is obviously less accurate, but there's little we can do about + * that. + */ + +clock_t begin, end; +static void +startTimer(void) +{ + begin = clock(); +} +static void +endTimer(const QString& message) +{ + long msec; + + end = clock(); + msec = ((end - begin) * 1000) / CLOCKS_PER_SEC; + +#ifndef HAVE_STDARG_H +#error "endTimer required stdarg functions" +#endif + /* Display the time taken to complete this task */ + xsldbgGenericErrorFunc(i18n("%1 took %2 ms to complete.\n").arg(message).arg(msec)); +} +#else + +/* + * We don't have a gettimeofday or time.h, so we just don't do timing + */ +static void +startTimer(void) +{ + /* + * Do nothing + */ +} +static void +endTimer(const QString& message) +{ + /* + * We can not do anything because we don't have a timing function + */ +#ifdef HAVE_STDARG_H + /* Display the time taken to complete this task */ + xsldbgGenericErrorFunc(i18n("%1 took %2 ms to complete.\n"),arg(message).arg(msec)); +#else + /* We don't have gettimeofday, time or stdarg.h, what crazy world is + * this ?! + */ +#endif +} +#endif + +static void +xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur) +{ + + xmlDocPtr res; + const char *params[8 * 2 + 2]; + int bytesWritten = -1; + int nbparams = 0; + int paramIndex; + parameterItemPtr paramItem; + + /* Copy the parameters accross for libxslt */ + for (paramIndex = 0; + paramIndex < arrayListCount(optionsGetParamItemList()); + paramIndex++) { + paramItem = (parameterItemPtr)arrayListGet(optionsGetParamItemList(), paramIndex); + if (paramItem) { + params[nbparams] = (char *) paramItem->name; + params[nbparams + 1] = (char *) paramItem->value; + nbparams += 2; + } + } + + params[nbparams] = NULL; + +#ifdef LIBXML_XINCLUDE_ENABLED + if (optionsGetIntOption(OPTIONS_XINCLUDE)) { + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); + xmlXIncludeProcess(doc); + if (optionsGetIntOption(OPTIONS_TIMING)) { + /* Display the time taken to do XInclude processing */ + endTimer(i18n("XInclude processing %1.").arg((const char*)optionsGetStringOption(OPTIONS_DATA_FILE_NAME))); + } + } +#endif + if (optionsGetIntOption(OPTIONS_TIMING) || + optionsGetIntOption(OPTIONS_PROFILING)) + startTimer(); + if ((optionsGetStringOption(OPTIONS_OUTPUT_FILE_NAME) == NULL) || + optionsGetIntOption(OPTIONS_SHELL)) { + if (optionsGetIntOption(OPTIONS_REPEAT)) { + int j; + + for (j = 1; j < optionsGetIntOption(OPTIONS_REPEAT); j++) { + res = xsltApplyStylesheet(cur, doc, params); + xmlFreeDoc(res); + doc = xsldbgLoadXmlData(); + } + } + if (optionsGetIntOption(OPTIONS_PROFILING)) { + if (terminalIO != NULL) + res = xsltProfileStylesheet(cur, doc, params, terminalIO); + else if ((optionsGetStringOption(OPTIONS_OUTPUT_FILE_NAME) == + NULL) || (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) + || (filesTempFileName(1) == NULL)) + res = xsltProfileStylesheet(cur, doc, params, stderr); + else { + /* We now have to output to using notify using + * temp file #1 */ + FILE *tempFile = fopen(filesTempFileName(1), "w"); + + if (tempFile != NULL) { + res = + xsltProfileStylesheet(cur, doc, params, tempFile); + fclose(tempFile); + /* send the data to application */ + notifyXsldbgApp(XSLDBG_MSG_FILEOUT, + filesTempFileName(1)); + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to write temporary results to %1.\n").arg(filesTempFileName(1))); + res = xsltProfileStylesheet(cur, doc, params, stderr); + } + } + } else { + res = xsltApplyStylesheet(cur, doc, params); + } + if (optionsGetIntOption(OPTIONS_PROFILING)) { + if (optionsGetIntOption(OPTIONS_REPEAT)) + /* Display how long it took to apply stylesheet */ + endTimer(i18n("Applying stylesheet %n time", "Applying stylesheet %n times", optionsGetIntOption(OPTIONS_REPEAT))); + else + /* Display how long it took to apply stylesheet */ + endTimer(i18n("Applying stylesheet")); + } + if (res == NULL) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, "Error: Transformation did not complete writing to file %s\n", + optionsGetStringOption + (OPTIONS_OUTPUT_FILE_NAME)); +#endif + return; + } + if (!optionsGetIntOption(OPTIONS_OUT)) { + xmlFreeDoc(res); + return; + } +#ifdef LIBXML_DEBUG_ENABLED + if (optionsGetIntOption(OPTIONS_DEBUG)) { + if (xslDebugStatus != DEBUG_RUN_RESTART){ + if (terminalIO != NULL) + xmlDebugDumpDocument(terminalIO, res); + else if ((optionsGetStringOption(OPTIONS_OUTPUT_FILE_NAME) == + NULL) || (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) + || (filesTempFileName(1) == NULL)) + xmlDebugDumpDocument(stdout, res); + else { + FILE *tempFile = fopen(filesTempFileName(1), "w"); + + if (tempFile) { + bytesWritten = 0; // flag that we have writen at least zero bytes + xmlDebugDumpDocument(tempFile, res); + fclose(tempFile); + /* send the data to application */ + notifyXsldbgApp(XSLDBG_MSG_FILEOUT, + filesTempFileName(1)); + } else { + xsldbgGenericErrorFunc(i18n("Error: Unable to write temporary results to %1.\n").arg(filesTempFileName(1))); + xmlDebugDumpDocument(stdout, res); + } + + } + } + } else { +#endif + if (xslDebugStatus != DEBUG_RUN_RESTART){ + if (cur->methodURI == NULL) { + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); + if (xslDebugStatus != DEBUG_QUIT) { + if (terminalIO != NULL) + bytesWritten = xsltSaveResultToFile(terminalIO, res, cur); + else if (optionsGetStringOption + (OPTIONS_OUTPUT_FILE_NAME) == NULL) + bytesWritten = xsltSaveResultToFile(stdout, res, cur); + else{ + bytesWritten = xsltSaveResultToFilename((const char *) + optionsGetStringOption + (OPTIONS_OUTPUT_FILE_NAME), + res, cur, 0); + } + } + if (optionsGetIntOption(OPTIONS_TIMING)) + /* Indicate how long it took to save to file */ + endTimer(i18n("Saving result")); + } else { + if (xmlStrEqual(cur->method, (const xmlChar *) "xhtml")) { + xsldbgGenericErrorFunc(i18n("Warning: Generating non-standard output XHTML.\n")); + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); + if (terminalIO != NULL) + bytesWritten = xsltSaveResultToFile(terminalIO, res, cur); + else if (optionsGetStringOption + (OPTIONS_OUTPUT_FILE_NAME) == NULL) + bytesWritten = xsltSaveResultToFile(stdout, res, cur); + else + bytesWritten = xsltSaveResultToFilename((const char *) + optionsGetStringOption + (OPTIONS_OUTPUT_FILE_NAME), + res, cur, 0); + if (optionsGetIntOption(OPTIONS_TIMING)) + /* Indicate how long it took to save to file */ + endTimer(i18n("Saving result")); + } else { + xsldbgGenericErrorFunc(i18n("Warning: Unsupported, non-standard output method %1.\n").arg(xsldbgText(cur->method))); + } + } + } +#ifdef LIBXML_DEBUG_ENABLED + } +#endif + + xmlFreeDoc(res); + } else { + xsltTransformContextPtr userCtxt = xsltNewTransformContext(cur, doc); + if (userCtxt){ + bytesWritten = xsltRunStylesheetUser(cur, doc, params, + (char *)optionsGetStringOption(OPTIONS_OUTPUT_FILE_NAME), + NULL, NULL, NULL, userCtxt); + if (optionsGetIntOption(OPTIONS_TIMING)) + endTimer(i18n("Running stylesheet and saving result")); + xsltFreeTransformContext(userCtxt); + }else{ + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } + } + if ((xslDebugStatus != DEBUG_RUN_RESTART) && (bytesWritten == -1)) + xsldbgGenericErrorFunc(i18n("Error: Unable to save results of transformation to file %1.\n").arg(xsldbgText(optionsGetStringOption(OPTIONS_OUTPUT_FILE_NAME)))); +} + +int +xsldbgMain(int argc, char **argv) +{ + Q_UNUSED(argc); + Q_UNUSED(argv); + int i=0, result = 1, noFilesFound = 0; + xsltStylesheetPtr cur = NULL; + xmlChar *expandedName; /* contains file name with path expansion if any */ + + /* in some cases we always want to bring up a command prompt */ + int showPrompt; + + /* the xml document we're processing */ + xmlDocPtr doc; + + KCmdLineArgs *args = 0; + if (getThreadStatus() == XSLDBG_MSG_THREAD_NOTUSED) + args = KCmdLineArgs::parsedArgs(); + + errorFile = stderr; + + + if (args){ + QString langChoice = args->getOption("lang"); + if (KGlobal::locale() && !langChoice.isEmpty() && result) + KGlobal::locale()->setLanguage(langChoice); + } + +#ifdef __riscos + /* Remember our invocation command such that we may call ourselves */ + xsldbgCommand = argv[0]; +#endif + + xmlInitMemory(); + + + LIBXML_TEST_VERSION xmlLineNumbersDefault(1); + + if (!xsldbgInit()) { + xsldbgGenericErrorFunc(i18n("Fatal error: Aborting debugger due to an unrecoverable error.\n")); + xsldbgFree(); + xsltCleanupGlobals(); + xmlCleanupParser(); + xmlMemoryDump(); + return (1); + } + + + if (args){ + for (i = 0; i < args->count(); i++) { + if (!result) + break; + + if (args->arg(i)[0] != '-') { + expandedName = filesExpandName((const xmlChar*)args->arg(i)); + if (!expandedName) { + result = 0; + break; + } + switch (noFilesFound) { + case 0: + optionsSetStringOption(OPTIONS_SOURCE_FILE_NAME, + expandedName); + noFilesFound++; + break; + case 1: + optionsSetStringOption(OPTIONS_DATA_FILE_NAME, + expandedName); + noFilesFound++; + break; + + default: + xsldbgGenericErrorFunc(i18n("Error: Too many file names supplied via command line.\n")); + result = 0; + } + xmlFree(expandedName); + continue; + } + } + + + // Handle boolean options + for (int optionID = OPTIONS_FIRST_BOOL_OPTIONID; optionID < OPTIONS_LAST_BOOL_OPTIONID; optionID++){ + if (optionsGetOptionName(OptionTypeEnum(optionID))){ + if (args->isSet((char *)optionsGetOptionName(OptionTypeEnum(optionID)))) + optionsSetIntOption(OptionTypeEnum + (optionID), 1); + else + optionsSetIntOption(OptionTypeEnum(optionID), 0); + } + } + + // No extra arguments go straight to the shell? + if (args->count() == 0) + result = optionsSetIntOption(OPTIONS_SHELL, 1); + + // Disable net access? + if (!args->isSet("net")){ + char noNetCmd[] = {"nonet 1"}; + xslDbgShellSetOption((xmlChar*)noNetCmd); + } + } + + if (getThreadStatus() != XSLDBG_MSG_THREAD_NOTUSED){ + result = optionsSetIntOption(OPTIONS_SHELL, 1); + } + /* copy the volitile options over to xsldbg */ + optionsCopyVolitleOptions(); + + /* + * shell interraction + */ + if (!optionsGetIntOption(OPTIONS_SHELL)) { /* excecute stylesheet (ie no debugging) */ + xslDebugStatus = DEBUG_NONE; + } else { + xslDebugStatus = DEBUG_STOP; + xsltGenericError(xsltGenericErrorContext, "XSLDBG %s\n", VERSION); + } + + if (optionsGetIntOption(OPTIONS_VALID)) + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + else + xmlLoadExtDtdDefaultValue = 0; + + + if (args){ + if (args->isSet("verbose") && result) + xsltSetGenericDebugFunc(stderr, NULL); + + QCString outFile = args->getOption("output"); + if (!outFile.isEmpty() && result) + result = xslDbgShellOutput((const xmlChar *)QFile::encodeName(outFile).data()); + + QCString maxDepth = args->getOption("maxdepth"); + if (!maxDepth.isEmpty() && result){ + bool OK; + int value = maxDepth.toInt(&OK); + if (OK && (value> 0)) + xsltMaxDepth = value; + } + + if (args->isSet("repeat") && result){ + if (optionsGetIntOption(OPTIONS_REPEAT) == 0) + optionsSetIntOption(OPTIONS_REPEAT, 20); + else + optionsSetIntOption(OPTIONS_REPEAT, 100); + } + + QCStringList xslParams(args->getOptionList("param")); + QCStringList::iterator it; + QCString param, paramName, paramValue; + int separatorIdx; + bool paramOK; + for ( it = xslParams.begin(); it != xslParams.end(); ++it){ + param = (*it); + paramOK = true; + separatorIdx = param.find(':'); + if (separatorIdx > 0){ + paramName = param.left((uint)separatorIdx); + paramValue = param.mid((uint)separatorIdx + 1); + if (!paramName.isEmpty() && !paramValue.isEmpty()){ + if (arrayListCount(optionsGetParamItemList()) <= 31) { + arrayListAdd(optionsGetParamItemList(), optionsParamItemNew((const xmlChar*)paramName.data(), (const xmlChar*)paramValue.data())); + }else{ + xsldbgGenericErrorFunc(i18n("Warning: Too many libxslt parameters provided via the command line option --param.\n")); + } + }else{ + paramOK = false; + } + }else{ + paramOK = false; + } + if (!paramOK) + xsldbgGenericErrorFunc(i18n("Error: Argument \"%1\" to --param is not in the format <name>:<value>.\n").arg(param.data())); + } + + QCString cdPath = args->getOption("cd"); + if (!cdPath.isEmpty() && result) + result = changeDir((const xmlChar *)QFile::encodeName(cdPath).data()); + + } + + if (!result) { + KCmdLineArgs::usage(); + xsldbgFree(); + return (1); + } + + + /* + * * Replace entities with their content. + */ + xmlSubstituteEntitiesDefault(1); + + /* + * * Register the EXSLT extensions and the test module + */ + exsltRegisterAll(); + xsltRegisterTestModule(); + + + + debugGotControl(0); + while (xslDebugStatus != DEBUG_QUIT) { + xsldbgReachedFirstTemplate = false; + /* don't force xsldbg to show command prompt */ + showPrompt = 0; + cur = NULL; + doc = NULL; + arrayListEmpty(filesEntityList()); + xsltSetXIncludeDefault(optionsGetIntOption(OPTIONS_XINCLUDE)); + + /* copy the volitile options over to xsldbg */ + optionsCopyVolitleOptions(); + + /* choose where error messages/xsldbg output get sent to */ + if (optionsGetIntOption(OPTIONS_STDOUT)) + errorFile = stdout; + else + errorFile = stderr; + + filesLoadCatalogs(); + + if (optionsGetIntOption(OPTIONS_SHELL)) { + debugGotControl(0); + xsldbgGenericErrorFunc(i18n("\nStarting stylesheet\n\n")); + if (optionsGetIntOption(OPTIONS_TRACE) == TRACE_OFF) + xslDebugStatus = DEBUG_STOP; /* stop as soon as possible */ + } + + if ((optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME) == NULL) || + (optionsGetStringOption(OPTIONS_DATA_FILE_NAME) == NULL)) { + /* at least on file name has not been set */ + /*goto a xsldbg command prompt */ + showPrompt = 1; + if (optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME) == NULL) + xsldbgGenericErrorFunc(i18n("Error: No XSLT source file supplied.\n")); + + if (optionsGetStringOption(OPTIONS_DATA_FILE_NAME) == NULL) { + xsldbgGenericErrorFunc(i18n("Error: No XML data file supplied.\n")); + } + + } else { + filesLoadXmlFile(NULL, FILES_SOURCEFILE_TYPE); + cur = filesGetStylesheet(); + if ((cur == NULL) || (cur->errors != 0)) { + /*goto a xsldbg command prompt */ + showPrompt = 1; + if (xslDebugStatus == DEBUG_NONE) { + xslDebugStatus = DEBUG_QUIT; /* panic !! */ + result = 0; + } + } + } + + if (showPrompt == 0) { + filesLoadXmlFile(NULL, FILES_XMLFILE_TYPE); + doc = filesGetMainDoc(); + if (doc == NULL) { + if (xslDebugStatus == DEBUG_NONE) { + xslDebugStatus = DEBUG_QUIT; /* panic !! */ + result = 0; + } else { + /*goto a xsldbg command prompt */ + showPrompt = 1; + } + } else { + if (xslDebugStatus != DEBUG_QUIT) { + xsltProcess(doc, cur); + result = 1; + } + } + + if (optionsGetIntOption(OPTIONS_SHELL) && (showPrompt == 0)) { + if ((xslDebugStatus != DEBUG_QUIT) + && !debugGotControl(-1)) { + xsldbgGenericErrorFunc(i18n("\nDebugger never received control.\n")); + /*goto a xsldbg command prompt */ + showPrompt = 1; + xslDebugStatus = DEBUG_STOP; + } else { + xsldbgGenericErrorFunc(i18n("\nFinished stylesheet\n\032\032\n")); + { + /* handle trace execution */ + int trace = optionsGetIntOption(OPTIONS_TRACE); + + switch (trace) { + case TRACE_OFF: + /* no trace of execution */ + break; + + case TRACE_ON: + /* tell xsldbg to stop tracing next time we get here */ + optionsSetIntOption(OPTIONS_TRACE, + TRACE_RUNNING); + xslDebugStatus = DEBUG_TRACE; + break; + + case TRACE_RUNNING: + /* turn off tracing */ + xslDebugStatus = DEBUG_CONT; + optionsSetIntOption(OPTIONS_TRACE, + TRACE_OFF); + break; + } + } + if (!optionsGetIntOption(OPTIONS_AUTORESTART) && (xslDebugStatus != DEBUG_RUN_RESTART)){ + /* pass control to user they won't be able to do much + other than add breakpoints, quit, run, continue */ + debugXSLBreak((xmlNodePtr) cur->doc, (xmlNodePtr) doc, + NULL, NULL); + } + } + } else { + /* request to execute stylesheet only so we're done */ + xslDebugStatus = DEBUG_QUIT; + } + } else { + /* Some sort of problem loading source file has occured. Quit? */ + if (xslDebugStatus == DEBUG_NONE) { + xslDebugStatus = DEBUG_QUIT; /* Panic!! */ + result = 0; + } else { + /*goto a xsldbg command prompt */ + showPrompt = 1; + } + } + + if (showPrompt && optionsGetIntOption(OPTIONS_SHELL)) { + xmlDocPtr tempDoc = xmlNewDoc((xmlChar *) "1.0"); + xmlNodePtr tempNode = + xmlNewNode(NULL, (xmlChar *) "xsldbg_default_node"); + if (!tempDoc || !tempNode) { + xsldbgFree(); + return (1); + } + xmlAddChild((xmlNodePtr) tempDoc, tempNode); + + xsldbgGenericErrorFunc(i18n("Going to the command shell; not all xsldbg commands will work as not all needed have been loaded.\n")); + xslDebugStatus = DEBUG_STOP; + if ((cur == NULL) && (doc == NULL)) { + /*no doc's loaded */ + debugXSLBreak(tempNode, tempNode, NULL, NULL); + } else if ((cur != NULL) && (doc == NULL)) { + /* stylesheet is loaded */ + debugXSLBreak((xmlNodePtr) cur->doc, tempNode, NULL, NULL); + } else if ((cur == NULL) && (doc != NULL)) { + /* xml doc is loaded */ + debugXSLBreak(tempNode, (xmlNodePtr) doc, NULL, NULL); + } else { + /* unexpected problem, both docs are loaded */ + debugXSLBreak((xmlNodePtr) cur->doc, (xmlNodePtr) doc, + NULL, NULL); + } + xmlFreeDoc(tempDoc); + } else if (showPrompt && !optionsGetIntOption(OPTIONS_SHELL)) { + xslDebugStatus = DEBUG_QUIT; + result = 0; /* panic */ + } + + if (optionsGetIntOption(OPTIONS_SHELL)) { + /* force a refesh of both stlesheet and xml data */ + filesFreeXmlFile(FILES_SOURCEFILE_TYPE); + filesFreeXmlFile(FILES_XMLFILE_TYPE); + } + } + + if (!result) { + xsldbgGenericErrorFunc(i18n("Fatal error: Aborting debugger due to an unrecoverable error.\n")); + } + xsldbgFree(); + xsltCleanupGlobals(); + xmlCleanupParser(); + xmlMemoryDump(); + return !result; +} + +/** + * xsldbgLoadStylesheet: + * + * Load the stylesheet and return it + * + * Returns The stylesheet after reloading it if successful + * NULL otherwise + */ +xsltStylesheetPtr +xsldbgLoadStylesheet() +{ + xsltStylesheetPtr cur = NULL; + xmlDocPtr style; + + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); + style = xmlParseFile((const char *) optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME)); + if (optionsGetIntOption(OPTIONS_TIMING)) + endTimer(i18n("Parsing stylesheet %1").arg((const char*)optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME))); + if (style == NULL) { + xsldbgGenericErrorFunc(i18n("Error: Cannot parse file %1.\n").arg(xsldbgUrl(optionsGetStringOption(OPTIONS_SOURCE_FILE_NAME)))); + cur = NULL; + if (!optionsGetIntOption(OPTIONS_SHELL)) { + xsldbgGenericErrorFunc(i18n("Fatal error: Aborting debugger due to an unrecoverable error.\n")); + xslDebugStatus = DEBUG_QUIT; + } else { + xsltGenericError(xsltGenericErrorContext, "\n"); + xslDebugStatus = DEBUG_STOP; + } + } else { + cur = xsltLoadStylesheetPI(style); + if (cur != NULL) { + /* it is an embedded stylesheet */ + xsltProcess(style, cur); + xsltFreeStylesheet(cur); + } else { + cur = xsltParseStylesheetDoc(style); + if (cur != NULL) { + if (cur->indent == 1) + xmlIndentTreeOutput = 1; + else + xmlIndentTreeOutput = 0; + } else { + xmlFreeDoc(style); + } + } + } + return cur; +} + + + +/** + * xsldbgLoadXmlData: + * + * Load the xml data file and return it + * + * Returns The data file after reloading it if successful + * NULL otherwise + */ +xmlDocPtr +xsldbgLoadXmlData(void) +{ + xmlDocPtr doc = NULL; + xmlSAXHandler mySAXHandler; + doc = NULL; + + xmlSAXVersion(&mySAXHandler,2); + oldGetEntity = mySAXHandler.getEntity; + mySAXHandler.getEntity = xsldbgGetEntity; + + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); +#ifdef LIBXML_HTML_ENABLED + if (optionsGetIntOption(OPTIONS_HTML)) + doc = htmlParseFile((char *) + optionsGetStringOption(OPTIONS_DATA_FILE_NAME), + NULL); + else +#endif +#ifdef LIBXML_DOCB_ENABLED + if (optionsGetIntOption(OPTIONS_DOCBOOK)) + doc = docbParseFile((char *) + optionsGetStringOption(OPTIONS_DATA_FILE_NAME), + NULL); + else +#endif + +#if LIBXML_VERSION >= 20600 + doc = xmlSAXParseFile(&mySAXHandler, + (char *) optionsGetStringOption(OPTIONS_DATA_FILE_NAME), 0); +#else + doc = xmlParseFile((char *) optionsGetStringOption(OPTIONS_DATA_FILE_NAME)); +#endif + if (doc == NULL) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse file %1.\n").arg(xsldbgUrl(optionsGetStringOption(OPTIONS_DATA_FILE_NAME)))); + if (!optionsGetIntOption(OPTIONS_SHELL)) { + xsldbgGenericErrorFunc(i18n("Fatal error: Aborting debugger due to an unrecoverable error.\n")); + xslDebugStatus = DEBUG_QUIT; + } else { + xsltGenericError(xsltGenericErrorContext, "\n"); + xslDebugStatus = DEBUG_STOP; + } + } else if (optionsGetIntOption(OPTIONS_TIMING)) + endTimer(QString("Parsing document %1").arg(xsldbgUrl(optionsGetStringOption(OPTIONS_DATA_FILE_NAME))).utf8().data()); + + return doc; +} + + +/** + * xsldbgLoadXmlTemporary: + * @path: The name of temporary file to load + * + * Load the temporary data file and return it + * + * Returns The temporary file after reloading it if successful, + * NULL otherwise + */ +xmlDocPtr +xsldbgLoadXmlTemporary(const xmlChar * path) +{ + xmlDocPtr doc = NULL; + doc = NULL; + + if (optionsGetIntOption(OPTIONS_TIMING)) + startTimer(); +#ifdef LIBXML_HTML_ENABLED + if (optionsGetIntOption(OPTIONS_HTML)) + doc = htmlParseFile((char *) path, NULL); + else +#endif +#ifdef LIBXML_DOCB_ENABLED + if (optionsGetIntOption(OPTIONS_DOCBOOK)) + doc = docbParseFile((char *) path, NULL); + else +#endif + doc = xmlSAXParseFile(&mySAXhdlr, (char *) path, 0); + if (doc == NULL) { + xsldbgGenericErrorFunc(i18n("Error: Unable to parse file %1.\n").arg(xsldbgUrl(path))); + } + + if (optionsGetIntOption(OPTIONS_TIMING) + && (xslDebugStatus != DEBUG_QUIT)) { + endTimer(QString("Parsing document %1").arg(xsldbgUrl(path))); + } + return doc; +} + +/** + * printTemplates: + * @style : valid as parsed my xsldbg + * @doc : " " " " " + * + * print out list of template names + */ +void +printTemplates(xsltStylesheetPtr style, xmlDocPtr doc) +{ + xsltTransformContextPtr ctxt = xsltNewTransformContext(style, doc); + + if (ctxt) { + /* don't be verbose when printing out template names */ + xslDbgShellPrintTemplateNames(ctxt, NULL, NULL, 0, 0); + } else { + xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n")); + } +} + +#ifdef WIN32 + +/* For the windows world we capture the control event */ +BOOL WINAPI +handler_routine(DWORD dwCtrlType) +{ + + switch (dwCtrlType) { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_CLOSE_EVENT: + catchSigInt(SIGINT); + break; + + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + xsldbgFree(); + exit(1); + break; + + default: + printf("Error: Unknown control event\n"); + break; + } + + return (true); +} + +#endif + +#if LIBXML_VERSION >= 2006000 +/* libxml/ handlers */ +void xsldbgStructErrorHandler(void * userData, xmlErrorPtr error) +{ + if (error && error->message && (error->level >= 0) && (error->level <= 4)){ + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN){ + static const char *msgPrefix[4 + 1] = {"", "warning :", "error:", "fatal:"}; + if (error->file) + xsltGenericError(xsltGenericErrorContext, "%s%s in file \"%s\" line %d", msgPrefix[error->level], error->message, error->file, error->line); + else + xsltGenericError(xsltGenericErrorContext, "%s%s", msgPrefix[error->level], error->message); + + }else{ + xsltGenericError(xsltGenericErrorContext,"Struct error handler"); + notifyXsldbgApp(XSLDBG_MSG_ERROR_MESSAGE, error); + } + } +} + +void xsldbgSAXErrorHandler(void * ctx, const char * msg, ...) +{ + if (ctx) + xsldbgStructErrorHandler(0, ((xmlParserCtxtPtr)ctx)->lastError); +} + +void xsldbgSAXWarningHandler(void * ctx, const char * msg, ...) +{ + if (ctx) + xsldbgStructErrorHandler(0, ((xmlParserCtxtPtr)ctx)->lastError); +} + +#endif + +/** + * catchSigInt: + * @value : not used + * + * Recover from a signal(SIGINT), exit if needed + */ +void +catchSigInt(int value) +{ + Q_UNUSED(value); + if ((xslDebugStatus == DEBUG_NONE) || (xsldbgStop == 1) || (xslDebugStatus == DEBUG_STOP)) { + xsldbgFree(); + exit(1); + } +#ifdef __riscos + /* re-catch SIGINT - RISC OS resets the handler when the interupt occurs */ + signal(SIGINT, catchSigInt); +#endif + + if (xslDebugStatus != DEBUG_STOP) { + /* stop running/walking imediately !! */ + xsldbgStop = 1; + } +} + + +/** + * catchSigTerm: + * @value : not used + * + * Clean up and exit + */ +void +catchSigTerm(int value) +{ + Q_UNUSED(value); + xsldbgFree(); + exit(1); +} + + + +typedef void (*sighandler_t) (int); +static sighandler_t oldHandler; + +static int initialized = 0; + +/** + * xsldbgInit: + * + * Returns 1 if able to allocate memory needed by xsldbg + * 0 otherwise + */ +int +xsldbgInit() +{ + int result = 0; + int xmlVer = 0; + + if (!initialized) { + sscanf(xmlParserVersion, "%d", &xmlVer); + if (!debugInit()) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Fatal error: Init of debug module failed\n"); +#endif + return result; + } + if (!filesInit()) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Fatal error: Init of files module failed\n"); +#endif + return result; + } + + if (!optionsInit()) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Fatal error: Init of options module failed\n"); +#endif + return result; + } + + if (!searchInit()) { +#ifdef WITH_XSLDBG_DEBUG_PROCESS + xsltGenericError(xsltGenericErrorContext, + "Fatal error: Init of search module failed\n"); +#endif + return result; + } + + + + /* set up the parser */ + xmlInitParser(); +#if 0 +#if LIBXML_VERSION >= 20600 + xmlSetGenericErrorFunc(NULL, NULL); + xmlSetStructuredErrorFunc(NULL , (xmlStructuredErrorFunc)xsldbgStructErrorHandler); +#else + xmlSetGenericErrorFunc(0, xsldbgGenericErrorFunc); + xsltSetGenericErrorFunc(0, xsldbgGenericErrorFunc); +#endif +#else + xmlSetGenericErrorFunc(0, xsldbgGenericErrorFunc); + xsltSetGenericErrorFunc(0, xsldbgGenericErrorFunc); +#endif + + /* + * disable CDATA from being built in the document tree + */ + xmlDefaultSAXHandlerInit(); + xmlDefaultSAXHandler.cdataBlock = NULL; + + if (getThreadStatus() != XSLDBG_MSG_THREAD_NOTUSED) { + initialized = 1; + return 1; /* this is all we need to do when running as a thread */ + } +#ifndef WIN32 + /* catch SIGINT */ + oldHandler = signal(SIGINT, catchSigInt); +#else + if (SetConsoleCtrlHandler(handler_routine, true) != true) + return result; +#endif + +#ifndef WIN32 + /* catch SIGTIN tty input available fro child */ + signal(SIGTERM, catchSigTerm); +#endif + initialized = 1; + } + return 1; +} + +/** + * xsldbgFree: + * + * Free memory used by xsldbg + */ +void +xsldbgFree() +{ + debugFree(); + filesFree(); + optionsFree(); + searchFree(); +#ifndef WIN32 + if (oldHandler != SIG_ERR) + signal(SIGINT, oldHandler); +#else + SetConsoleCtrlHandler(handler_routine, false); +#endif + initialized = 0; + +#ifdef HAVE_READLINE + /* rl_free_line_state (); + rl_cleanup_after_signal(); */ +# ifdef HAVE_HISTORY + clear_history(); +# endif +#endif + +} + + +char msgBuffer[4000]; + +/** + * xsldbgGenericErrorFunc: + * @ctx: Is Valid + * @msg: Is valid + * @...: other parameters to use + * + * Handles print output from xsldbg and passes it to the application if + * running as a thread otherwise send to stderr + */ +void +xsldbgGenericErrorFunc(void *ctx, const char *msg, ...) +{ + va_list args; + Q_UNUSED(ctx); + + va_start(args, msg); + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) { + vsnprintf(msgBuffer, sizeof(msgBuffer), msg, args); + + notifyTextXsldbgApp(XSLDBG_MSG_TEXTOUT, msgBuffer); + } else { + xmlChar *encodeResult = NULL; + + vsnprintf(msgBuffer, sizeof(msgBuffer), msg, args); + encodeResult = filesEncode((xmlChar *) msgBuffer); + if (encodeResult) { + fprintf(errorFile, "%s", encodeResult); + xmlFree(encodeResult); + } else + fprintf(errorFile, "%s", msgBuffer); + } + va_end(args); +} + +void xsldbgGenericErrorFunc(QString const &text) +{ + xsldbgGenericErrorFunc(0, "%s", text.utf8().data()); +} + + +QString xsldbgUrl(const char *utf8fUrl) +{ + QString tempUrl(utf8fUrl); + QString fixedURI; + KURL url(tempUrl); + + // May be provided with a URL that only has been encoded and has no protocol prefix ie a local file + if ( !tempUrl.startsWith("file:/") && !tempUrl.startsWith("http:/") && !tempUrl.startsWith("ftp:/")) + fixedURI = KURL::decode_string(tempUrl); + else + fixedURI = url.prettyURL(); + + return fixedURI; +} + +QString xsldbgUrl(const xmlChar *utf8Url) +{ + return xsldbgUrl((const char*)(utf8Url)); +} + +QString xsldbgText(const char *utf8Text) +{ + return QString::fromUtf8(utf8Text); + +} + +QString xsldbgText(const xmlChar *utf8Text) +{ + return QString::fromUtf8((const char *)utf8Text); +} + diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.h new file mode 100644 index 00000000..6972fc12 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbg.h @@ -0,0 +1,188 @@ + +/*************************************************************************** + xsldbg.h - describe the application level functions + ------------------- + begin : Sun Sep 16 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef XSLDEBUGGER_H +#define XSLDEBUGGER_H + +#ifdef USE_KDE_DOCS + +/** + * Provide provide application level services and useful bits and pieces + * + * @short application functions and useful bits and pieces + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +#endif + + +/* We want skip most of these includes when building documentation */ +#ifndef BUILD_DOCS +#ifndef __riscos +# ifndef WIN32 +# include "config.h" + /* we don't need to use dll declares for *nix based machines */ +# define XSLDBG_SO_API +# else + /* dll declares get defined in xsldbgwin32config.h *nix based machines */ +# include "xsldbgwin32config.h" +# endif +#else + /* we don't need to use dll declares for risc_os*/ +# define XSLDBG_SO_API +# include "config_riscos.h" +# include "libxml/riscos.h" +#endif + +#include <libxslt/xsltconfig.h> + + +#if !defined (FORCE_DEBUGGER) && (LIBXSLT_VERSION > 10019) +# ifndef WITH_XSLT_DEBUGGER +# ifndef WITH_DEBUGGER +# error "WITH_DEBUGGER MACRO not defined in libxslt maybe you've disable debugger in libxslt." \ + "if your are sure then disable this check by defining WITH_FORCE_DEBUGGER. eg.\n" \ + "\nmake CFLAGS=\"$CFLAGS -D FORCE_DEBUGGER\"" +# endif +# endif +#endif + +#ifdef WITH_XSLDBG_DEBUG + +#ifndef WITH_XSLDBG_DEBUG_PROCESS +#define WITH_XSLDBG_DEBUG_PROCESS +#endif + +#ifndef WITH_XSLDBG_DEBUG_BREAKPOINTS +#define WITH_XSLDBG_DEBUG_BREAKPOINTS +#endif + +#endif /* end of WITH_XSL_DEBUG */ + + +#include <libxslt/xslt.h> +#include <libexslt/exslt.h> +#include <libxslt/xsltutils.h> + +#include <qstring.h> +#include <klocale.h> + +#include "breakpoint.h" + + +#endif /* BUILD_DOCS */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef USE_GNOME_DOCS + +/** + * xsldbgLoadStylesheet: + * + * Load the stylesheet and return it + * + * Returns the stylesheet after reloading it if successful + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Load the stylesheet and return it + * + * @returns The stylesheet after reloading it if successful + * NULL otherwise + */ +#endif +#endif + xsltStylesheetPtr xsldbgLoadStylesheet(void); + + +#ifdef USE_GNOME_DOCS + +/** + * xsldbgLoadXmlData: + * + * Load the xml data file and return it + * + * Returns the data file after reloading it if successful + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Load the xml data file and return it + * + * @returns The stylesheet after reloading it if successful + * NULL otherwise + */ +#endif +#endif + xmlDocPtr xsldbgLoadXmlData(void); + + +#ifdef USE_GNOME_DOCS + +/** + * xsldbgLoadXmlTemporary: + * @path: The name of temporary file to load + * + * Load the temporary data file and return it + * + * Returns The temporary file after reloading it if successful, + * NULL otherwise + */ +#else +#ifdef USE_KDE_DOCS + +/** + * Load the temporary data file and return it + * + * @returns The temporary file after reloading it if successful, + * NULL otherwise + * @param path The name of temporary file to loa + */ +#endif +#endif + xmlDocPtr xsldbgLoadXmlTemporary(const xmlChar * path); + + +void xsldbgGenericErrorFunc(void *ctx, const char *msg, ...) +#ifdef __GNUC__ + __attribute__ ( ( format ( printf, 2, 3 ) ) ) +#endif +; +int xsldbgMain(int argc, char **argv); + +#ifdef __cplusplus +} +#endif + +void xsldbgGenericErrorFunc(QString const &text); +QString xsldbgUrl(const char *utf8Url); +QString xsldbgUrl(const xmlChar *utf8Url); +QString xsldbgText(const char *utf8Text); +QString xsldbgText(const xmlChar *utf8Text); + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgconfig.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgconfig.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgconfig.h diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgevent.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgevent.h new file mode 100644 index 00000000..85b1827f --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgevent.h @@ -0,0 +1,302 @@ + +/*************************************************************************** + xsldbgevent.h - event to notify app of + data from xsldbg + ------------------- + begin : Fri Feb 1 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef XSLDBGEVENT_H +#define XSLDBGEVENT_H + +#if defined WIN32 +#include <libxsldbg/xsldbgwin32config.h> +#endif + +#include <qevent.h> +#include <qptrlist.h> + +#include "xsldbgmsg.h" + +/* how many columns do we have */ +#define XSLDBGEVENT_COLUMNS 4 + +class XsldbgDebuggerBase; +class XsldbgEventData; + +class XsldbgEventDataList : public QGList +{ +public: + XsldbgEventDataList(void) {} + XsldbgEventDataList( const XsldbgEventDataList &l ) : QGList(l) {} + ~XsldbgEventDataList(void) { clear(); } + XsldbgEventDataList &operator=(const XsldbgEventDataList &l) + { return (XsldbgEventDataList&)QGList::operator=(l); } + bool operator==( const XsldbgEventDataList &list ) const + { return QGList::operator==( list ); } + uint count(void) const { return QGList::count(); } + bool isEmpty(void) const { return QGList::count() == 0; } + bool insert( uint i, const XsldbgEventData *d){ return QGList::insertAt(i,(QPtrCollection::Item)d); } + void inSort( const XsldbgEventData *d ) { QGList::inSort((QPtrCollection::Item)d); } + void prepend( const XsldbgEventData *d ) { QGList::insertAt(0,(QPtrCollection::Item)d); } + void append( const XsldbgEventData *d ) { QGList::append((QPtrCollection::Item)d); } + bool remove( uint i ) { return QGList::removeAt(i); } + bool remove(void) { return QGList::remove((QPtrCollection::Item)0); } + bool remove( const XsldbgEventData *d ) { return QGList::remove((QPtrCollection::Item)d); } + bool removeRef( const XsldbgEventData *d ) { return QGList::removeRef((QPtrCollection::Item)d); } + void removeNode( QLNode *n ) { QGList::removeNode(n); } + bool removeFirst(void) { return QGList::removeFirst(); } + bool removeLast(void) { return QGList::removeLast(); } + XsldbgEventData *take( uint i ) { return (XsldbgEventData *)QGList::takeAt(i); } + XsldbgEventData *take(void) { return (XsldbgEventData *)QGList::take(); } + XsldbgEventData *takeNode( QLNode *n ) { return (XsldbgEventData *)QGList::takeNode(n); } + void clear(void) { QGList::clear(); } + void sort(void) { QGList::sort(); } + int find( const XsldbgEventData *d ) { return QGList::find((QPtrCollection::Item)d); } + int findNext( const XsldbgEventData *d ) { return QGList::find((QPtrCollection::Item)d,FALSE); } + int findRef( const XsldbgEventData *d ) { return QGList::findRef((QPtrCollection::Item)d); } + int findNextRef( const XsldbgEventData *d ){ return QGList::findRef((QPtrCollection::Item)d,FALSE);} + uint contains( const XsldbgEventData *d ) const { return QGList::contains((QPtrCollection::Item)d); } + uint containsRef( const XsldbgEventData *d ) const + { return QGList::containsRef((QPtrCollection::Item)d); } + XsldbgEventData *at( uint i ) { return (XsldbgEventData *)QGList::at(i); } + int at(void) const { return QGList::at(); } + XsldbgEventData *current(void) const { return (XsldbgEventData *)QGList::get(); } + QLNode *currentNode(void) const { return QGList::currentNode(); } + XsldbgEventData *getFirst(void) const { return (XsldbgEventData *)QGList::cfirst(); } + XsldbgEventData *getLast(void) const { return (XsldbgEventData *)QGList::clast(); } + XsldbgEventData *first(void) { return (XsldbgEventData *)QGList::first(); } + XsldbgEventData *last(void) { return (XsldbgEventData *)QGList::last(); } + XsldbgEventData *next(void) { return (XsldbgEventData *)QGList::next(); } + XsldbgEventData *prev(void) { return (XsldbgEventData *)QGList::prev(); } + void toVector( QGVector *vec )const{ QGList::toVector(vec); } +private: + void deleteItem( QPtrCollection::Item d ); +}; + + + + + + +/** + * This class is used to convert a message from xsldbg into a simple data type + * + * @short convertor of xsldbg message to a data class + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +class XsldbgEventData { + + public: + XsldbgEventData(void); + ~XsldbgEventData(void); + + + /** + * Set the text for the column specified + * + * @param column 0 =< @p column < XSLDBGEVENT_COLUMNS + * @param text The text value to store in column indicated + */ + void setText(int column, QString text); + + + /** + * Get the text from the column specified + * + * @returns QString::null if invalid column number + * + * @param column 0 =< @p column < XSLDBGEVENT_COLUMNS + * + */ + QString getText(int column); + + + /** + * Set the integer value for the column specified + * + * @param column 0 =< @p column < XSLDBGEVENT_COLUMNS + * @param value The value to store in column indicated + */ + void setInt(int column, int value); + + + /** + * Get the integer value from the column specified + * + * @returns -1 if invalid column number + * + * @param column 0 =< @p column < XSLDBGEVENT_COLUMNS + * + */ + int getInt(int column); + + private: + /** Below are the messages that this class will support + Values are mapped left to right ie the first QString value maps + to textValues[0], the second mapps to textValues[1] + the third maps to textValues[2] etc.. */ + QString textValues[XSLDBGEVENT_COLUMNS]; + + /** + Both int and bool values are mapped to intValues in the same manner as + stated above */ + int intValues[XSLDBGEVENT_COLUMNS]; + + /** - - - - - - The message/signal types supported - - - - - - */ + // /** line number and/or file name changed */ + // void lineNoChanged(QString /* fileName */, int /* lineNumber */, bool /* breakpoint */); + // These data items are mapped to attributes of this class with the same name + + + // /** Show a message in debugger window */ + // void showMessage(QString /* msg*/); + // These data item is mapped to the text attribute + + + // /** Add breakpoint to view, First parameter is QString::null + // to indicate start of breakpoint list notfication */ + // void breakpointItem(QString /* fileName*/, int /* lineNumber */, QString /*templateName*/, + // bool /* enabled */, int /* id */); + // These data items are mapped to attributes of this class with the same name + + + // /** Add global variable to view, First parameter is QString::null + // to indicate start of global variable list notfication */ + // void globalVariableItem(QString /* name */, QString /* fileName */, int /* lineNumber */); + // These data items are mapped to attributes of this class with the same name + + + // /** Add local variable to view, First parameter is QString::null + // to indicate start of local variable list notfication */ + // void localVariableItem(QString /*name */, QString /* templateContext*/, + // QString /* fileName */, int /*lineNumber */); + // These data items are mapped to attributes of this class with the same name + + + // /** Add template to view, First parameter is QString::null + // to indicate start of template list notfication */ + // void templateItem(QString /* name*/, QString /*mode*/, QString /* fileName */, int /* lineNumber */); + + // /** Add source to view, First parameter is QString::null + // to indicate start of source list notfication */ + // void sourceItem(QString /* fileName */, QString /* parentFileName */, int /*lineNumber */); + + // /** Add parameter to view, First parameter is QString::null + // to indicate start of parameter list notfication */ + // void parameterItem(QString /* name*/, QString /* value */); + + // /** Add callStack to view, First parameter is QString::null + // to indicate start of callstack list notfication */ + // void callStackItem(QString /* tempalteName*/, QString /* fileName */, int /* lineNumber */); + + // /** Add entity to view, First parameter is QString::null + // to indicate start of entity list notfication */ + // void entityItem(QString /*SystemID*/, QString /*PublicID*/); + + // /* Show the URI for SystemID or PublicID requested */ + // void resolveItem(QString /*URI*/); + + // /* Display a integer option value First parameter is QString::null + // to indicate start of option list notification */ + // void intOptionItem(QString /* name*/, int /* value */); + + // /* Display a string option value. First parameter is QString::null + // to indicate start of option list notification */ + // void stringOptionItem(QString /* name*/, QString /* value */); + +}; + + +/** + * This class is posted to the applications event queue. When the application + * has time to process the event this class then aids in emitting + * the relavant signals for the event. + * + * @short Emit signals to QT application via debugger base class + * + * @author Keith Isdale <k_isdale@tpg.com.au> + */ +class XsldbgEvent : public QEvent { + + public: + XsldbgEvent(XsldbgMessageEnum type, const void *data); + ~XsldbgEvent(void); + + /** Main control for emitting messages, use this from the application + inside its event processing function */ + void emitMessage(XsldbgDebuggerBase *debugger); + + /** Emit a single message. It uses handleXXX to do the actual emitting + of signal from debugger */ + void emitMessage(XsldbgEventData *eventData); + + private: + /** Create the XsldbgEventData for this message. Is used by our constructor + it uses handleXXX function to fill in the approriate values in + the XsldbgEventData provided */ + XsldbgEventData * createEventData(XsldbgMessageEnum type, const void *msgData); + + /** The following functions are directly related to the eventual signals that + will be emitted ie the signal + lineNoChanged(QString, int bool) + is mapped to + handleLineNoChanged(XsldbgEventData *, void *) + */ + void handleLineNoChanged(XsldbgEventData *eventData, const void *msgData); + void handleShowMessage(XsldbgEventData *eventData, const void *msgData); + void handleBreakpointItem(XsldbgEventData *eventData, const void *msgData); + void handleGlobalVariableItem(XsldbgEventData *eventData, const void *msgData); + void handleLocalVariableItem(XsldbgEventData *eventData, const void *msgData); + void handleTemplateItem(XsldbgEventData *eventData, const void *msgData); + void handleSourceItem(XsldbgEventData *eventData, const void *msgData); + void handleIncludedSourceItem(XsldbgEventData *eventData, const void *msgData); + void handleParameterItem(XsldbgEventData *eventData, const void *msgData); + void handleCallStackItem(XsldbgEventData *eventData, const void *msgData); + void handleEntityItem(XsldbgEventData *eventData, const void *msgData); + void handleResolveItem(XsldbgEventData *eventData, const void *msgData); + void handleIntOptionItem(XsldbgEventData *eventData, const void *msgData); + void handleStringOptionItem(XsldbgEventData *eventData, const void *msgData); + + + private: + + /** What type is the items in list */ + XsldbgMessageEnum itemType; + + /** A flag that gets set once the list has been filled with approriate + XsldbgEventData */ + bool beenCreated; + + /** This is a volitile value that is only valid for the duration + of the constuctor. It will be set to 0L immediately after */ + const void *data; + + /** This is a volitile value only valid for duration of emitMessage + function. It will be set to 0L imedediately after */ + XsldbgDebuggerBase *debugger; + + /** This is the data associated with this event + each data item in the list will be of the type required + by the "type" this event + */ + class XsldbgEventDataList list; + }; + + + + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgio.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgio.h new file mode 100644 index 00000000..0e164f0e --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgio.h @@ -0,0 +1,41 @@ + +/*************************************************************************** + xsldbgio.h - declare user input functions + ------------------- + begin : Sun Dec 23 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef XSLDBGIO_H +#define XSLDBGIO_H + +#ifndef BUILD_DOCS +#include <libxml/tree.h> /* needed for definition of xmlChar */ +#endif + +/** + * xslShellReadline: + * @prompt: the prompt value + * + * Read a string + * + * Returns a copy of the text inputed or NULL if EOF in stdin found. + * The caller is expected to free the returned string. + */ +xmlChar *xslDbgShellReadline(xmlChar * prompt); + + +#define DEBUG_BUFFER_SIZE 500 /*used by xslDbgShell */ + + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.cpp b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.cpp new file mode 100644 index 00000000..9f95d353 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.cpp @@ -0,0 +1,119 @@ + +/*************************************************************************** + xsldbg.cpp - send message to console or KXSLDbg + ------------------- + begin : Mon April 26 2004 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "xsldbg.h" + +#include <libxslt/xsltutils.h> + +#ifdef HAVE_READLINE +#include <readline/readline.h> +#ifdef HAVE_HISTORY +#include <readline/history.h> +#endif +#endif + +#include "xsldbgmsg.h" +#include "xsldbgio.h" +#include "options.h" + +static int (*notifyXsldbgAppFuncPtr) (XsldbgMessageEnum type, const void *data) = 0; + +static int (*notifyStateXsldbgAppFuncPtr)(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, + const char *text) = 0; + +static int (*notifyTextXsldbgAppFuncPtr)(XsldbgMessageEnum type, const char *text) = 0; +static xmlChar * (*xslDbgShellReadlineFuncPtr)(xmlChar * prompt) = 0; + + +#ifdef __cplusplus +extern "C" { +#endif + +void xsldbgSetAppFunc(int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type, const void *data)) +{ + notifyXsldbgAppFuncPtr = notifyXsldbgAppFunc; +} + +void xsldbgSetAppStateFunc(int (*notifyStateXsldbgAppFunc)(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, + const char *text)) +{ + notifyStateXsldbgAppFuncPtr = notifyStateXsldbgAppFunc; +} + + +void xsldbgSetTextFunc(int (*notifyTextXsldbgAppFunc)(XsldbgMessageEnum type, const char *text)) +{ + notifyTextXsldbgAppFuncPtr = notifyTextXsldbgAppFunc; +} + +void xsldbgSetReadlineFunc(xmlChar * (*xslDbgShellReadlineFunc)(xmlChar * prompt)) +{ + xslDbgShellReadlineFuncPtr = xslDbgShellReadlineFunc; +} + +int notifyXsldbgApp(XsldbgMessageEnum type, const void *data) +{ + if (!notifyXsldbgAppFuncPtr) + return 1; + else + return (notifyXsldbgAppFuncPtr)(type, data); +} + +int notifyStateXsldbgApp(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, const char *text) +{ + if (!notifyStateXsldbgAppFuncPtr) + return 1; + else + return (notifyStateXsldbgApp)(type, commandId, commandState, text); +} + +int notifyTextXsldbgApp(XsldbgMessageEnum type, const char *text) +{ + if (!notifyTextXsldbgAppFuncPtr) + return 1; + else + return (notifyTextXsldbgAppFuncPtr)(type, text); +} + + +/* use this function instead of the one that was in debugXSL.c */ +/** + * xslShellReadline: + * @prompt: the prompt value + * + * Read a string + * + * Returns a copy of the text inputed or NULL if EOF in stdin found. + * The caller is expected to free the returned string. + */ +xmlChar * +xslDbgShellReadline(xmlChar * prompt) +{ + + if (!xslDbgShellReadlineFuncPtr) + return 0; + else + return (xslDbgShellReadlineFuncPtr)(prompt); +} + +#ifdef __cplusplus +} +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.h new file mode 100644 index 00000000..12b16a3c --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgmsg.h @@ -0,0 +1,210 @@ + +/*************************************************************************** + xsldbgmsg.h - description + ------------------- + begin : Thu Dec 20 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef XSLDBGMSG_H +#define XSLDBGMSG_H + +#ifdef WIN32 +# include <libxsldbg/xsldbgwin32config.h> +#else +# ifndef XSLDBG_SO_API +# define XSLDBG_SO_API +# endif +#endif + +#ifndef BUILD_DOCS +#include <libxml/tree.h> /* needed for the definition of xmlChar */ +#include "arraylist.h" +#endif + +typedef enum { + /* thread status */ + XSLDBG_MSG_THREAD_NOTUSED, /* 0: Thread are not to be used */ + XSLDBG_MSG_THREAD_INIT, /* 1: The xsldbg thread is initializing */ + XSLDBG_MSG_THREAD_RUN, /* 2: The xsldbg thread is running */ + XSLDBG_MSG_THREAD_STOP, /* 3: The xsldbg thread is about to die */ + XSLDBG_MSG_THREAD_DEAD, /* 4: The xsldbg thread died */ + + /* input status ( once thread is running) */ + XSLDBG_MSG_AWAITING_INPUT, /* 5: Waiting for user input */ + XSLDBG_MSG_READ_INPUT, /* 6: Read user input */ + XSLDBG_MSG_PROCESSING_INPUT, /* 7: Processing user's request */ + + /* provide more informatiom about state of xsldbg (optional) */ + XSLDBG_MSG_PROCESSING_RESULT, /* 8: An error occured performing command + * requested command */ + XSLDBG_MSG_LINE_CHANGED, /* 9: Changed to new line number + * ie a step */ + XSLDBG_MSG_FILE_CHANGED, /* 10: Loaded source/data file */ + XSLDBG_MSG_BREAKPOINT_CHANGED, /* 11: Response to a showbreak command */ + XSLDBG_MSG_PARAMETER_CHANGED, /* 12: Response to showparam command */ + XSLDBG_MSG_TEXTOUT, /* 13 : Free form text from xsldg */ + XSLDBG_MSG_FILEOUT, /* 14 : Response to cat commmand, ie + * Free form text in file */ + XSLDBG_MSG_LOCALVAR_CHANGED, /* 15 : Response to locals command ie a + * local variable */ + XSLDBG_MSG_GLOBALVAR_CHANGED, /* 16 : Response to globals command + * ie a global variable */ + XSLDBG_MSG_TEMPLATE_CHANGED, /* 17 : Response to templates commmand + * ie template details */ + XSLDBG_MSG_SOURCE_CHANGED, /* 18 : Response to stylesheets command, + * a normal stylesheet */ + XSLDBG_MSG_INCLUDED_SOURCE_CHANGED, /* 19: Response to stylesheets + * command, a xmlNodeptr of + * a included stylesheet */ + XSLDBG_MSG_CALLSTACK_CHANGED, /* 20: Response to where command, + * ie a item on the call stack */ + XSLDBG_MSG_ENTITIY_CHANGED, /* 21: Response to entities + * command */ + XSLDBG_MSG_RESOLVE_CHANGE, /* 22: Response to system or + * public command */ + XSLDBG_MSG_LIST, /* 23 : As list of messages */ + + XSLDBG_MSG_INTOPTION_CHANGE, /* 23* Response to options command */ + XSLDBG_MSG_STRINGOPTION_CHANGE, /* 24* Response to options command */ + XSLDBG_MSG_ERROR_MESSAGE /* 25: Entercepted error message from libxml2 */ +} XsldbgMessageEnum; + + +typedef enum { + XSLDBG_COMMAND_FAILED, /* generic error */ + XSLDBG_COMMAND_WARNING, + XSLDBG_COMMAND_INFO, + XSLDBG_COMMAND_NOTUSED +} XsldbgCommandStateEnum; + + + +/** + * Notify the application that something happened to the xsldbg thread + * + * @param type : A valid XsldbgMessageEnum + * + * @param data : The meaning of data can have a different meaning for each value of @type + *<pre> + * Value of @type Meaning of @data + * -------------------------- +++ --------------------- + * XSLDBG_MSG_THREAD_NOTUSED, not used + * XSLDBG_MSG_THREAD_INIT, not used + * XSLDBG_MSG_THREAD_RUN, not used + * XSLDBG_MSG_THREAD_STOP, not used + * XSLDBG_MSG_THREAD_DEAD, not used + * XSLDBG_MSG_AWAITING_INPUT, not used + * XSLDBG_MSG_READ_INPUT, A value of the char* for user input + * XSLDBG_MSG_PROCESSING_INPUT, not used + * XSLDBG_MSG_PROCESSING_RESULT, A value of type xsldbgErrorMsgPtr + * XSLDBG_MSG_LINE_CHANGED Is non-NULL if reached breakpoint + * otherwise just change in line number + * of displayed source/data + * XSLDBG_MSG_FILE_CHANGED, not used + * XSLDBG_MSG_BREAKPOINT_CHANGED A breakPointPtr of the breakpoint + * XSLDBG_MSG_PARAMETER_CHANGED A parameterItemPtr of libxslt pameter. + * XSLDBG_MSG_TEXTOUT A char * to buffer for text output + * XSLDBG_MSG_FILEOUT A FILE * for text to output + * XSLDBG_MSG_LOCALVAR_CHANGED, A local variable of type xsltStackElemPtr + * XSLDBG_MSG_GLOBALVAR_CHANGED, A global variable of type xsltStackElemPtr + * XSLDBG_MSG_TEMPLATE_CHANGED, A template of type xsltTemplatePtr + * XSLDBG_MSG_SOURCE_CHANGED, A xsltStylesheetPtr of a normal stylesheet + * XSLDBG_MSG_INCLUDED_SOURCE_CHANGED A xmlNodePtr of a included stylsheet + * XSLDBG_MSG_CALLSTACK_CHANGED A callPointPtr of a call stack item + * XSLDBG_MSG_ENTITIY_CHANGED A const entityInfoPtr + * for the included entity + * XSLDBG_MSG_RESOLVE_CHANGE A xmlChar* of URI that + * SystemID or PublicID resolves to + * XSLDBG_MSG_LIST A notifyMessageListPtr + * + * XSLDBG_MSG_INTOPTION_CHANGE A paramItemPtr, value is not used + * XSLDBG_MSG_STRINGOPTION_CHANGE A paramItemPtr, intValue is not used + * XSLDBG_MSG_ERROR_MESSAGE A xmlErrorPtr + * + * + * Legend : + * not used :- value may be NULL but must not be used + * + * All values are to treated as volitile and are only guaranteed + * to be valid for the life of the notification messages. ie make a + * NEW copy of value if needed for longer than that. + * Unless stated otherwise, if reponse can return a value and the value is + * NULL then that indicates the start of a list of values + * + *<pre> + * @returns 1 on sucess + * 0 otherwise +*/ + +typedef struct _xsldbgErrorMsg xsldbgErrorMsg; +typedef xsldbgErrorMsg *xsldbgErrorMsgPtr; +struct _xsldbgErrorMsg { + XsldbgMessageEnum type; + int commandId; + XsldbgCommandStateEnum commandState; + xmlChar *text; + xmlChar *messagefileName; /* used when send large chunks of data */ +}; + + +typedef struct _notifyMessageList notifyMessageList; +typedef notifyMessageList *notifyMessageListPtr; +struct _notifyMessageList { + XsldbgMessageEnum type; + arrayListPtr list; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void xsldbgSetAppFunc(int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type, const void *data)); + +void xsldbgSetAppStateFunc(int (*notifyStateXsldbgAppFunc)(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, + const char *text)); + +void xsldbgSetTextFunc(int (*notifyTextXsldbgAppFunc)(XsldbgMessageEnum type, const char *text)); + +void xsldbgSetReadlineFunc(xmlChar * (*xslDbgShellReadlineFunc)(xmlChar * prompt)); + +int notifyXsldbgApp(XsldbgMessageEnum type, const void *data); + +int notifyStateXsldbgApp(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, + const char *text); + +int notifyTextXsldbgApp(XsldbgMessageEnum type, const char *text); + +xmlChar * xslDbgShellReadline(xmlChar * prompt); + + + /* The following functions implemented in xsldbgthread.c */ + int notifyListStart(XsldbgMessageEnum type); + + /* Data must be valid for until the next notifyListStart. + * Memory pointed to by @data will not be freed. Added @data items + * queued to list must be of the same data type as required by the + * XsldbgMessageEnum used with the matching notifyListSend */ + int notifyListQueue(const void *data); + + /* The notified application is responsible for free memory used + * by the ArrayList and notifyMessageList of notify message */ + int notifyListSend(void); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgnotifier.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgnotifier.h new file mode 100644 index 00000000..5c5aaeac --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgnotifier.h @@ -0,0 +1,48 @@ + +/*************************************************************************** + xsldbgnotifier.h - description + ------------------- + begin : Thu Dec 20 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef XSLDBGNOTIFIER_H +#define XSLDBGNOTIFIER_H + +#include "xsldbgmsg.h" + +#ifndef __cplusplus +#error "Must only be used with a c++ compiler" +#endif + + + +/** + *@author keith + */ + +class XsldbgNotifier { + public: + XsldbgNotifier(void); + virtual ~ XsldbgNotifier(void); + + virtual void doNotify(XsldbgMessageEnum type, const void *data); +}; + + + +/* get the notifer */ +void setNotifier(XsldbgNotifier * notifier); + + +#endif diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.cpp b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.cpp new file mode 100644 index 00000000..ecb94052 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.cpp @@ -0,0 +1,184 @@ + +/*************************************************************************** + xsldbgthread.c - basic thread support + ------------------- + begin : Thu Dec 20 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "xsldbg.h" +#include "breakpoint.h" +#include "options.h" + +#include "xsldbgmsg.h" +#include "xsldbgthread.h" + +static void (*cleanupFuncPtr)(void) = 0; +static int threadStatus = XSLDBG_MSG_THREAD_NOTUSED; +static int inputStatus = XSLDBG_MSG_AWAITING_INPUT; + +/* is xsldbg ready for input from the application */ +static int inputReady = 0; + +/* Is the application ready for a notification message */ +static int appReady = 0; + +static notifyMessageListPtr notifyList; + +arrayListPtr msgList = NULL; + +int +getAppReady(void) +{ + return appReady; +} + +void +setAppReady(int ready) +{ + appReady = ready; +} + + +/* the compiler will optimize this function to inline and to keep variable private*/ +int +getInputStatus(void) +{ + return inputStatus; +} + +void +setInputStatus(XsldbgMessageEnum type) +{ + switch (type) { + case XSLDBG_MSG_AWAITING_INPUT: /* Waiting for user input */ + case XSLDBG_MSG_READ_INPUT: /* Read user input */ + case XSLDBG_MSG_PROCESSING_INPUT: /* Processing user's request */ + inputStatus = type; + break; + + default: + printf("Invalid input status %d\n", type); + } +} + + +/* the compiler will optimize this function to inline and to keep variable private*/ +int +getThreadStatus(void) +{ + return threadStatus; +} + +/* reset the status to @p type */ +void +setThreadStatus(XsldbgMessageEnum type) +{ + switch (type) { + case XSLDBG_MSG_THREAD_NOTUSED: + case XSLDBG_MSG_THREAD_INIT: + case XSLDBG_MSG_THREAD_RUN: + threadStatus = type; + break; + + case XSLDBG_MSG_THREAD_STOP: + case XSLDBG_MSG_THREAD_DEAD: + xslDebugStatus = DEBUG_QUIT; + threadStatus = type; + break; + + default: + printf("Invalid thread status %d\n", type); + } +} + + +/* Is input ready yet */ +int +getInputReady(void) +{ + return inputReady; +} + +/* set/clear flag that indicates if input is ready*/ +void +setInputReady(int value) +{ + inputReady = value; +} + + + +int +notifyListStart(XsldbgMessageEnum type) +{ + int result = 0; + + switch (type) { + case XSLDBG_MSG_INTOPTION_CHANGE: + case XSLDBG_MSG_STRINGOPTION_CHANGE: + msgList = + arrayListNew(10, (freeItemFunc) optionsParamItemFree); + break; + + default: + msgList = arrayListNew(10, NULL); + } + + notifyList = + (notifyMessageListPtr) xmlMalloc(sizeof(notifyMessageList)); + if (notifyList && msgList) { + notifyList->type = type; + notifyList->list = msgList; + result = 1; + } + + return result; +} + +int +notifyListQueue(const void *data) +{ + int result = 0; + + if (msgList) { + arrayListAdd(msgList, (void *) data); + result = 1; + } + return result; +} + + +int +notifyListSend(void) +{ + int result = 0; + + if (notifyList && msgList) { + notifyXsldbgApp(XSLDBG_MSG_LIST, notifyList); + result = 1; + } + return result; +} + +void xsldbgSetThreadCleanupFunc(void (*cleanupFunc)(void)) +{ + cleanupFuncPtr = cleanupFunc; +} + +void xsldbgThreadCleanup(void) +{ + if (cleanupFuncPtr != 0) + (cleanupFuncPtr)(); +} diff --git a/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.h b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.h new file mode 100644 index 00000000..d83e71f3 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libxsldbg/xsldbgthread.h @@ -0,0 +1,90 @@ + +/*************************************************************************** + xsldbgthread.h - description + ------------------- + begin : Thu Dec 20 2001 + copyright : (C) 2001 by Keith Isdale + email : k_isdale@tpg.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef XSLDBGTHREAD_H +#define XSLDBGTHREAD_H + +#if defined WIN32 +#include <libxsldbg/xsldbgwin32config.h> +#endif + + +#ifndef BUILD_DOCS +#include <libxml/xmlmemory.h> +#include <libxml/tree.h> + +#include "xsldbgmsg.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + int getAppReady(void); + + void setAppReady(int ready); + + int getInputStatus(void); + + void setInputStatus(XsldbgMessageEnum type); + + int getThreadStatus(void); + + void setThreadStatus(XsldbgMessageEnum type); + + void *xsldbgThreadMain(void *data); + + int xsldbgMain(int argc, char **argv); + + int xsldbgThreadInit(void); + + void xsldbgThreadFree(void); + + /* thread has died so cleanup after it */ + void xsldbgThreadCleanup(void); + void xsldbgSetThreadCleanupFunc(void (*cleanupFunc)(void)); + + const char *getFakeInput(void); + + int fakeInput(const char *text); + + /* Is input ready yet */ + int getInputReady(void); + + /* set/clear flag that indicates if input is ready */ + void setInputReady(int value); + + xmlChar *xslDbgShellReadline(xmlChar * prompt); + + + + /* This is implemented by xsldbg.c */ + +/** + * xsldbgFree: + * + * Free memory used by xsldbg + */ + void xsldbgFree(void); + + +#ifdef __cplusplus +} +#endif +#endif |