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 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 93 antlr3DebugListenerNew() 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 146 pANTLR3_DEBUG_EVENT_LISTENER 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 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 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 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 322 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 721 rewindLast (pANTLR3_DEBUG_EVENT_LISTENER delboy) 722 { 723 transmit(delboy, (const char *)"rewind\n"); 724 } 725 726 static void 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 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 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 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 775 beginResync (pANTLR3_DEBUG_EVENT_LISTENER delboy) 776 { 777 transmit(delboy, (const char *)"beginResync\n"); 778 } 779 780 static void 781 endResync (pANTLR3_DEBUG_EVENT_LISTENER delboy) 782 { 783 transmit(delboy, (const char *)"endResync\n"); 784 } 785 786 static void 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 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 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 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 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 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 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 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 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 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 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 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