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