/// \file /// Provides the debugging functions invoked by a recognizer /// built using the debug generator mode of the antlr tool. /// See antlr3debugeventlistener.h for documentation. /// // [The "BSD licence"] // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC // http://www.temporal-wave.com // http://www.linkedin.com/in/jimidle // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // 3. The name of the author may not be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <antlr3.h> // Not everyone wishes to include the debugger stuff in their final deployment because // it will then rely on being linked with the socket libraries. Hence if the programmer turns // off the debugging, we do some dummy stuff that satifies compilers etc but means there is // no debugger and no reliance on the socket librarires. If you set this flag, then using the -debug // option to generate your code will produce code that just crashes, but then I presme you are smart // enough to realize that building the libraries without debugger support means you can't call the // debugger ;-) // #ifdef ANTLR3_NODEBUGGER ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER antlr3DebugListenerNew() { ANTLR3_PRINTF("C runtime was compiled without debugger support. This program will crash!!"); return NULL; } #else static ANTLR3_BOOLEAN handshake (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void enterRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName); static void enterAlt (pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt); static void exitRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName); static void enterSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber); static void exitSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber); static void enterDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber); static void exitDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber); static void consumeToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t); static void consumeHiddenToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t); static void LT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t); static void mark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker); static void rewindMark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker); static void rewindLast (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void beginBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level); static void endBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful); static void location (pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos); static void recognitionException (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e); static void beginResync (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void endResync (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void semanticPredicate (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate); static void commence (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void terminate (pANTLR3_DEBUG_EVENT_LISTENER delboy); static void consumeNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t); static void LTT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t); static void nilNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t); static void errorNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t); static void createNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t); static void createNodeTok (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token); static void becomeRoot (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot); static void addChild (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child); static void setTokenBoundaries (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex); static void ack (pANTLR3_DEBUG_EVENT_LISTENER delboy); /// Create and initialize a new debug event listener that can be connected to /// by ANTLRWorks and any other debugger via a socket. /// ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER antlr3DebugListenerNew() { pANTLR3_DEBUG_EVENT_LISTENER delboy; delboy = ANTLR3_CALLOC(1, sizeof(ANTLR3_DEBUG_EVENT_LISTENER)); if (delboy == NULL) { return NULL; } // Initialize the API // delboy->addChild = addChild; delboy->becomeRoot = becomeRoot; delboy->beginBacktrack = beginBacktrack; delboy->beginResync = beginResync; delboy->commence = commence; delboy->consumeHiddenToken = consumeHiddenToken; delboy->consumeNode = consumeNode; delboy->consumeToken = consumeToken; delboy->createNode = createNode; delboy->createNodeTok = createNodeTok; delboy->endBacktrack = endBacktrack; delboy->endResync = endResync; delboy->enterAlt = enterAlt; delboy->enterDecision = enterDecision; delboy->enterRule = enterRule; delboy->enterSubRule = enterSubRule; delboy->exitDecision = exitDecision; delboy->exitRule = exitRule; delboy->exitSubRule = exitSubRule; delboy->handshake = handshake; delboy->location = location; delboy->LT = LT; delboy->LTT = LTT; delboy->mark = mark; delboy->nilNode = nilNode; delboy->recognitionException = recognitionException; delboy->rewind = rewindMark; delboy->rewindLast = rewindLast; delboy->semanticPredicate = semanticPredicate; delboy->setTokenBoundaries = setTokenBoundaries; delboy->terminate = terminate; delboy->errorNode = errorNode; delboy->PROTOCOL_VERSION = 2; // ANTLR 3.1 is at protocol version 2 delboy->port = DEFAULT_DEBUGGER_PORT; return delboy; } pANTLR3_DEBUG_EVENT_LISTENER antlr3DebugListenerNewPort(ANTLR3_UINT32 port) { pANTLR3_DEBUG_EVENT_LISTENER delboy; delboy = antlr3DebugListenerNew(); if (delboy != NULL) { delboy->port = port; } return delboy; } //-------------------------------------------------------------------------------- // Support functions for sending stuff over the socket interface // static int sockSend(SOCKET sock, const char * ptr, int len) { int sent; int thisSend; sent = 0; while (sent < len) { // Send as many bytes as we can // thisSend = send(sock, ptr, len - sent, 0); // Check for errors and tell the user if we got one // if (thisSend == -1) { return ANTLR3_FALSE; } // Increment our offset by how many we were able to send // ptr += thisSend; sent += thisSend; } return ANTLR3_TRUE; } static ANTLR3_BOOLEAN handshake (pANTLR3_DEBUG_EVENT_LISTENER delboy) { /// Connection structure with which to wait and accept a connection from /// a debugger. /// SOCKET serverSocket; // Connection structures to deal with the client after we accept the connection // and the server while we accept a connection. // ANTLR3_SOCKADDRT client; ANTLR3_SOCKADDRT server; // Buffer to construct our message in // char message[256]; // Specifies the length of the connection structure to accept() // Windows use int, everyone else uses size_t // ANTLR3_SALENT sockaddr_len; // Option holder for setsockopt() // int optVal; if (delboy->initialized == ANTLR3_FALSE) { // Windows requires us to initialize WinSock. // #ifdef ANTLR3_WINDOWS { WORD wVersionRequested; WSADATA wsaData; int err; // Return code from WSAStartup // We must initialise the Windows socket system when the DLL is loaded. // We are asking for Winsock 1.1 or better as we don't need anything // too complicated for this. // wVersionRequested = MAKEWORD( 1, 1); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // Tell the user that we could not find a usable // WinSock DLL // return FALSE; } } #endif // Create the server socket, we are the server because we just wait until // a debugger connects to the port we are listening on. // serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { return ANTLR3_FALSE; } // Set the listening port // server.sin_port = htons((unsigned short)delboy->port); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl (INADDR_ANY); // We could allow a rebind on the same addr/port pair I suppose, but // I imagine that most people will just want to start debugging one parser at once. // Maybe change this at some point, but rejecting the bind at this point will ensure // that people realize they have left something running in the background. // if (bind(serverSocket, (pANTLR3_SOCKADDRC)&server, sizeof(server)) == -1) { return ANTLR3_FALSE; } // We have bound the socket to the port and address so we now ask the TCP subsystem // to start listening on that address/port // if (listen(serverSocket, 1) == -1) { // Some error, just fail // return ANTLR3_FALSE; } // Now we can try to accept a connection on the port // sockaddr_len = sizeof(client); delboy->socket = accept(serverSocket, (pANTLR3_SOCKADDRC)&client, &sockaddr_len); // Having accepted a connection, we can stop listening and close down the socket // shutdown (serverSocket, 0x02); ANTLR3_CLOSESOCKET (serverSocket); if (delboy->socket == -1) { return ANTLR3_FALSE; } // Disable Nagle as this is essentially a chat exchange // optVal = 1; setsockopt(delboy->socket, SOL_SOCKET, TCP_NODELAY, (const void *)&optVal, sizeof(optVal)); } // We now have a good socket connection with the debugging client, so we // send it the protocol version we are using and what the name of the grammar // is that we represent. // sprintf (message, "ANTLR %d\n", delboy->PROTOCOL_VERSION); sockSend (delboy->socket, message, (int)strlen(message)); sprintf (message, "grammar \"%s\n", delboy->grammarFileName->chars); sockSend (delboy->socket, message, (int)strlen(message)); ack (delboy); delboy->initialized = ANTLR3_TRUE; return ANTLR3_TRUE; } // Send the supplied text and wait for an ack from the client static void transmit(pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * ptr) { sockSend(delboy->socket, ptr, (int)strlen(ptr)); ack(delboy); } static void ack (pANTLR3_DEBUG_EVENT_LISTENER delboy) { // Local buffer to read the next character in to // char buffer; int rCount; // Ack terminates in a line feed, so we just wait for // one of those. Speed is not of the essence so we don't need // to buffer the input or anything. // do { rCount = recv(delboy->socket, &buffer, 1, 0); } while (rCount == 1 && buffer != '\n'); // If the socket ws closed on us, then we will get an error or // (with a graceful close), 0. We can assume the the debugger stopped for some reason // (such as Java crashing again). Therefore we just exit the program // completely if we don't get the terminating '\n' for the ack. // if (rCount != 1) { ANTLR3_PRINTF("Exiting debugger as remote client closed the socket\n"); ANTLR3_PRINTF("Received char count was %d, and last char received was %02X\n", rCount, buffer); exit(0); } } // Given a buffer string and a source string, serialize the // text, escaping any newlines and linefeeds. We have no need // for speed here, this is the debugger. // void serializeText(pANTLR3_STRING buffer, pANTLR3_STRING text) { ANTLR3_UINT32 c; ANTLR3_UCHAR character; // strings lead in with a " // buffer->append(buffer, "\t\""); if (text == NULL) { return; } // Now we replace linefeeds, newlines and the escape // leadin character '%' with their hex equivalents // prefixed by '%' // for (c = 0; c < text->len; c++) { switch (character = text->charAt(text, c)) { case '\n': buffer->append(buffer, "%0A"); break; case '\r': buffer->append(buffer, "%0D"); break; case '\\': buffer->append(buffer, "%25"); break; // Other characters: The Song Remains the Same. // default: buffer->addc(buffer, character); break; } } } // Given a token, create a stringified version of it, in the supplied // buffer. We create a string for this in the debug 'object', if there // is not one there already, and then reuse it here if asked to do this // again. // pANTLR3_STRING serializeToken(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t) { // Do we already have a serialization buffer? // if (delboy->tokenString == NULL) { // No, so create one, using the string factory that // the grammar name used, which is guaranteed to exist. // 64 bytes will do us here for starters. // delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64); } // Empty string // delboy->tokenString->set(delboy->tokenString, (const char *)""); // Now we serialize the elements of the token.Note that the debugger only // uses 32 bits. // delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getTokenIndex(t))); delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getType(t))); delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getChannel(t))); delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getLine(t))); delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getCharPositionInLine(t))); // Now send the text that the token represents. // serializeText(delboy->tokenString, t->getText(t)); // Finally, as the debugger is a Java program it will expect to get UTF-8 // encoded strings. We don't use UTF-8 internally to the C runtime, so we // must force encode it. We have a method to do this in the string class, but // it returns malloc space that we must free afterwards. // return delboy->tokenString->toUTF8(delboy->tokenString); } // Given a tree node, create a stringified version of it in the supplied // buffer. // pANTLR3_STRING serializeNode(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node) { pANTLR3_COMMON_TOKEN token; // Do we already have a serialization buffer? // if (delboy->tokenString == NULL) { // No, so create one, using the string factory that // the grammar name used, which is guaranteed to exist. // 64 bytes will do us here for starters. // delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64); } // Empty string // delboy->tokenString->set(delboy->tokenString, (const char *)""); // Protect against bugs/errors etc // if (node == NULL) { return delboy->tokenString; } // Now we serialize the elements of the node.Note that the debugger only // uses 32 bits. // delboy->tokenString->addc(delboy->tokenString, '\t'); // Adaptor ID // delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, node)); delboy->tokenString->addc(delboy->tokenString, '\t'); // Type of the current token (which may be imaginary) // delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getType(delboy->adaptor, node)); // See if we have an actual token or just an imaginary // token = delboy->adaptor->getToken(delboy->adaptor, node); delboy->tokenString->addc(delboy->tokenString, '\t'); if (token != NULL) { // Real token // delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(token->getLine(token))); delboy->tokenString->addc(delboy->tokenString, ' '); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(token->getCharPositionInLine(token))); } else { // Imaginary tokens have no location // delboy->tokenString->addi(delboy->tokenString, -1); delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, -1); } // Start Index of the node // delboy->tokenString->addc(delboy->tokenString, '\t'); delboy->tokenString->addi(delboy->tokenString, (ANTLR3_UINT32)(delboy->adaptor->getTokenStartIndex(delboy->adaptor, node))); // Now send the text that the node represents. // serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, node)); // Finally, as the debugger is a Java program it will expect to get UTF-8 // encoded strings. We don't use UTF-8 internally to the C runtime, so we // must force encode it. We have a method to do this in the string class, but // there is no utf8 string implementation as of yet // return delboy->tokenString->toUTF8(delboy->tokenString); } //------------------------------------------------------------------------------------------------------------------ // EVENTS // static void enterRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "enterRule\t%s\t%s\n", grammarFileName, ruleName); transmit(delboy, buffer); } static void enterAlt (pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "enterAlt\t%d\n", alt); transmit(delboy, buffer); } static void exitRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "exitRule\t%s\t%s\n", grammarFileName, ruleName); transmit(delboy, buffer); } static void enterSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "enterSubRule\t%d\n", decisionNumber); transmit(delboy, buffer); } static void exitSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "exitSubRule\t%d\n", decisionNumber); transmit(delboy, buffer); } static void enterDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "enterDecision\t%d\n", decisionNumber); transmit(delboy, buffer); } static void exitDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber) { char buffer[512]; // Create the message (speed is not of the essence) // sprintf(buffer, "exitDecision\t%d\n", decisionNumber); transmit(delboy, buffer); } static void consumeToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t) { pANTLR3_STRING msg; // Create the serialized token // msg = serializeToken(delboy, t); // Insert the debug event indicator // msg->insert8(msg, 0, "consumeToken\t"); msg->addc(msg, '\n'); // Transmit the message and wait for ack // transmit(delboy, (const char *)(msg->chars)); } static void consumeHiddenToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t) { pANTLR3_STRING msg; // Create the serialized token // msg = serializeToken(delboy, t); // Insert the debug event indicator // msg->insert8(msg, 0, "consumeHiddenToken\t"); msg->addc(msg, '\n'); // Transmit the message and wait for ack // transmit(delboy, (const char *)(msg->chars)); } // Looking at the next token event. // static void LT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t) { pANTLR3_STRING msg; if (t != NULL) { // Create the serialized token // msg = serializeToken(delboy, t); // Insert the index parameter // msg->insert8(msg, 0, "\t"); msg->inserti(msg, 0, i); // Insert the debug event indicator // msg->insert8(msg, 0, "LT\t"); msg->addc(msg, '\n'); // Transmit the message and wait for ack // transmit(delboy, (const char *)(msg->chars)); } } static void mark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker) { char buffer[128]; sprintf(buffer, "mark\t%d\n", (ANTLR3_UINT32)(marker & 0xFFFFFFFF)); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void rewindMark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker) { char buffer[128]; sprintf(buffer, "rewind\t%d\n", (ANTLR3_UINT32)(marker & 0xFFFFFFFF)); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void rewindLast (pANTLR3_DEBUG_EVENT_LISTENER delboy) { transmit(delboy, (const char *)"rewind\n"); } static void beginBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level) { char buffer[128]; sprintf(buffer, "beginBacktrack\t%d\n", (ANTLR3_UINT32)(level & 0xFFFFFFFF)); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void endBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful) { char buffer[128]; sprintf(buffer, "endBacktrack\t%d\t%d\n", level, successful); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void location (pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos) { char buffer[128]; sprintf(buffer, "location\t%d\t%d\n", line, pos); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void recognitionException (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e) { char buffer[256]; sprintf(buffer, "exception\t%s\t%d\t%d\t%d\n", (char *)(e->name), (ANTLR3_INT32)(e->index), e->line, e->charPositionInLine); // Transmit the message and wait for ack // transmit(delboy, buffer); } static void beginResync (pANTLR3_DEBUG_EVENT_LISTENER delboy) { transmit(delboy, (const char *)"beginResync\n"); } static void endResync (pANTLR3_DEBUG_EVENT_LISTENER delboy) { transmit(delboy, (const char *)"endResync\n"); } static void semanticPredicate (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate) { unsigned char * buffer; unsigned char * out; if (predicate != NULL) { buffer = (unsigned char *)ANTLR3_MALLOC(64 + 2*strlen(predicate)); if (buffer != NULL) { out = buffer + sprintf((char *)buffer, "semanticPredicate\t%s\t", result == ANTLR3_TRUE ? "true" : "false"); while (*predicate != '\0') { switch(*predicate) { case '\n': *out++ = '%'; *out++ = '0'; *out++ = 'A'; break; case '\r': *out++ = '%'; *out++ = '0'; *out++ = 'D'; break; case '%': *out++ = '%'; *out++ = '0'; *out++ = 'D'; break; default: *out++ = *predicate; break; } predicate++; } *out++ = '\n'; *out++ = '\0'; } // Send it and wait for the ack // transmit(delboy, (const char *)buffer); } } #ifdef ANTLR3_WINDOWS #pragma warning (push) #pragma warning (disable : 4100) #endif static void commence (pANTLR3_DEBUG_EVENT_LISTENER delboy) { // Nothing to see here // } #ifdef ANTLR3_WINDOWS #pragma warning (pop) #endif static void terminate (pANTLR3_DEBUG_EVENT_LISTENER delboy) { // Terminate sequence // sockSend(delboy->socket, "terminate\n", 10); // Send out the command } //---------------------------------------------------------------- // Tree parsing events // static void consumeNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t) { pANTLR3_STRING buffer; buffer = serializeNode (delboy, t); // Now prepend the command // buffer->insert8 (buffer, 0, "consumeNode\t"); buffer->addc (buffer, '\n'); // Send to the debugger and wait for the ack // transmit (delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars)); } static void LTT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t) { pANTLR3_STRING buffer; buffer = serializeNode (delboy, t); // Now prepend the command // buffer->insert8 (buffer, 0, "\t"); buffer->inserti (buffer, 0, i); buffer->insert8 (buffer, 0, "LN\t"); buffer->addc (buffer, '\n'); // Send to the debugger and wait for the ack // transmit (delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars)); } static void nilNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t) { char buffer[128]; sprintf(buffer, "nilNode\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, t)); transmit(delboy, buffer); } static void createNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t) { // Do we already have a serialization buffer? // if (delboy->tokenString == NULL) { // No, so create one, using the string factory that // the grammar name used, which is guaranteed to exist. // 64 bytes will do us here for starters. // delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64); } // Empty string // delboy->tokenString->set8(delboy->tokenString, (const char *)"createNodeFromTokenElements "); // Now we serialize the elements of the node.Note that the debugger only // uses 32 bits. // // Adaptor ID // delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, t)); delboy->tokenString->addc(delboy->tokenString, '\t'); // Type of the current token (which may be imaginary) // delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getType(delboy->adaptor, t)); // The text that this node represents // serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, t)); delboy->tokenString->addc(delboy->tokenString, '\n'); // Finally, as the debugger is a Java program it will expect to get UTF-8 // encoded strings. We don't use UTF-8 internally to the C runtime, so we // must force encode it. We have a method to do this in the string class, but // there is no utf8 string implementation as of yet // transmit(delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars)); } static void errorNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t) { // Do we already have a serialization buffer? // if (delboy->tokenString == NULL) { // No, so create one, using the string factory that // the grammar name used, which is guaranteed to exist. // 64 bytes will do us here for starters. // delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64); } // Empty string // delboy->tokenString->set8(delboy->tokenString, (const char *)"errorNode\t"); // Now we serialize the elements of the node.Note that the debugger only // uses 32 bits. // // Adaptor ID // delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, t)); delboy->tokenString->addc(delboy->tokenString, '\t'); // Type of the current token (which is an error) // delboy->tokenString->addi(delboy->tokenString, ANTLR3_TOKEN_INVALID); // The text that this node represents // serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, t)); delboy->tokenString->addc(delboy->tokenString, '\n'); // Finally, as the debugger is a Java program it will expect to get UTF-8 // encoded strings. We don't use UTF-8 internally to the C runtime, so we // must force encode it. We have a method to do this in the string class, but // there is no utf8 string implementation as of yet // transmit(delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars)); } static void createNodeTok (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token) { char buffer[128]; sprintf(buffer, "createNode\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, node), (ANTLR3_UINT32)token->getTokenIndex(token)); transmit(delboy, buffer); } static void becomeRoot (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot) { char buffer[128]; sprintf(buffer, "becomeRoot\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, newRoot), delboy->adaptor->getUniqueID(delboy->adaptor, oldRoot) ); transmit(delboy, buffer); } static void addChild (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child) { char buffer[128]; sprintf(buffer, "addChild\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, root), delboy->adaptor->getUniqueID(delboy->adaptor, child) ); transmit(delboy, buffer); } static void setTokenBoundaries (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex) { char buffer[128]; sprintf(buffer, "becomeRoot\t%d\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, t), (ANTLR3_UINT32)tokenStartIndex, (ANTLR3_UINT32)tokenStopIndex ); transmit(delboy, buffer); } #endif