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
47ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER
48antlr3DebugListenerNew()
49{
50		ANTLR3_PRINTF("C runtime was compiled without debugger support. This program will crash!!");
51		return NULL;
52}
53#else
54
55static	ANTLR3_BOOLEAN	handshake		(pANTLR3_DEBUG_EVENT_LISTENER delboy);
56static	void	enterRule				(pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);
57static	void	enterAlt				(pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt);
58static	void	exitRule				(pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);
59static	void	enterSubRule			(pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
60static	void	exitSubRule				(pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
61static	void	enterDecision			(pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
62static	void	exitDecision			(pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
63static	void	consumeToken			(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);
64static	void	consumeHiddenToken		(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);
65static	void	LT						(pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t);
66static	void	mark					(pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);
67static	void	rewindMark				(pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);
68static	void	rewindLast				(pANTLR3_DEBUG_EVENT_LISTENER delboy);
69static	void	beginBacktrack			(pANTLR3_DEBUG_EVENT_LISTENER delboy, int level);
70static	void	endBacktrack			(pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful);
71static	void	location				(pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos);
72static	void	recognitionException	(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e);
73static	void	beginResync				(pANTLR3_DEBUG_EVENT_LISTENER delboy);
74static	void	endResync				(pANTLR3_DEBUG_EVENT_LISTENER delboy);
75static	void	semanticPredicate		(pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate);
76static	void	commence				(pANTLR3_DEBUG_EVENT_LISTENER delboy);
77static	void	terminate				(pANTLR3_DEBUG_EVENT_LISTENER delboy);
78static	void	consumeNode				(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
79static	void	LTT						(pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t);
80static	void	nilNode					(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
81static	void	errorNode				(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
82static	void	createNode				(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);
83static	void	createNodeTok			(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token);
84static	void	becomeRoot				(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot);
85static	void	addChild				(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child);
86static	void	setTokenBoundaries		(pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex);
87static	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///
92ANTLR3_API pANTLR3_DEBUG_EVENT_LISTENER
93antlr3DebugListenerNew()
94{
95	pANTLR3_DEBUG_EVENT_LISTENER	delboy;
96
97	delboy = 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
146pANTLR3_DEBUG_EVENT_LISTENER
147antlr3DebugListenerNewPort(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//
164static int
165sockSend(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
193static	ANTLR3_BOOLEAN
194handshake				(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 void *)&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
322static void
323transmit(pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * ptr)
324{
325	sockSend(delboy->socket, ptr, (int)strlen(ptr));
326	ack(delboy);
327}
328
329static	void
330ack						(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//
364void
365serializeText(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//
417pANTLR3_STRING
418serializeToken(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//
463pANTLR3_STRING
464serializeNode(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//
547static	void
548enterRule				(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
558static	void
559enterAlt				(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
569static	void
570exitRule				(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
580static	void
581enterSubRule			(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
591static	void
592exitSubRule				(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
602static	void
603enterDecision			(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
614static	void
615exitDecision			(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
625static	void
626consumeToken			(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
645static	void
646consumeHiddenToken		(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//
667static	void
668LT						(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
695static	void
696mark					(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
707static	void
708rewindMark					(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
720static	void
721rewindLast				(pANTLR3_DEBUG_EVENT_LISTENER delboy)
722{
723	transmit(delboy, (const char *)"rewind\n");
724}
725
726static	void
727beginBacktrack			(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
738static	void
739endBacktrack			(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
750static	void
751location				(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
762static	void
763recognitionException	(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
774static	void
775beginResync				(pANTLR3_DEBUG_EVENT_LISTENER delboy)
776{
777	transmit(delboy, (const char *)"beginResync\n");
778}
779
780static	void
781endResync				(pANTLR3_DEBUG_EVENT_LISTENER delboy)
782{
783	transmit(delboy, (const char *)"endResync\n");
784}
785
786static	void
787semanticPredicate		(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
849static	void
850commence				(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
860static	void
861terminate				(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//
871static	void
872consumeNode				(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
888static	void
889LTT						(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
907static	void
908nilNode					(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
915static	void
916createNode				(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}
958static void
959errorNode				(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
1002static	void
1003createNodeTok			(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
1012static	void
1013becomeRoot				(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
1024static	void
1025addChild				(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
1035static	void
1036setTokenBoundaries		(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