1*16467b97STreehugger Robot /// \file
2*16467b97STreehugger Robot /// Provides the debugging functions invoked by a recognizer
3*16467b97STreehugger Robot /// built using the debug generator mode of the antlr tool.
4*16467b97STreehugger Robot /// See antlr3debugeventlistener.h for documentation.
5*16467b97STreehugger Robot ///
6*16467b97STreehugger Robot
7*16467b97STreehugger Robot // [The "BSD licence"]
8*16467b97STreehugger Robot // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
9*16467b97STreehugger Robot // http://www.temporal-wave.com
10*16467b97STreehugger Robot // http://www.linkedin.com/in/jimidle
11*16467b97STreehugger Robot //
12*16467b97STreehugger Robot // All rights reserved.
13*16467b97STreehugger Robot //
14*16467b97STreehugger Robot // Redistribution and use in source and binary forms, with or without
15*16467b97STreehugger Robot // modification, are permitted provided that the following conditions
16*16467b97STreehugger Robot // are met:
17*16467b97STreehugger Robot // 1. Redistributions of source code must retain the above copyright
18*16467b97STreehugger Robot // notice, this list of conditions and the following disclaimer.
19*16467b97STreehugger Robot // 2. Redistributions in binary form must reproduce the above copyright
20*16467b97STreehugger Robot // notice, this list of conditions and the following disclaimer in the
21*16467b97STreehugger Robot // documentation and/or other materials provided with the distribution.
22*16467b97STreehugger Robot // 3. The name of the author may not be used to endorse or promote products
23*16467b97STreehugger Robot // derived from this software without specific prior written permission.
24*16467b97STreehugger Robot //
25*16467b97STreehugger Robot // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26*16467b97STreehugger Robot // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27*16467b97STreehugger Robot // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28*16467b97STreehugger Robot // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29*16467b97STreehugger Robot // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30*16467b97STreehugger Robot // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31*16467b97STreehugger Robot // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32*16467b97STreehugger Robot // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33*16467b97STreehugger Robot // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34*16467b97STreehugger Robot // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*16467b97STreehugger Robot
36*16467b97STreehugger Robot #include <antlr3.h>
37*16467b97STreehugger Robot
38*16467b97STreehugger Robot // Not everyone wishes to include the debugger stuff in their final deployment because
39*16467b97STreehugger Robot // it will then rely on being linked with the socket libraries. Hence if the programmer turns
40*16467b97STreehugger Robot // off the debugging, we do some dummy stuff that satifies compilers etc but means there is
41*16467b97STreehugger Robot // no debugger and no reliance on the socket librarires. If you set this flag, then using the -debug
42*16467b97STreehugger Robot // option to generate your code will produce code that just crashes, but then I presme you are smart
43*16467b97STreehugger Robot // enough to realize that building the libraries without debugger support means you can't call the
44*16467b97STreehugger Robot // debugger ;-)
45*16467b97STreehugger Robot //
46*16467b97STreehugger Robot #ifdef ANTLR3_NODEBUGGER
47*16467b97STreehugger Robot ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER
antlr3DebugListenerNew()48*16467b97STreehugger Robot antlr3DebugListenerNew()
49*16467b97STreehugger Robot {
50*16467b97STreehugger Robot ANTLR3_PRINTF("C runtime was compiled without debugger support. This program will crash!!");
51*16467b97STreehugger Robot return NULL;
52*16467b97STreehugger Robot }
53*16467b97STreehugger Robot #else
54*16467b97STreehugger Robot
55*16467b97STreehugger Robot static ANTLR3_BOOLEAN handshake (pANTLR3_DEBUG_EVENT_LISTENER delboy);
56*16467b97STreehugger Robot static void enterRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);
57*16467b97STreehugger Robot static void enterAlt (pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt);
58*16467b97STreehugger Robot static void exitRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);
59*16467b97STreehugger Robot static void enterSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
60*16467b97STreehugger Robot static void exitSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
61*16467b97STreehugger Robot static void enterDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
62*16467b97STreehugger Robot static void exitDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
63*16467b97STreehugger Robot static void consumeToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);
64*16467b97STreehugger Robot static void consumeHiddenToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);
65*16467b97STreehugger Robot static void LT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t);
66*16467b97STreehugger Robot static void mark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);
67*16467b97STreehugger Robot static void rewindMark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);
68*16467b97STreehugger Robot static void rewindLast (pANTLR3_DEBUG_EVENT_LISTENER delboy);
69*16467b97STreehugger Robot static void beginBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level);
70*16467b97STreehugger Robot static void endBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful);
71*16467b97STreehugger Robot static void location (pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos);
72*16467b97STreehugger Robot static void recognitionException (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e);
73*16467b97STreehugger Robot static void beginResync (pANTLR3_DEBUG_EVENT_LISTENER delboy);
74*16467b97STreehugger Robot static void endResync (pANTLR3_DEBUG_EVENT_LISTENER delboy);
75*16467b97STreehugger Robot static void semanticPredicate (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate);
76*16467b97STreehugger Robot static void commence (pANTLR3_DEBUG_EVENT_LISTENER delboy);
77*16467b97STreehugger Robot static void terminate (pANTLR3_DEBUG_EVENT_LISTENER delboy);
78*16467b97STreehugger Robot static void consumeNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
79*16467b97STreehugger Robot static void LTT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t);
80*16467b97STreehugger Robot static void nilNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
81*16467b97STreehugger Robot static void errorNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
82*16467b97STreehugger Robot static void createNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
83*16467b97STreehugger Robot static void createNodeTok (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token);
84*16467b97STreehugger Robot static void becomeRoot (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot);
85*16467b97STreehugger Robot static void addChild (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child);
86*16467b97STreehugger Robot static void setTokenBoundaries (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex);
87*16467b97STreehugger Robot static void ack (pANTLR3_DEBUG_EVENT_LISTENER delboy);
88*16467b97STreehugger Robot
89*16467b97STreehugger Robot /// Create and initialize a new debug event listener that can be connected to
90*16467b97STreehugger Robot /// by ANTLRWorks and any other debugger via a socket.
91*16467b97STreehugger Robot ///
92*16467b97STreehugger Robot ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER
antlr3DebugListenerNew()93*16467b97STreehugger Robot antlr3DebugListenerNew()
94*16467b97STreehugger Robot {
95*16467b97STreehugger Robot pANTLR3_DEBUG_EVENT_LISTENER delboy;
96*16467b97STreehugger Robot
97*16467b97STreehugger Robot delboy = (pANTLR3_DEBUG_EVENT_LISTENER)ANTLR3_CALLOC(1, sizeof(ANTLR3_DEBUG_EVENT_LISTENER));
98*16467b97STreehugger Robot
99*16467b97STreehugger Robot if (delboy == NULL)
100*16467b97STreehugger Robot {
101*16467b97STreehugger Robot return NULL;
102*16467b97STreehugger Robot }
103*16467b97STreehugger Robot
104*16467b97STreehugger Robot // Initialize the API
105*16467b97STreehugger Robot //
106*16467b97STreehugger Robot delboy->addChild = addChild;
107*16467b97STreehugger Robot delboy->becomeRoot = becomeRoot;
108*16467b97STreehugger Robot delboy->beginBacktrack = beginBacktrack;
109*16467b97STreehugger Robot delboy->beginResync = beginResync;
110*16467b97STreehugger Robot delboy->commence = commence;
111*16467b97STreehugger Robot delboy->consumeHiddenToken = consumeHiddenToken;
112*16467b97STreehugger Robot delboy->consumeNode = consumeNode;
113*16467b97STreehugger Robot delboy->consumeToken = consumeToken;
114*16467b97STreehugger Robot delboy->createNode = createNode;
115*16467b97STreehugger Robot delboy->createNodeTok = createNodeTok;
116*16467b97STreehugger Robot delboy->endBacktrack = endBacktrack;
117*16467b97STreehugger Robot delboy->endResync = endResync;
118*16467b97STreehugger Robot delboy->enterAlt = enterAlt;
119*16467b97STreehugger Robot delboy->enterDecision = enterDecision;
120*16467b97STreehugger Robot delboy->enterRule = enterRule;
121*16467b97STreehugger Robot delboy->enterSubRule = enterSubRule;
122*16467b97STreehugger Robot delboy->exitDecision = exitDecision;
123*16467b97STreehugger Robot delboy->exitRule = exitRule;
124*16467b97STreehugger Robot delboy->exitSubRule = exitSubRule;
125*16467b97STreehugger Robot delboy->handshake = handshake;
126*16467b97STreehugger Robot delboy->location = location;
127*16467b97STreehugger Robot delboy->LT = LT;
128*16467b97STreehugger Robot delboy->LTT = LTT;
129*16467b97STreehugger Robot delboy->mark = mark;
130*16467b97STreehugger Robot delboy->nilNode = nilNode;
131*16467b97STreehugger Robot delboy->recognitionException = recognitionException;
132*16467b97STreehugger Robot delboy->rewind = rewindMark;
133*16467b97STreehugger Robot delboy->rewindLast = rewindLast;
134*16467b97STreehugger Robot delboy->semanticPredicate = semanticPredicate;
135*16467b97STreehugger Robot delboy->setTokenBoundaries = setTokenBoundaries;
136*16467b97STreehugger Robot delboy->terminate = terminate;
137*16467b97STreehugger Robot delboy->errorNode = errorNode;
138*16467b97STreehugger Robot
139*16467b97STreehugger Robot delboy->protocol_version = 2; // ANTLR 3.1 is at protocol version 2
140*16467b97STreehugger Robot
141*16467b97STreehugger Robot delboy->port = DEFAULT_DEBUGGER_PORT;
142*16467b97STreehugger Robot
143*16467b97STreehugger Robot return delboy;
144*16467b97STreehugger Robot }
145*16467b97STreehugger Robot
146*16467b97STreehugger Robot pANTLR3_DEBUG_EVENT_LISTENER
antlr3DebugListenerNewPort(ANTLR3_UINT32 port)147*16467b97STreehugger Robot antlr3DebugListenerNewPort(ANTLR3_UINT32 port)
148*16467b97STreehugger Robot {
149*16467b97STreehugger Robot pANTLR3_DEBUG_EVENT_LISTENER delboy;
150*16467b97STreehugger Robot
151*16467b97STreehugger Robot delboy = antlr3DebugListenerNew();
152*16467b97STreehugger Robot
153*16467b97STreehugger Robot if (delboy != NULL)
154*16467b97STreehugger Robot {
155*16467b97STreehugger Robot delboy->port = port;
156*16467b97STreehugger Robot }
157*16467b97STreehugger Robot
158*16467b97STreehugger Robot return delboy;
159*16467b97STreehugger Robot }
160*16467b97STreehugger Robot
161*16467b97STreehugger Robot //--------------------------------------------------------------------------------
162*16467b97STreehugger Robot // Support functions for sending stuff over the socket interface
163*16467b97STreehugger Robot //
164*16467b97STreehugger Robot static int
sockSend(SOCKET sock,const char * ptr,int len)165*16467b97STreehugger Robot sockSend(SOCKET sock, const char * ptr, int len)
166*16467b97STreehugger Robot {
167*16467b97STreehugger Robot int sent;
168*16467b97STreehugger Robot int thisSend;
169*16467b97STreehugger Robot
170*16467b97STreehugger Robot sent = 0;
171*16467b97STreehugger Robot
172*16467b97STreehugger Robot while (sent < len)
173*16467b97STreehugger Robot {
174*16467b97STreehugger Robot // Send as many bytes as we can
175*16467b97STreehugger Robot //
176*16467b97STreehugger Robot thisSend = send(sock, ptr, len - sent, 0);
177*16467b97STreehugger Robot
178*16467b97STreehugger Robot // Check for errors and tell the user if we got one
179*16467b97STreehugger Robot //
180*16467b97STreehugger Robot if (thisSend == -1)
181*16467b97STreehugger Robot {
182*16467b97STreehugger Robot return ANTLR3_FALSE;
183*16467b97STreehugger Robot }
184*16467b97STreehugger Robot
185*16467b97STreehugger Robot // Increment our offset by how many we were able to send
186*16467b97STreehugger Robot //
187*16467b97STreehugger Robot ptr += thisSend;
188*16467b97STreehugger Robot sent += thisSend;
189*16467b97STreehugger Robot }
190*16467b97STreehugger Robot return ANTLR3_TRUE;
191*16467b97STreehugger Robot }
192*16467b97STreehugger Robot
193*16467b97STreehugger Robot static ANTLR3_BOOLEAN
handshake(pANTLR3_DEBUG_EVENT_LISTENER delboy)194*16467b97STreehugger Robot handshake (pANTLR3_DEBUG_EVENT_LISTENER delboy)
195*16467b97STreehugger Robot {
196*16467b97STreehugger Robot /// Connection structure with which to wait and accept a connection from
197*16467b97STreehugger Robot /// a debugger.
198*16467b97STreehugger Robot ///
199*16467b97STreehugger Robot SOCKET serverSocket;
200*16467b97STreehugger Robot
201*16467b97STreehugger Robot // Connection structures to deal with the client after we accept the connection
202*16467b97STreehugger Robot // and the server while we accept a connection.
203*16467b97STreehugger Robot //
204*16467b97STreehugger Robot ANTLR3_SOCKADDRT client;
205*16467b97STreehugger Robot ANTLR3_SOCKADDRT server;
206*16467b97STreehugger Robot
207*16467b97STreehugger Robot // Buffer to construct our message in
208*16467b97STreehugger Robot //
209*16467b97STreehugger Robot char message[256];
210*16467b97STreehugger Robot
211*16467b97STreehugger Robot // Specifies the length of the connection structure to accept()
212*16467b97STreehugger Robot // Windows use int, everyone else uses size_t
213*16467b97STreehugger Robot //
214*16467b97STreehugger Robot ANTLR3_SALENT sockaddr_len;
215*16467b97STreehugger Robot
216*16467b97STreehugger Robot // Option holder for setsockopt()
217*16467b97STreehugger Robot //
218*16467b97STreehugger Robot int optVal;
219*16467b97STreehugger Robot
220*16467b97STreehugger Robot if (delboy->initialized == ANTLR3_FALSE)
221*16467b97STreehugger Robot {
222*16467b97STreehugger Robot // Windows requires us to initialize WinSock.
223*16467b97STreehugger Robot //
224*16467b97STreehugger Robot #ifdef ANTLR3_WINDOWS
225*16467b97STreehugger Robot {
226*16467b97STreehugger Robot WORD wVersionRequested;
227*16467b97STreehugger Robot WSADATA wsaData;
228*16467b97STreehugger Robot int err; // Return code from WSAStartup
229*16467b97STreehugger Robot
230*16467b97STreehugger Robot // We must initialise the Windows socket system when the DLL is loaded.
231*16467b97STreehugger Robot // We are asking for Winsock 1.1 or better as we don't need anything
232*16467b97STreehugger Robot // too complicated for this.
233*16467b97STreehugger Robot //
234*16467b97STreehugger Robot wVersionRequested = MAKEWORD( 1, 1);
235*16467b97STreehugger Robot
236*16467b97STreehugger Robot err = WSAStartup( wVersionRequested, &wsaData );
237*16467b97STreehugger Robot
238*16467b97STreehugger Robot if ( err != 0 )
239*16467b97STreehugger Robot {
240*16467b97STreehugger Robot // Tell the user that we could not find a usable
241*16467b97STreehugger Robot // WinSock DLL
242*16467b97STreehugger Robot //
243*16467b97STreehugger Robot return FALSE;
244*16467b97STreehugger Robot }
245*16467b97STreehugger Robot }
246*16467b97STreehugger Robot #endif
247*16467b97STreehugger Robot
248*16467b97STreehugger Robot // Create the server socket, we are the server because we just wait until
249*16467b97STreehugger Robot // a debugger connects to the port we are listening on.
250*16467b97STreehugger Robot //
251*16467b97STreehugger Robot serverSocket = socket(AF_INET, SOCK_STREAM, 0);
252*16467b97STreehugger Robot
253*16467b97STreehugger Robot if (serverSocket == INVALID_SOCKET)
254*16467b97STreehugger Robot {
255*16467b97STreehugger Robot return ANTLR3_FALSE;
256*16467b97STreehugger Robot }
257*16467b97STreehugger Robot
258*16467b97STreehugger Robot // Set the listening port
259*16467b97STreehugger Robot //
260*16467b97STreehugger Robot server.sin_port = htons((unsigned short)delboy->port);
261*16467b97STreehugger Robot server.sin_family = AF_INET;
262*16467b97STreehugger Robot server.sin_addr.s_addr = htonl (INADDR_ANY);
263*16467b97STreehugger Robot
264*16467b97STreehugger Robot // We could allow a rebind on the same addr/port pair I suppose, but
265*16467b97STreehugger Robot // I imagine that most people will just want to start debugging one parser at once.
266*16467b97STreehugger Robot // Maybe change this at some point, but rejecting the bind at this point will ensure
267*16467b97STreehugger Robot // that people realize they have left something running in the background.
268*16467b97STreehugger Robot //
269*16467b97STreehugger Robot if (bind(serverSocket, (pANTLR3_SOCKADDRC)&server, sizeof(server)) == -1)
270*16467b97STreehugger Robot {
271*16467b97STreehugger Robot return ANTLR3_FALSE;
272*16467b97STreehugger Robot }
273*16467b97STreehugger Robot
274*16467b97STreehugger Robot // We have bound the socket to the port and address so we now ask the TCP subsystem
275*16467b97STreehugger Robot // to start listening on that address/port
276*16467b97STreehugger Robot //
277*16467b97STreehugger Robot if (listen(serverSocket, 1) == -1)
278*16467b97STreehugger Robot {
279*16467b97STreehugger Robot // Some error, just fail
280*16467b97STreehugger Robot //
281*16467b97STreehugger Robot return ANTLR3_FALSE;
282*16467b97STreehugger Robot }
283*16467b97STreehugger Robot
284*16467b97STreehugger Robot // Now we can try to accept a connection on the port
285*16467b97STreehugger Robot //
286*16467b97STreehugger Robot sockaddr_len = sizeof(client);
287*16467b97STreehugger Robot delboy->socket = accept(serverSocket, (pANTLR3_SOCKADDRC)&client, &sockaddr_len);
288*16467b97STreehugger Robot
289*16467b97STreehugger Robot // Having accepted a connection, we can stop listening and close down the socket
290*16467b97STreehugger Robot //
291*16467b97STreehugger Robot shutdown (serverSocket, 0x02);
292*16467b97STreehugger Robot ANTLR3_CLOSESOCKET (serverSocket);
293*16467b97STreehugger Robot
294*16467b97STreehugger Robot if (delboy->socket == -1)
295*16467b97STreehugger Robot {
296*16467b97STreehugger Robot return ANTLR3_FALSE;
297*16467b97STreehugger Robot }
298*16467b97STreehugger Robot
299*16467b97STreehugger Robot // Disable Nagle as this is essentially a chat exchange
300*16467b97STreehugger Robot //
301*16467b97STreehugger Robot optVal = 1;
302*16467b97STreehugger Robot setsockopt(delboy->socket, SOL_SOCKET, TCP_NODELAY, (const char *)&optVal, sizeof(optVal));
303*16467b97STreehugger Robot
304*16467b97STreehugger Robot }
305*16467b97STreehugger Robot
306*16467b97STreehugger Robot // We now have a good socket connection with the debugging client, so we
307*16467b97STreehugger Robot // send it the protocol version we are using and what the name of the grammar
308*16467b97STreehugger Robot // is that we represent.
309*16467b97STreehugger Robot //
310*16467b97STreehugger Robot sprintf (message, "ANTLR %d\n", delboy->protocol_version);
311*16467b97STreehugger Robot sockSend (delboy->socket, message, (int)strlen(message));
312*16467b97STreehugger Robot sprintf (message, "grammar \"%s\n", delboy->grammarFileName->chars);
313*16467b97STreehugger Robot sockSend (delboy->socket, message, (int)strlen(message));
314*16467b97STreehugger Robot ack (delboy);
315*16467b97STreehugger Robot
316*16467b97STreehugger Robot delboy->initialized = ANTLR3_TRUE;
317*16467b97STreehugger Robot
318*16467b97STreehugger Robot return ANTLR3_TRUE;
319*16467b97STreehugger Robot }
320*16467b97STreehugger Robot
321*16467b97STreehugger Robot // Send the supplied text and wait for an ack from the client
322*16467b97STreehugger Robot static void
transmit(pANTLR3_DEBUG_EVENT_LISTENER delboy,const char * ptr)323*16467b97STreehugger Robot transmit(pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * ptr)
324*16467b97STreehugger Robot {
325*16467b97STreehugger Robot sockSend(delboy->socket, ptr, (int)strlen(ptr));
326*16467b97STreehugger Robot ack(delboy);
327*16467b97STreehugger Robot }
328*16467b97STreehugger Robot
329*16467b97STreehugger Robot static void
ack(pANTLR3_DEBUG_EVENT_LISTENER delboy)330*16467b97STreehugger Robot ack (pANTLR3_DEBUG_EVENT_LISTENER delboy)
331*16467b97STreehugger Robot {
332*16467b97STreehugger Robot // Local buffer to read the next character in to
333*16467b97STreehugger Robot //
334*16467b97STreehugger Robot char buffer;
335*16467b97STreehugger Robot int rCount;
336*16467b97STreehugger Robot
337*16467b97STreehugger Robot // Ack terminates in a line feed, so we just wait for
338*16467b97STreehugger Robot // one of those. Speed is not of the essence so we don't need
339*16467b97STreehugger Robot // to buffer the input or anything.
340*16467b97STreehugger Robot //
341*16467b97STreehugger Robot do
342*16467b97STreehugger Robot {
343*16467b97STreehugger Robot rCount = recv(delboy->socket, &buffer, 1, 0);
344*16467b97STreehugger Robot }
345*16467b97STreehugger Robot while (rCount == 1 && buffer != '\n');
346*16467b97STreehugger Robot
347*16467b97STreehugger Robot // If the socket ws closed on us, then we will get an error or
348*16467b97STreehugger Robot // (with a graceful close), 0. We can assume the the debugger stopped for some reason
349*16467b97STreehugger Robot // (such as Java crashing again). Therefore we just exit the program
350*16467b97STreehugger Robot // completely if we don't get the terminating '\n' for the ack.
351*16467b97STreehugger Robot //
352*16467b97STreehugger Robot if (rCount != 1)
353*16467b97STreehugger Robot {
354*16467b97STreehugger Robot ANTLR3_PRINTF("Exiting debugger as remote client closed the socket\n");
355*16467b97STreehugger Robot ANTLR3_PRINTF("Received char count was %d, and last char received was %02X\n", rCount, buffer);
356*16467b97STreehugger Robot exit(0);
357*16467b97STreehugger Robot }
358*16467b97STreehugger Robot }
359*16467b97STreehugger Robot
360*16467b97STreehugger Robot // Given a buffer string and a source string, serialize the
361*16467b97STreehugger Robot // text, escaping any newlines and linefeeds. We have no need
362*16467b97STreehugger Robot // for speed here, this is the debugger.
363*16467b97STreehugger Robot //
364*16467b97STreehugger Robot void
serializeText(pANTLR3_STRING buffer,pANTLR3_STRING text)365*16467b97STreehugger Robot serializeText(pANTLR3_STRING buffer, pANTLR3_STRING text)
366*16467b97STreehugger Robot {
367*16467b97STreehugger Robot ANTLR3_UINT32 c;
368*16467b97STreehugger Robot ANTLR3_UCHAR character;
369*16467b97STreehugger Robot
370*16467b97STreehugger Robot // strings lead in with a "
371*16467b97STreehugger Robot //
372*16467b97STreehugger Robot buffer->append(buffer, "\t\"");
373*16467b97STreehugger Robot
374*16467b97STreehugger Robot if (text == NULL)
375*16467b97STreehugger Robot {
376*16467b97STreehugger Robot return;
377*16467b97STreehugger Robot }
378*16467b97STreehugger Robot
379*16467b97STreehugger Robot // Now we replace linefeeds, newlines and the escape
380*16467b97STreehugger Robot // leadin character '%' with their hex equivalents
381*16467b97STreehugger Robot // prefixed by '%'
382*16467b97STreehugger Robot //
383*16467b97STreehugger Robot for (c = 0; c < text->len; c++)
384*16467b97STreehugger Robot {
385*16467b97STreehugger Robot switch (character = text->charAt(text, c))
386*16467b97STreehugger Robot {
387*16467b97STreehugger Robot case '\n':
388*16467b97STreehugger Robot
389*16467b97STreehugger Robot buffer->append(buffer, "%0A");
390*16467b97STreehugger Robot break;
391*16467b97STreehugger Robot
392*16467b97STreehugger Robot case '\r':
393*16467b97STreehugger Robot
394*16467b97STreehugger Robot buffer->append(buffer, "%0D");
395*16467b97STreehugger Robot break;
396*16467b97STreehugger Robot
397*16467b97STreehugger Robot case '\\':
398*16467b97STreehugger Robot
399*16467b97STreehugger Robot buffer->append(buffer, "%25");
400*16467b97STreehugger Robot break;
401*16467b97STreehugger Robot
402*16467b97STreehugger Robot // Other characters: The Song Remains the Same.
403*16467b97STreehugger Robot //
404*16467b97STreehugger Robot default:
405*16467b97STreehugger Robot
406*16467b97STreehugger Robot buffer->addc(buffer, character);
407*16467b97STreehugger Robot break;
408*16467b97STreehugger Robot }
409*16467b97STreehugger Robot }
410*16467b97STreehugger Robot }
411*16467b97STreehugger Robot
412*16467b97STreehugger Robot // Given a token, create a stringified version of it, in the supplied
413*16467b97STreehugger Robot // buffer. We create a string for this in the debug 'object', if there
414*16467b97STreehugger Robot // is not one there already, and then reuse it here if asked to do this
415*16467b97STreehugger Robot // again.
416*16467b97STreehugger Robot //
417*16467b97STreehugger Robot pANTLR3_STRING
serializeToken(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_COMMON_TOKEN t)418*16467b97STreehugger Robot serializeToken(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t)
419*16467b97STreehugger Robot {
420*16467b97STreehugger Robot // Do we already have a serialization buffer?
421*16467b97STreehugger Robot //
422*16467b97STreehugger Robot if (delboy->tokenString == NULL)
423*16467b97STreehugger Robot {
424*16467b97STreehugger Robot // No, so create one, using the string factory that
425*16467b97STreehugger Robot // the grammar name used, which is guaranteed to exist.
426*16467b97STreehugger Robot // 64 bytes will do us here for starters.
427*16467b97STreehugger Robot //
428*16467b97STreehugger Robot delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64);
429*16467b97STreehugger Robot }
430*16467b97STreehugger Robot
431*16467b97STreehugger Robot // Empty string
432*16467b97STreehugger Robot //
433*16467b97STreehugger Robot delboy->tokenString->set(delboy->tokenString, (const char *)"");
434*16467b97STreehugger Robot
435*16467b97STreehugger Robot // Now we serialize the elements of the token.Note that the debugger only
436*16467b97STreehugger Robot // uses 32 bits.
437*16467b97STreehugger Robot //
438*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getTokenIndex(t)));
439*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
440*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getType(t)));
441*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
442*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getChannel(t)));
443*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
444*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getLine(t)));
445*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
446*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(t->getCharPositionInLine(t)));
447*16467b97STreehugger Robot
448*16467b97STreehugger Robot // Now send the text that the token represents.
449*16467b97STreehugger Robot //
450*16467b97STreehugger Robot serializeText(delboy->tokenString, t->getText(t));
451*16467b97STreehugger Robot
452*16467b97STreehugger Robot // Finally, as the debugger is a Java program it will expect to get UTF-8
453*16467b97STreehugger Robot // encoded strings. We don't use UTF-8 internally to the C runtime, so we
454*16467b97STreehugger Robot // must force encode it. We have a method to do this in the string class, but
455*16467b97STreehugger Robot // it returns malloc space that we must free afterwards.
456*16467b97STreehugger Robot //
457*16467b97STreehugger Robot return delboy->tokenString->toUTF8(delboy->tokenString);
458*16467b97STreehugger Robot }
459*16467b97STreehugger Robot
460*16467b97STreehugger Robot // Given a tree node, create a stringified version of it in the supplied
461*16467b97STreehugger Robot // buffer.
462*16467b97STreehugger Robot //
463*16467b97STreehugger Robot pANTLR3_STRING
serializeNode(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE node)464*16467b97STreehugger Robot serializeNode(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node)
465*16467b97STreehugger Robot {
466*16467b97STreehugger Robot pANTLR3_COMMON_TOKEN token;
467*16467b97STreehugger Robot
468*16467b97STreehugger Robot
469*16467b97STreehugger Robot // Do we already have a serialization buffer?
470*16467b97STreehugger Robot //
471*16467b97STreehugger Robot if (delboy->tokenString == NULL)
472*16467b97STreehugger Robot {
473*16467b97STreehugger Robot // No, so create one, using the string factory that
474*16467b97STreehugger Robot // the grammar name used, which is guaranteed to exist.
475*16467b97STreehugger Robot // 64 bytes will do us here for starters.
476*16467b97STreehugger Robot //
477*16467b97STreehugger Robot delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64);
478*16467b97STreehugger Robot }
479*16467b97STreehugger Robot
480*16467b97STreehugger Robot // Empty string
481*16467b97STreehugger Robot //
482*16467b97STreehugger Robot delboy->tokenString->set(delboy->tokenString, (const char *)"");
483*16467b97STreehugger Robot
484*16467b97STreehugger Robot // Protect against bugs/errors etc
485*16467b97STreehugger Robot //
486*16467b97STreehugger Robot if (node == NULL)
487*16467b97STreehugger Robot {
488*16467b97STreehugger Robot return delboy->tokenString;
489*16467b97STreehugger Robot }
490*16467b97STreehugger Robot
491*16467b97STreehugger Robot // Now we serialize the elements of the node.Note that the debugger only
492*16467b97STreehugger Robot // uses 32 bits.
493*16467b97STreehugger Robot //
494*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
495*16467b97STreehugger Robot
496*16467b97STreehugger Robot // Adaptor ID
497*16467b97STreehugger Robot //
498*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, node));
499*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
500*16467b97STreehugger Robot
501*16467b97STreehugger Robot // Type of the current token (which may be imaginary)
502*16467b97STreehugger Robot //
503*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getType(delboy->adaptor, node));
504*16467b97STreehugger Robot
505*16467b97STreehugger Robot // See if we have an actual token or just an imaginary
506*16467b97STreehugger Robot //
507*16467b97STreehugger Robot token = delboy->adaptor->getToken(delboy->adaptor, node);
508*16467b97STreehugger Robot
509*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
510*16467b97STreehugger Robot if (token != NULL)
511*16467b97STreehugger Robot {
512*16467b97STreehugger Robot // Real token
513*16467b97STreehugger Robot //
514*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(token->getLine(token)));
515*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, ' ');
516*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_INT32)(token->getCharPositionInLine(token)));
517*16467b97STreehugger Robot }
518*16467b97STreehugger Robot else
519*16467b97STreehugger Robot {
520*16467b97STreehugger Robot // Imaginary tokens have no location
521*16467b97STreehugger Robot //
522*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, -1);
523*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
524*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, -1);
525*16467b97STreehugger Robot }
526*16467b97STreehugger Robot
527*16467b97STreehugger Robot // Start Index of the node
528*16467b97STreehugger Robot //
529*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
530*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, (ANTLR3_UINT32)(delboy->adaptor->getTokenStartIndex(delboy->adaptor, node)));
531*16467b97STreehugger Robot
532*16467b97STreehugger Robot // Now send the text that the node represents.
533*16467b97STreehugger Robot //
534*16467b97STreehugger Robot serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, node));
535*16467b97STreehugger Robot
536*16467b97STreehugger Robot // Finally, as the debugger is a Java program it will expect to get UTF-8
537*16467b97STreehugger Robot // encoded strings. We don't use UTF-8 internally to the C runtime, so we
538*16467b97STreehugger Robot // must force encode it. We have a method to do this in the string class, but
539*16467b97STreehugger Robot // there is no utf8 string implementation as of yet
540*16467b97STreehugger Robot //
541*16467b97STreehugger Robot return delboy->tokenString->toUTF8(delboy->tokenString);
542*16467b97STreehugger Robot }
543*16467b97STreehugger Robot
544*16467b97STreehugger Robot //------------------------------------------------------------------------------------------------------------------
545*16467b97STreehugger Robot // EVENTS
546*16467b97STreehugger Robot //
547*16467b97STreehugger Robot static void
enterRule(pANTLR3_DEBUG_EVENT_LISTENER delboy,const char * grammarFileName,const char * ruleName)548*16467b97STreehugger Robot enterRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName)
549*16467b97STreehugger Robot {
550*16467b97STreehugger Robot char buffer[512];
551*16467b97STreehugger Robot
552*16467b97STreehugger Robot // Create the message (speed is not of the essence)
553*16467b97STreehugger Robot //
554*16467b97STreehugger Robot sprintf(buffer, "enterRule\t%s\t%s\n", grammarFileName, ruleName);
555*16467b97STreehugger Robot transmit(delboy, buffer);
556*16467b97STreehugger Robot }
557*16467b97STreehugger Robot
558*16467b97STreehugger Robot static void
enterAlt(pANTLR3_DEBUG_EVENT_LISTENER delboy,int alt)559*16467b97STreehugger Robot enterAlt (pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt)
560*16467b97STreehugger Robot {
561*16467b97STreehugger Robot char buffer[512];
562*16467b97STreehugger Robot
563*16467b97STreehugger Robot // Create the message (speed is not of the essence)
564*16467b97STreehugger Robot //
565*16467b97STreehugger Robot sprintf(buffer, "enterAlt\t%d\n", alt);
566*16467b97STreehugger Robot transmit(delboy, buffer);
567*16467b97STreehugger Robot }
568*16467b97STreehugger Robot
569*16467b97STreehugger Robot static void
exitRule(pANTLR3_DEBUG_EVENT_LISTENER delboy,const char * grammarFileName,const char * ruleName)570*16467b97STreehugger Robot exitRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName)
571*16467b97STreehugger Robot {
572*16467b97STreehugger Robot char buffer[512];
573*16467b97STreehugger Robot
574*16467b97STreehugger Robot // Create the message (speed is not of the essence)
575*16467b97STreehugger Robot //
576*16467b97STreehugger Robot sprintf(buffer, "exitRule\t%s\t%s\n", grammarFileName, ruleName);
577*16467b97STreehugger Robot transmit(delboy, buffer);
578*16467b97STreehugger Robot }
579*16467b97STreehugger Robot
580*16467b97STreehugger Robot static void
enterSubRule(pANTLR3_DEBUG_EVENT_LISTENER delboy,int decisionNumber)581*16467b97STreehugger Robot enterSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber)
582*16467b97STreehugger Robot {
583*16467b97STreehugger Robot char buffer[512];
584*16467b97STreehugger Robot
585*16467b97STreehugger Robot // Create the message (speed is not of the essence)
586*16467b97STreehugger Robot //
587*16467b97STreehugger Robot sprintf(buffer, "enterSubRule\t%d\n", decisionNumber);
588*16467b97STreehugger Robot transmit(delboy, buffer);
589*16467b97STreehugger Robot }
590*16467b97STreehugger Robot
591*16467b97STreehugger Robot static void
exitSubRule(pANTLR3_DEBUG_EVENT_LISTENER delboy,int decisionNumber)592*16467b97STreehugger Robot exitSubRule (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber)
593*16467b97STreehugger Robot {
594*16467b97STreehugger Robot char buffer[512];
595*16467b97STreehugger Robot
596*16467b97STreehugger Robot // Create the message (speed is not of the essence)
597*16467b97STreehugger Robot //
598*16467b97STreehugger Robot sprintf(buffer, "exitSubRule\t%d\n", decisionNumber);
599*16467b97STreehugger Robot transmit(delboy, buffer);
600*16467b97STreehugger Robot }
601*16467b97STreehugger Robot
602*16467b97STreehugger Robot static void
enterDecision(pANTLR3_DEBUG_EVENT_LISTENER delboy,int decisionNumber)603*16467b97STreehugger Robot enterDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber)
604*16467b97STreehugger Robot {
605*16467b97STreehugger Robot char buffer[512];
606*16467b97STreehugger Robot
607*16467b97STreehugger Robot // Create the message (speed is not of the essence)
608*16467b97STreehugger Robot //
609*16467b97STreehugger Robot sprintf(buffer, "enterDecision\t%d\n", decisionNumber);
610*16467b97STreehugger Robot transmit(delboy, buffer);
611*16467b97STreehugger Robot
612*16467b97STreehugger Robot }
613*16467b97STreehugger Robot
614*16467b97STreehugger Robot static void
exitDecision(pANTLR3_DEBUG_EVENT_LISTENER delboy,int decisionNumber)615*16467b97STreehugger Robot exitDecision (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber)
616*16467b97STreehugger Robot {
617*16467b97STreehugger Robot char buffer[512];
618*16467b97STreehugger Robot
619*16467b97STreehugger Robot // Create the message (speed is not of the essence)
620*16467b97STreehugger Robot //
621*16467b97STreehugger Robot sprintf(buffer, "exitDecision\t%d\n", decisionNumber);
622*16467b97STreehugger Robot transmit(delboy, buffer);
623*16467b97STreehugger Robot }
624*16467b97STreehugger Robot
625*16467b97STreehugger Robot static void
consumeToken(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_COMMON_TOKEN t)626*16467b97STreehugger Robot consumeToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t)
627*16467b97STreehugger Robot {
628*16467b97STreehugger Robot pANTLR3_STRING msg;
629*16467b97STreehugger Robot
630*16467b97STreehugger Robot // Create the serialized token
631*16467b97STreehugger Robot //
632*16467b97STreehugger Robot msg = serializeToken(delboy, t);
633*16467b97STreehugger Robot
634*16467b97STreehugger Robot // Insert the debug event indicator
635*16467b97STreehugger Robot //
636*16467b97STreehugger Robot msg->insert8(msg, 0, "consumeToken\t");
637*16467b97STreehugger Robot
638*16467b97STreehugger Robot msg->addc(msg, '\n');
639*16467b97STreehugger Robot
640*16467b97STreehugger Robot // Transmit the message and wait for ack
641*16467b97STreehugger Robot //
642*16467b97STreehugger Robot transmit(delboy, (const char *)(msg->chars));
643*16467b97STreehugger Robot }
644*16467b97STreehugger Robot
645*16467b97STreehugger Robot static void
consumeHiddenToken(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_COMMON_TOKEN t)646*16467b97STreehugger Robot consumeHiddenToken (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t)
647*16467b97STreehugger Robot {
648*16467b97STreehugger Robot pANTLR3_STRING msg;
649*16467b97STreehugger Robot
650*16467b97STreehugger Robot // Create the serialized token
651*16467b97STreehugger Robot //
652*16467b97STreehugger Robot msg = serializeToken(delboy, t);
653*16467b97STreehugger Robot
654*16467b97STreehugger Robot // Insert the debug event indicator
655*16467b97STreehugger Robot //
656*16467b97STreehugger Robot msg->insert8(msg, 0, "consumeHiddenToken\t");
657*16467b97STreehugger Robot
658*16467b97STreehugger Robot msg->addc(msg, '\n');
659*16467b97STreehugger Robot
660*16467b97STreehugger Robot // Transmit the message and wait for ack
661*16467b97STreehugger Robot //
662*16467b97STreehugger Robot transmit(delboy, (const char *)(msg->chars));
663*16467b97STreehugger Robot }
664*16467b97STreehugger Robot
665*16467b97STreehugger Robot // Looking at the next token event.
666*16467b97STreehugger Robot //
667*16467b97STreehugger Robot static void
LT(pANTLR3_DEBUG_EVENT_LISTENER delboy,int i,pANTLR3_COMMON_TOKEN t)668*16467b97STreehugger Robot LT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t)
669*16467b97STreehugger Robot {
670*16467b97STreehugger Robot pANTLR3_STRING msg;
671*16467b97STreehugger Robot
672*16467b97STreehugger Robot if (t != NULL)
673*16467b97STreehugger Robot {
674*16467b97STreehugger Robot // Create the serialized token
675*16467b97STreehugger Robot //
676*16467b97STreehugger Robot msg = serializeToken(delboy, t);
677*16467b97STreehugger Robot
678*16467b97STreehugger Robot // Insert the index parameter
679*16467b97STreehugger Robot //
680*16467b97STreehugger Robot msg->insert8(msg, 0, "\t");
681*16467b97STreehugger Robot msg->inserti(msg, 0, i);
682*16467b97STreehugger Robot
683*16467b97STreehugger Robot // Insert the debug event indicator
684*16467b97STreehugger Robot //
685*16467b97STreehugger Robot msg->insert8(msg, 0, "LT\t");
686*16467b97STreehugger Robot
687*16467b97STreehugger Robot msg->addc(msg, '\n');
688*16467b97STreehugger Robot
689*16467b97STreehugger Robot // Transmit the message and wait for ack
690*16467b97STreehugger Robot //
691*16467b97STreehugger Robot transmit(delboy, (const char *)(msg->chars));
692*16467b97STreehugger Robot }
693*16467b97STreehugger Robot }
694*16467b97STreehugger Robot
695*16467b97STreehugger Robot static void
mark(pANTLR3_DEBUG_EVENT_LISTENER delboy,ANTLR3_MARKER marker)696*16467b97STreehugger Robot mark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker)
697*16467b97STreehugger Robot {
698*16467b97STreehugger Robot char buffer[128];
699*16467b97STreehugger Robot
700*16467b97STreehugger Robot sprintf(buffer, "mark\t%d\n", (ANTLR3_UINT32)(marker & 0xFFFFFFFF));
701*16467b97STreehugger Robot
702*16467b97STreehugger Robot // Transmit the message and wait for ack
703*16467b97STreehugger Robot //
704*16467b97STreehugger Robot transmit(delboy, buffer);
705*16467b97STreehugger Robot }
706*16467b97STreehugger Robot
707*16467b97STreehugger Robot static void
rewindMark(pANTLR3_DEBUG_EVENT_LISTENER delboy,ANTLR3_MARKER marker)708*16467b97STreehugger Robot rewindMark (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker)
709*16467b97STreehugger Robot {
710*16467b97STreehugger Robot char buffer[128];
711*16467b97STreehugger Robot
712*16467b97STreehugger Robot sprintf(buffer, "rewind\t%d\n", (ANTLR3_UINT32)(marker & 0xFFFFFFFF));
713*16467b97STreehugger Robot
714*16467b97STreehugger Robot // Transmit the message and wait for ack
715*16467b97STreehugger Robot //
716*16467b97STreehugger Robot transmit(delboy, buffer);
717*16467b97STreehugger Robot
718*16467b97STreehugger Robot }
719*16467b97STreehugger Robot
720*16467b97STreehugger Robot static void
rewindLast(pANTLR3_DEBUG_EVENT_LISTENER delboy)721*16467b97STreehugger Robot rewindLast (pANTLR3_DEBUG_EVENT_LISTENER delboy)
722*16467b97STreehugger Robot {
723*16467b97STreehugger Robot transmit(delboy, (const char *)"rewind\n");
724*16467b97STreehugger Robot }
725*16467b97STreehugger Robot
726*16467b97STreehugger Robot static void
beginBacktrack(pANTLR3_DEBUG_EVENT_LISTENER delboy,int level)727*16467b97STreehugger Robot beginBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level)
728*16467b97STreehugger Robot {
729*16467b97STreehugger Robot char buffer[128];
730*16467b97STreehugger Robot
731*16467b97STreehugger Robot sprintf(buffer, "beginBacktrack\t%d\n", (ANTLR3_UINT32)(level & 0xFFFFFFFF));
732*16467b97STreehugger Robot
733*16467b97STreehugger Robot // Transmit the message and wait for ack
734*16467b97STreehugger Robot //
735*16467b97STreehugger Robot transmit(delboy, buffer);
736*16467b97STreehugger Robot }
737*16467b97STreehugger Robot
738*16467b97STreehugger Robot static void
endBacktrack(pANTLR3_DEBUG_EVENT_LISTENER delboy,int level,ANTLR3_BOOLEAN successful)739*16467b97STreehugger Robot endBacktrack (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful)
740*16467b97STreehugger Robot {
741*16467b97STreehugger Robot char buffer[128];
742*16467b97STreehugger Robot
743*16467b97STreehugger Robot sprintf(buffer, "endBacktrack\t%d\t%d\n", level, successful);
744*16467b97STreehugger Robot
745*16467b97STreehugger Robot // Transmit the message and wait for ack
746*16467b97STreehugger Robot //
747*16467b97STreehugger Robot transmit(delboy, buffer);
748*16467b97STreehugger Robot }
749*16467b97STreehugger Robot
750*16467b97STreehugger Robot static void
location(pANTLR3_DEBUG_EVENT_LISTENER delboy,int line,int pos)751*16467b97STreehugger Robot location (pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos)
752*16467b97STreehugger Robot {
753*16467b97STreehugger Robot char buffer[128];
754*16467b97STreehugger Robot
755*16467b97STreehugger Robot sprintf(buffer, "location\t%d\t%d\n", line, pos);
756*16467b97STreehugger Robot
757*16467b97STreehugger Robot // Transmit the message and wait for ack
758*16467b97STreehugger Robot //
759*16467b97STreehugger Robot transmit(delboy, buffer);
760*16467b97STreehugger Robot }
761*16467b97STreehugger Robot
762*16467b97STreehugger Robot static void
recognitionException(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_EXCEPTION e)763*16467b97STreehugger Robot recognitionException (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e)
764*16467b97STreehugger Robot {
765*16467b97STreehugger Robot char buffer[256];
766*16467b97STreehugger Robot
767*16467b97STreehugger Robot sprintf(buffer, "exception\t%s\t%d\t%d\t%d\n", (char *)(e->name), (ANTLR3_INT32)(e->index), e->line, e->charPositionInLine);
768*16467b97STreehugger Robot
769*16467b97STreehugger Robot // Transmit the message and wait for ack
770*16467b97STreehugger Robot //
771*16467b97STreehugger Robot transmit(delboy, buffer);
772*16467b97STreehugger Robot }
773*16467b97STreehugger Robot
774*16467b97STreehugger Robot static void
beginResync(pANTLR3_DEBUG_EVENT_LISTENER delboy)775*16467b97STreehugger Robot beginResync (pANTLR3_DEBUG_EVENT_LISTENER delboy)
776*16467b97STreehugger Robot {
777*16467b97STreehugger Robot transmit(delboy, (const char *)"beginResync\n");
778*16467b97STreehugger Robot }
779*16467b97STreehugger Robot
780*16467b97STreehugger Robot static void
endResync(pANTLR3_DEBUG_EVENT_LISTENER delboy)781*16467b97STreehugger Robot endResync (pANTLR3_DEBUG_EVENT_LISTENER delboy)
782*16467b97STreehugger Robot {
783*16467b97STreehugger Robot transmit(delboy, (const char *)"endResync\n");
784*16467b97STreehugger Robot }
785*16467b97STreehugger Robot
786*16467b97STreehugger Robot static void
semanticPredicate(pANTLR3_DEBUG_EVENT_LISTENER delboy,ANTLR3_BOOLEAN result,const char * predicate)787*16467b97STreehugger Robot semanticPredicate (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate)
788*16467b97STreehugger Robot {
789*16467b97STreehugger Robot unsigned char * buffer;
790*16467b97STreehugger Robot unsigned char * out;
791*16467b97STreehugger Robot
792*16467b97STreehugger Robot if (predicate != NULL)
793*16467b97STreehugger Robot {
794*16467b97STreehugger Robot buffer = (unsigned char *)ANTLR3_MALLOC(64 + 2*strlen(predicate));
795*16467b97STreehugger Robot
796*16467b97STreehugger Robot if (buffer != NULL)
797*16467b97STreehugger Robot {
798*16467b97STreehugger Robot out = buffer + sprintf((char *)buffer, "semanticPredicate\t%s\t", result == ANTLR3_TRUE ? "true" : "false");
799*16467b97STreehugger Robot
800*16467b97STreehugger Robot while (*predicate != '\0')
801*16467b97STreehugger Robot {
802*16467b97STreehugger Robot switch(*predicate)
803*16467b97STreehugger Robot {
804*16467b97STreehugger Robot case '\n':
805*16467b97STreehugger Robot
806*16467b97STreehugger Robot *out++ = '%';
807*16467b97STreehugger Robot *out++ = '0';
808*16467b97STreehugger Robot *out++ = 'A';
809*16467b97STreehugger Robot break;
810*16467b97STreehugger Robot
811*16467b97STreehugger Robot case '\r':
812*16467b97STreehugger Robot
813*16467b97STreehugger Robot *out++ = '%';
814*16467b97STreehugger Robot *out++ = '0';
815*16467b97STreehugger Robot *out++ = 'D';
816*16467b97STreehugger Robot break;
817*16467b97STreehugger Robot
818*16467b97STreehugger Robot case '%':
819*16467b97STreehugger Robot
820*16467b97STreehugger Robot *out++ = '%';
821*16467b97STreehugger Robot *out++ = '0';
822*16467b97STreehugger Robot *out++ = 'D';
823*16467b97STreehugger Robot break;
824*16467b97STreehugger Robot
825*16467b97STreehugger Robot
826*16467b97STreehugger Robot default:
827*16467b97STreehugger Robot
828*16467b97STreehugger Robot *out++ = *predicate;
829*16467b97STreehugger Robot break;
830*16467b97STreehugger Robot }
831*16467b97STreehugger Robot
832*16467b97STreehugger Robot predicate++;
833*16467b97STreehugger Robot }
834*16467b97STreehugger Robot *out++ = '\n';
835*16467b97STreehugger Robot *out++ = '\0';
836*16467b97STreehugger Robot }
837*16467b97STreehugger Robot
838*16467b97STreehugger Robot // Send it and wait for the ack
839*16467b97STreehugger Robot //
840*16467b97STreehugger Robot transmit(delboy, (const char *)buffer);
841*16467b97STreehugger Robot }
842*16467b97STreehugger Robot }
843*16467b97STreehugger Robot
844*16467b97STreehugger Robot #ifdef ANTLR3_WINDOWS
845*16467b97STreehugger Robot #pragma warning (push)
846*16467b97STreehugger Robot #pragma warning (disable : 4100)
847*16467b97STreehugger Robot #endif
848*16467b97STreehugger Robot
849*16467b97STreehugger Robot static void
commence(pANTLR3_DEBUG_EVENT_LISTENER delboy)850*16467b97STreehugger Robot commence (pANTLR3_DEBUG_EVENT_LISTENER delboy)
851*16467b97STreehugger Robot {
852*16467b97STreehugger Robot // Nothing to see here
853*16467b97STreehugger Robot //
854*16467b97STreehugger Robot }
855*16467b97STreehugger Robot
856*16467b97STreehugger Robot #ifdef ANTLR3_WINDOWS
857*16467b97STreehugger Robot #pragma warning (pop)
858*16467b97STreehugger Robot #endif
859*16467b97STreehugger Robot
860*16467b97STreehugger Robot static void
terminate(pANTLR3_DEBUG_EVENT_LISTENER delboy)861*16467b97STreehugger Robot terminate (pANTLR3_DEBUG_EVENT_LISTENER delboy)
862*16467b97STreehugger Robot {
863*16467b97STreehugger Robot // Terminate sequence
864*16467b97STreehugger Robot //
865*16467b97STreehugger Robot sockSend(delboy->socket, "terminate\n", 10); // Send out the command
866*16467b97STreehugger Robot }
867*16467b97STreehugger Robot
868*16467b97STreehugger Robot //----------------------------------------------------------------
869*16467b97STreehugger Robot // Tree parsing events
870*16467b97STreehugger Robot //
871*16467b97STreehugger Robot static void
consumeNode(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE t)872*16467b97STreehugger Robot consumeNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t)
873*16467b97STreehugger Robot {
874*16467b97STreehugger Robot pANTLR3_STRING buffer;
875*16467b97STreehugger Robot
876*16467b97STreehugger Robot buffer = serializeNode (delboy, t);
877*16467b97STreehugger Robot
878*16467b97STreehugger Robot // Now prepend the command
879*16467b97STreehugger Robot //
880*16467b97STreehugger Robot buffer->insert8 (buffer, 0, "consumeNode\t");
881*16467b97STreehugger Robot buffer->addc (buffer, '\n');
882*16467b97STreehugger Robot
883*16467b97STreehugger Robot // Send to the debugger and wait for the ack
884*16467b97STreehugger Robot //
885*16467b97STreehugger Robot transmit (delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars));
886*16467b97STreehugger Robot }
887*16467b97STreehugger Robot
888*16467b97STreehugger Robot static void
LTT(pANTLR3_DEBUG_EVENT_LISTENER delboy,int i,pANTLR3_BASE_TREE t)889*16467b97STreehugger Robot LTT (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t)
890*16467b97STreehugger Robot {
891*16467b97STreehugger Robot pANTLR3_STRING buffer;
892*16467b97STreehugger Robot
893*16467b97STreehugger Robot buffer = serializeNode (delboy, t);
894*16467b97STreehugger Robot
895*16467b97STreehugger Robot // Now prepend the command
896*16467b97STreehugger Robot //
897*16467b97STreehugger Robot buffer->insert8 (buffer, 0, "\t");
898*16467b97STreehugger Robot buffer->inserti (buffer, 0, i);
899*16467b97STreehugger Robot buffer->insert8 (buffer, 0, "LN\t");
900*16467b97STreehugger Robot buffer->addc (buffer, '\n');
901*16467b97STreehugger Robot
902*16467b97STreehugger Robot // Send to the debugger and wait for the ack
903*16467b97STreehugger Robot //
904*16467b97STreehugger Robot transmit (delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars));
905*16467b97STreehugger Robot }
906*16467b97STreehugger Robot
907*16467b97STreehugger Robot static void
nilNode(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE t)908*16467b97STreehugger Robot nilNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t)
909*16467b97STreehugger Robot {
910*16467b97STreehugger Robot char buffer[128];
911*16467b97STreehugger Robot sprintf(buffer, "nilNode\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, t));
912*16467b97STreehugger Robot transmit(delboy, buffer);
913*16467b97STreehugger Robot }
914*16467b97STreehugger Robot
915*16467b97STreehugger Robot static void
createNode(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE t)916*16467b97STreehugger Robot createNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t)
917*16467b97STreehugger Robot {
918*16467b97STreehugger Robot // Do we already have a serialization buffer?
919*16467b97STreehugger Robot //
920*16467b97STreehugger Robot if (delboy->tokenString == NULL)
921*16467b97STreehugger Robot {
922*16467b97STreehugger Robot // No, so create one, using the string factory that
923*16467b97STreehugger Robot // the grammar name used, which is guaranteed to exist.
924*16467b97STreehugger Robot // 64 bytes will do us here for starters.
925*16467b97STreehugger Robot //
926*16467b97STreehugger Robot delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64);
927*16467b97STreehugger Robot }
928*16467b97STreehugger Robot
929*16467b97STreehugger Robot // Empty string
930*16467b97STreehugger Robot //
931*16467b97STreehugger Robot delboy->tokenString->set8(delboy->tokenString, (const char *)"createNodeFromTokenElements ");
932*16467b97STreehugger Robot
933*16467b97STreehugger Robot // Now we serialize the elements of the node.Note that the debugger only
934*16467b97STreehugger Robot // uses 32 bits.
935*16467b97STreehugger Robot //
936*16467b97STreehugger Robot // Adaptor ID
937*16467b97STreehugger Robot //
938*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, t));
939*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
940*16467b97STreehugger Robot
941*16467b97STreehugger Robot // Type of the current token (which may be imaginary)
942*16467b97STreehugger Robot //
943*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getType(delboy->adaptor, t));
944*16467b97STreehugger Robot
945*16467b97STreehugger Robot // The text that this node represents
946*16467b97STreehugger Robot //
947*16467b97STreehugger Robot serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, t));
948*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\n');
949*16467b97STreehugger Robot
950*16467b97STreehugger Robot // Finally, as the debugger is a Java program it will expect to get UTF-8
951*16467b97STreehugger Robot // encoded strings. We don't use UTF-8 internally to the C runtime, so we
952*16467b97STreehugger Robot // must force encode it. We have a method to do this in the string class, but
953*16467b97STreehugger Robot // there is no utf8 string implementation as of yet
954*16467b97STreehugger Robot //
955*16467b97STreehugger Robot transmit(delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars));
956*16467b97STreehugger Robot
957*16467b97STreehugger Robot }
958*16467b97STreehugger Robot static void
errorNode(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE t)959*16467b97STreehugger Robot errorNode (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t)
960*16467b97STreehugger Robot {
961*16467b97STreehugger Robot // Do we already have a serialization buffer?
962*16467b97STreehugger Robot //
963*16467b97STreehugger Robot if (delboy->tokenString == NULL)
964*16467b97STreehugger Robot {
965*16467b97STreehugger Robot // No, so create one, using the string factory that
966*16467b97STreehugger Robot // the grammar name used, which is guaranteed to exist.
967*16467b97STreehugger Robot // 64 bytes will do us here for starters.
968*16467b97STreehugger Robot //
969*16467b97STreehugger Robot delboy->tokenString = delboy->grammarFileName->factory->newSize(delboy->grammarFileName->factory, 64);
970*16467b97STreehugger Robot }
971*16467b97STreehugger Robot
972*16467b97STreehugger Robot // Empty string
973*16467b97STreehugger Robot //
974*16467b97STreehugger Robot delboy->tokenString->set8(delboy->tokenString, (const char *)"errorNode\t");
975*16467b97STreehugger Robot
976*16467b97STreehugger Robot // Now we serialize the elements of the node.Note that the debugger only
977*16467b97STreehugger Robot // uses 32 bits.
978*16467b97STreehugger Robot //
979*16467b97STreehugger Robot // Adaptor ID
980*16467b97STreehugger Robot //
981*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, delboy->adaptor->getUniqueID(delboy->adaptor, t));
982*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\t');
983*16467b97STreehugger Robot
984*16467b97STreehugger Robot // Type of the current token (which is an error)
985*16467b97STreehugger Robot //
986*16467b97STreehugger Robot delboy->tokenString->addi(delboy->tokenString, ANTLR3_TOKEN_INVALID);
987*16467b97STreehugger Robot
988*16467b97STreehugger Robot // The text that this node represents
989*16467b97STreehugger Robot //
990*16467b97STreehugger Robot serializeText(delboy->tokenString, delboy->adaptor->getText(delboy->adaptor, t));
991*16467b97STreehugger Robot delboy->tokenString->addc(delboy->tokenString, '\n');
992*16467b97STreehugger Robot
993*16467b97STreehugger Robot // Finally, as the debugger is a Java program it will expect to get UTF-8
994*16467b97STreehugger Robot // encoded strings. We don't use UTF-8 internally to the C runtime, so we
995*16467b97STreehugger Robot // must force encode it. We have a method to do this in the string class, but
996*16467b97STreehugger Robot // there is no utf8 string implementation as of yet
997*16467b97STreehugger Robot //
998*16467b97STreehugger Robot transmit(delboy, (const char *)(delboy->tokenString->toUTF8(delboy->tokenString)->chars));
999*16467b97STreehugger Robot
1000*16467b97STreehugger Robot }
1001*16467b97STreehugger Robot
1002*16467b97STreehugger Robot static void
createNodeTok(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE node,pANTLR3_COMMON_TOKEN token)1003*16467b97STreehugger Robot createNodeTok (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token)
1004*16467b97STreehugger Robot {
1005*16467b97STreehugger Robot char buffer[128];
1006*16467b97STreehugger Robot
1007*16467b97STreehugger Robot sprintf(buffer, "createNode\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, node), (ANTLR3_UINT32)token->getTokenIndex(token));
1008*16467b97STreehugger Robot
1009*16467b97STreehugger Robot transmit(delboy, buffer);
1010*16467b97STreehugger Robot }
1011*16467b97STreehugger Robot
1012*16467b97STreehugger Robot static void
becomeRoot(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE newRoot,pANTLR3_BASE_TREE oldRoot)1013*16467b97STreehugger Robot becomeRoot (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot)
1014*16467b97STreehugger Robot {
1015*16467b97STreehugger Robot char buffer[128];
1016*16467b97STreehugger Robot
1017*16467b97STreehugger Robot sprintf(buffer, "becomeRoot\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, newRoot),
1018*16467b97STreehugger Robot delboy->adaptor->getUniqueID(delboy->adaptor, oldRoot)
1019*16467b97STreehugger Robot );
1020*16467b97STreehugger Robot transmit(delboy, buffer);
1021*16467b97STreehugger Robot }
1022*16467b97STreehugger Robot
1023*16467b97STreehugger Robot
1024*16467b97STreehugger Robot static void
addChild(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE root,pANTLR3_BASE_TREE child)1025*16467b97STreehugger Robot addChild (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child)
1026*16467b97STreehugger Robot {
1027*16467b97STreehugger Robot char buffer[128];
1028*16467b97STreehugger Robot
1029*16467b97STreehugger Robot sprintf(buffer, "addChild\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, root),
1030*16467b97STreehugger Robot delboy->adaptor->getUniqueID(delboy->adaptor, child)
1031*16467b97STreehugger Robot );
1032*16467b97STreehugger Robot transmit(delboy, buffer);
1033*16467b97STreehugger Robot }
1034*16467b97STreehugger Robot
1035*16467b97STreehugger Robot static void
setTokenBoundaries(pANTLR3_DEBUG_EVENT_LISTENER delboy,pANTLR3_BASE_TREE t,ANTLR3_MARKER tokenStartIndex,ANTLR3_MARKER tokenStopIndex)1036*16467b97STreehugger Robot setTokenBoundaries (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex)
1037*16467b97STreehugger Robot {
1038*16467b97STreehugger Robot char buffer[128];
1039*16467b97STreehugger Robot
1040*16467b97STreehugger Robot sprintf(buffer, "becomeRoot\t%d\t%d\t%d\n", delboy->adaptor->getUniqueID(delboy->adaptor, t),
1041*16467b97STreehugger Robot (ANTLR3_UINT32)tokenStartIndex,
1042*16467b97STreehugger Robot (ANTLR3_UINT32)tokenStopIndex
1043*16467b97STreehugger Robot );
1044*16467b97STreehugger Robot transmit(delboy, buffer);
1045*16467b97STreehugger Robot }
1046*16467b97STreehugger Robot #endif
1047*16467b97STreehugger Robot
1048