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