diff options
Diffstat (limited to 'kxsldbg/kxsldbgpart/libqtnotfier/xsldbgthread.cpp')
-rw-r--r-- | kxsldbg/kxsldbgpart/libqtnotfier/xsldbgthread.cpp | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/kxsldbg/kxsldbgpart/libqtnotfier/xsldbgthread.cpp b/kxsldbg/kxsldbgpart/libqtnotfier/xsldbgthread.cpp new file mode 100644 index 00000000..1f428bb5 --- /dev/null +++ b/kxsldbg/kxsldbgpart/libqtnotfier/xsldbgthread.cpp @@ -0,0 +1,360 @@ +/*************************************************************************** + xsldbgthread.cpp - description + ------------------- + begin : Thu Dec 20 2001 + copyright : (C) 2001 by keith + email : keith@linux + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "config.h" +#include <pthread.h> /* need to create/work with process thread */ +#include <errno.h> /* need for EAGAIN */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> + +#include <libxml/xmlerror.h> + +#include "../libxsldbg/breakpoint.h" +#include "../libxsldbg/xsldbgmsg.h" +#include "../libxsldbg/xsldbgthread.h" +#include "../libxsldbg/qtnotifier2.h" + +#ifdef HAVE_READLINE +#include <readline/readline.h> +#ifdef HAVE_HISTORY +#include <readline/history.h> +#endif +#endif + +#define DEBUG_BUFFER_SIZE 500 + +static char inputBuffer[DEBUG_BUFFER_SIZE]; +static char outputBuffer[DEBUG_BUFFER_SIZE]; + +/*the major structure to hold information about the process thread */ +pthread_t mythread; + +/* The reader for stdout */ +pthread_t stdoutReaderThread; + +FILE *stdoutIO = NULL; + + +/* ----------------------------------------------- + private functions + ---------------------------------------------------*/ + +extern "C" { + +/** + * xsldbgGenericErrorFunc: + * @ctx: Is Valid + * @msg: Is valid + * @...: other parameters to use + * + * Handles print output from xsldbg and passes it to the application + */ +void +xsldbgGenericErrorFunc(void *ctx, const char *msg, ...); +xmlChar * qtXslDbgShellReadline(xmlChar * prompt); + +} + +/* ----------------------------------------------- + end functions + ---------------------------------------------------*/ + +/* setup all application wide items */ +int +xsldbgThreadInit(void) +{ + int result = 0; + fprintf(stderr, "mainInit()\n"); + xsltSetGenericErrorFunc(0, xsldbgGenericErrorFunc); + setThreadStatus(XSLDBG_MSG_THREAD_INIT); + xsldbgSetAppFunc(qtNotifyXsldbgApp); + xsldbgSetAppStateFunc(qtNotifyStateXsldbgApp); + xsldbgSetTextFunc(qtNotifyTextXsldbgApp); + xsldbgSetReadlineFunc(qtXslDbgShellReadline); + + + /* create the thread */ + if (pthread_create(&mythread, NULL, xsldbgThreadMain, NULL) != EAGAIN) { + int counter; + for (counter = 0; counter < 11; counter++){ + if (getThreadStatus() != XSLDBG_MSG_THREAD_INIT) + break; + usleep(250000); /*guess that it will take at most 2.5 seconds to startup */ + } + /* xsldbg should have started by now if it can */ + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN){ + fprintf(stderr, "Created thread\n"); + result++; + }else + fprintf(stderr, "Thread did not start\n"); + } else { + fprintf(stderr, "Failed to create thread\n"); + } + + return result; +} + + +/* tell the thread to stop and free that memory !*/ +void +xsldbgThreadFree(void) +{ + fprintf(stderr, "xsldbgThreadFree()\n"); + if (getThreadStatus() != XSLDBG_MSG_THREAD_DEAD) + { + int counter; + fprintf(stderr, "Killing xsldbg thread\n"); + setThreadStatus(XSLDBG_MSG_THREAD_STOP); + for (counter = 0; counter < 11; counter++){ + if (getThreadStatus() == XSLDBG_MSG_THREAD_DEAD) + break; + usleep(250000); /*guess that it will take at most 2.5 seconds to stop */ + } + } + +} + +const char *getFakeInput() +{ + return inputBuffer; +} + + +/* put text into standard input just like we had typed it */ +int +fakeInput(const char *text) +{ + int result = 0; + + if (!text || (getInputReady() == 1) || (getThreadStatus() != XSLDBG_MSG_THREAD_RUN)) + return result; + + // fprintf(stderr, "\nFaking input of \"%s\"\n", text); + strncpy(inputBuffer, text, sizeof(inputBuffer)); + setInputReady(1); + result++; + return result; +} + + +/* use this function instead of the one that was in debugXSL.c */ +/** + * qtXslDbgShellReadline: + * @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 * +qtXslDbgShellReadline(xmlChar * prompt) +{ + + const char *inputReadBuff; + + static char last_read[DEBUG_BUFFER_SIZE] = { '\0' }; + + if (getThreadStatus() != XSLDBG_MSG_THREAD_RUN) + { +#ifdef HAVE_READLINE + xmlChar *line_read; + + /* Get a line from the user. */ + line_read = (xmlChar *) readline((char *) prompt); + + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) { + add_history((char *) line_read); + strncpy((char*)last_read, (char*)line_read, DEBUG_BUFFER_SIZE - 1); + } else { + /* if only <Enter>is pressed then try last saved command line */ + line_read = (xmlChar *) xmlMemStrdup(last_read); + } + return (line_read); +#else + char line_read[DEBUG_BUFFER_SIZE]; + + if (prompt != NULL) + xsltGenericError(xsltGenericErrorContext, "%s", prompt); + if (!fgets(line_read, DEBUG_BUFFER_SIZE - 1, stdin)) + return (NULL); + line_read[DEBUG_BUFFER_SIZE - 1] = 0; + /* if only <Enter>is pressed then try last saved command line */ + if ((strlen(line_read) == 0) || (line_read[0] == '\n')) { + strcpy(line_read, last_read); + } else { + strcpy(last_read, line_read); + } + return (xmlChar *) xmlMemStrdup(line_read); +#endif + + } + else{ + + setInputStatus(XSLDBG_MSG_AWAITING_INPUT); + notifyXsldbgApp(XSLDBG_MSG_AWAITING_INPUT, NULL); + + while (getInputReady() == 0){ + usleep(10000); + /* have we been told to die */ + if (getThreadStatus() == XSLDBG_MSG_THREAD_STOP){ + fprintf(stderr, "About to stop thread\n"); + xslDebugStatus = DEBUG_QUIT; + return NULL; + } + } + + setInputStatus(XSLDBG_MSG_READ_INPUT); + inputReadBuff = getFakeInput(); + if(inputReadBuff){ + notifyXsldbgApp(XSLDBG_MSG_READ_INPUT, inputReadBuff); + return (xmlChar*)xmlMemStrdup(inputReadBuff); + }else{ + return NULL; + } + } +} + + +xsldbgErrorMsg msg; +xsldbgErrorMsgPtr msgPtr = &msg; +xmlChar *msgText = NULL; + +int qtNotifyStateXsldbgApp(XsldbgMessageEnum type, int commandId, + XsldbgCommandStateEnum commandState, const char *text) +{ + int result = 0; + msg.type = type; + msg.commandId = commandId; + msg.commandState = commandState; + if (text != NULL) + { + msg.text = (xmlChar*)xmlMemStrdup(text); + if (msg.text == NULL) + return result; /* out of memory */ + } + else + msg.text = NULL; + + notifyXsldbgApp(XSLDBG_MSG_PROCESSING_RESULT, msgPtr); + if (msg.text != NULL) + { + xmlFree(msg.text); + msg.text = NULL; + } + + result = 1; + return result; +} + + +int qtNotifyTextXsldbgApp(XsldbgMessageEnum type, const char *text) +{ + return qtNotifyStateXsldbgApp(type, -1, XSLDBG_COMMAND_NOTUSED, text); +} + +char mainBuffer[DEBUG_BUFFER_SIZE]; +static void xsldbgThreadCleanupQt(void); + + +/* this is where the thread get to do all its work */ +void * +xsldbgThreadMain(void *) +{ + // int defaultArgc = 2; + // char *defaultArgv[2]; + // int i; + + if (getThreadStatus() != XSLDBG_MSG_THREAD_INIT){ + fprintf(stderr, "xsldbg thread is not ready to be started. Or one is already running.\n"); + return NULL; /* we can't start more than one thread of xsldbg */ + } + +// defaultArgv[0] = xmlMemStrdup("xsldbg"); +// defaultArgv[1] = xmlMemStrdup("--shell"); + /* + defaultArgv[2] = xmlMemStrdup("xsldoc.xsl"); + defaultArgv[3] = xmlMemStrdup("xsldoc.xml"); + */ +/* for (i = 0; i < defaultArgc; i++){ + if (defaultArgv[i] == NULL){ + fprintf(stderr, "Start thread failed. Unable to create xsldbg arguments\n"); + return NULL; + } + } +*/ + xsldbgSetThreadCleanupFunc(xsldbgThreadCleanupQt); + setThreadStatus(XSLDBG_MSG_THREAD_RUN); + setInputStatus(XSLDBG_MSG_AWAITING_INPUT); + fprintf(stderr, "Starting thread\n"); + + /* call the "main of xsldbg" found in debugXSL.c */ +// xsldbgMain(defaultArgc, defaultArgv); + xsldbgMain(0,0); + fprintf(stderr, "Stopping thread\n"); +/* + for (i = 0; i < defaultArgc; i++){ + xmlFree(defaultArgv[i]); + } +*/ + + setThreadStatus(XSLDBG_MSG_THREAD_DEAD); + setInputStatus(XSLDBG_MSG_PROCESSING_INPUT); + notifyXsldbgApp(XSLDBG_MSG_THREAD_DEAD, NULL); + return NULL; +} + + + +/* thread has died so cleanup after it not called directly but via + notifyXsldbgApp*/ +void +xsldbgThreadCleanupQt(void) +{ + fprintf(stderr, "Thread has finished\n"); + if (getThreadStatus() == XSLDBG_MSG_THREAD_RUN) + { + xsldbgThreadFree(); + } + /* its safe to modify threadStatus as the thread is now dead */ + setThreadStatus(XSLDBG_MSG_THREAD_DEAD); +} + + + +void * +xsldbgThreadStdoutReader(void *data) +{ + if (!stdoutIO) + return data; + + while (getThreadStatus() == XSLDBG_MSG_THREAD_RUN){ + if (fgets(outputBuffer, sizeof(outputBuffer -1), stdoutIO)){ + usleep(10000); + strcat(outputBuffer, "\n"); + notifyTextXsldbgApp(XSLDBG_MSG_TEXTOUT, outputBuffer); + }else{ + fprintf(stderr, "Unable to read from stdout from xsldbg\n"); + break; + } + } + return data; +} |