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