summaryrefslogtreecommitdiffstats
path: root/kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commite9ae80694875f869892f13f4fcaf1170a00dea41 (patch)
treeaa2f8d8a217e2d376224c8d46b7397b68d35de2d /kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp
downloadtdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.tar.gz
tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp')
-rw-r--r--kxsldbg/kxsldbgpart/libxsldbg/breakpoint_cmds.cpp1036
1 files changed, 1036 insertions, 0 deletions
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
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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(&copy->url, &copy->lineNo);
+ } else {
+ result = validateData(&copy->url, &copy->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, &copy, (xsltTransformContextPtr)data);
+ }else{
+ result = validateBreakPoint(breakPtr, &copy);
+ }
+ }else{
+ xsldbgGenericErrorFunc(i18n("Error: Out of memory.\n"));
+ }
+
+ xmlFree(copy.url);
+ }
+}