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