* Start plumbing data back to the UI now that we're partially working asynchronously
authorRobert Sesek <rsesek@bluestatic.org>
Sun, 21 Feb 2010 16:32:50 +0000 (11:32 -0500)
committerRobert Sesek <rsesek@bluestatic.org>
Sun, 21 Feb 2010 16:32:50 +0000 (11:32 -0500)
* Set up a callback for |-addBreakpoint:|
* Create |-transactionIDFromResponse:| helper

Source/DebuggerController.h
Source/DebuggerController.m
Source/GDBpConnection.h
Source/GDBpConnection.m

index 99ad1dbe7a99d3ef34b6c4f6dbf9c11130e39278..20fdd05558c440dc0b70b49a7f7b42a9ccc6923e 100644 (file)
 {
        GDBpConnection* connection;
        
+       // This is true when the |connection| has told us to clobber. We will do
+       // so upon receipt of the first new stack frame.
+       BOOL aboutToClobber_;
+       
        StackController* stackController;
        IBOutlet NSArrayController* stackArrayController;
        
index 8bfa2c41484d4f647d84dc4d4c98c7f08bd38705..00621df96e80df814395ef315e4d287cffddaa65 100644 (file)
  */
 - (void)updateSourceViewer
 {
-       id selection = [stackArrayController selection];
-       if ([selection valueForKey:@"filename"] == NSNoSelectionMarker)
+       NSArray* selection = [stackArrayController selectedObjects];
+       if (!selection || [selection count] < 1)
                return;
+       if ([selection count] > 1)
+               NSLog(@"INVALID SELECTION");
+       StackFrame* frame = [selection objectAtIndex:0];
        
-       // get the filename
-       NSString* filename = [selection valueForKey:@"filename"];
-       filename = [[NSURL URLWithString:filename] path];
+       // Get the filename.
+       NSString* filename = [[NSURL URLWithString:frame.filename] path];
        if ([filename isEqualToString:@""])
                return;
        
-       // replace the source if necessary
-       if (![sourceViewer.file isEqualToString:filename])
+       // Replace the source if necessary.
+       if (frame.source && ![sourceViewer.file isEqualToString:filename])
        {
-               NSString* source = [selection valueForKey:@"source"];
-               [sourceViewer setString:source asFile:filename];
+               [sourceViewer setString:frame.source asFile:filename];
                
                NSSet* breakpoints = [NSSet setWithArray:[[BreakpointManager sharedManager] breakpointsForFile:filename]];
                [[sourceViewer numberView] setMarkers:breakpoints];
        }
        
-       int line = [[selection valueForKey:@"lineNumber"] intValue];
-       [sourceViewer setMarkedLine:line];
-       [sourceViewer scrollToLine:line];
+       [sourceViewer setMarkedLine:frame.lineNumber];
+       [sourceViewer scrollToLine:frame.lineNumber];
        
        [[sourceViewer textView] display];
 }
        [[sourceViewer numberView] setNeedsDisplay:YES];
 }
 
+#pragma mark GDBpConnectionDelegate
+
+- (void)clobberStack
+{
+       aboutToClobber_ = YES;
+}
+
+- (void)newStackFrame:(StackFrame*)frame
+{
+       if (aboutToClobber_)
+       {
+               [stackController.stack removeAllObjects];
+               aboutToClobber_ = NO;
+       }
+       [stackController push:frame];
+       [self updateStackViewer];
+       [self updateSourceViewer];
+}
+
+- (void)sourceUpdated:(StackFrame*)frame
+{
+       [self updateSourceViewer];
+}
+
 @end
index 096a98b4b422cacda2916d4820f2100bf934d706..068743234e3fd965e5c4bb7c2c7493ea18b12ef6 100644 (file)
        
        // A dictionary that maps routingIDs to StackFrame objects.
        NSMutableDictionary* stackFrames_;
+       // The stack depth for the current build of |stackFrames_|.
+       NSInteger stackDepth_;
+       // The earliest transaction ID for the current build of |stackFrames_|.
+       NSInteger stackFirstTransactionID_;
        
        // Callback table. This maps transaction IDs to selectors. When the engine
        // returns a response to the debugger, we will dispatch the response XML to
 // Tells the debugger that a new stack frame is avaliable.
 - (void)newStackFrame:(StackFrame*)frame;
 
-// A simple step has occurred. Pop the top frame the new current one is provided.
-- (void)popStackFrame:(StackFrame*)frame;
+// Tells the debugger that new source is available for the given frame.
+- (void)sourceUpdated:(StackFrame*)frame;
 
 @end
 
index a065bc4c8fec3224bb534cb75c65204f7bb97d7e..e9b9b2692701ee09926e3d3beb3ca13cb556a7f8 100644 (file)
@@ -57,6 +57,7 @@
 - (void)sendQueuedWrites;
 
 - (NSString*)escapedURIPath:(NSString*)path;
+- (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response;
 @end
 
 // CFNetwork Callbacks /////////////////////////////////////////////////////////
@@ -375,10 +376,23 @@ void SocketAcceptCallback(CFSocketRef socket,
                return;
        
        NSString* file = [self escapedURIPath:[bp transformedPath]];
-       NSString* cmd = [self createCommand:[NSString stringWithFormat:@"breakpoint_set -t line -f %@ -n %i", file, [bp line]]];
-       [socket send:cmd];
-       NSXMLDocument* info = [self processData:[socket receive]];
-       [bp setDebuggerId:[[[[info rootElement] attributeForName:@"id"] stringValue] intValue]];
+       NSNumber* transaction = [self sendCommandWithCallback:@selector(breakpointReceived:)
+                                                                                                  format:@"breakpoint_set -t line -f %@ -n %i", file, [bp line]];
+       [callbackContext_ setObject:bp forKey:transaction];
+}
+
+/**
+ * Callback for setting a breakpoint.
+ */
+- (void)breakpointReceived:(NSXMLDocument*)response
+{
+       NSNumber* transaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]];
+       Breakpoint* bp = [callbackContext_ objectForKey:transaction];
+       if (!bp)
+               return;
+       
+       [callbackContext_ removeObjectForKey:callbackContext_];
+       [bp setDebuggerId:[[[[response rootElement] attributeForName:@"id"] stringValue] intValue]];
 }
 
 /**
@@ -611,7 +625,7 @@ void SocketAcceptCallback(CFSocketRef socket,
                NSLog(@"<-- %@", response);
        
        // Get the name of the command from the engine's response.
-       NSInteger transaction = [[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue];
+       NSInteger transaction = [self transactionIDFromResponse:response];
        if (transaction < lastReadTransaction_)
                NSLog(@"out of date transaction %@", response);
        
@@ -682,9 +696,10 @@ void SocketAcceptCallback(CFSocketRef socket,
        // TODO: figure out if we can not clobber the stack every time.
        if (YES || [command isEqualToString:@"run"])
        {
-               //[delegate clobberStack];
+               if ([delegate respondsToSelector:@selector(clobberStack)])
+                       [delegate clobberStack];
                [stackFrames_ removeAllObjects];
-               [self sendCommandWithCallback:@selector(rebuildStack:) format:@"stack_depth"];
+               stackFirstTransactionID_ = [[self sendCommandWithCallback:@selector(rebuildStack:) format:@"stack_depth"] intValue];
        }
 }
 
@@ -696,6 +711,9 @@ void SocketAcceptCallback(CFSocketRef socket,
 {
        NSInteger depth = [[[[response rootElement] attributeForName:@"depth"] stringValue] intValue];
        
+       if (stackFirstTransactionID_ == [self transactionIDFromResponse:response])
+               stackDepth_ = depth;
+       
        // We now need to alloc a bunch of stack frames and get the basic information
        // for them.
        for (NSInteger i = 0; i < depth; i++)
@@ -713,7 +731,9 @@ void SocketAcceptCallback(CFSocketRef socket,
 - (void)getStackFrame:(NSXMLDocument*)response
 {
        // Get the routing information.
-       NSUInteger routingID = [[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue];
+       NSInteger routingID = [self transactionIDFromResponse:response];
+       if (routingID < stackFirstTransactionID_)
+               return;
        NSNumber* routingNumber = [NSNumber numberWithInt:routingID];
        
        // Make sure we initialized this frame in our last |-rebuildStack:|.
@@ -739,6 +759,9 @@ void SocketAcceptCallback(CFSocketRef socket,
        // Get the names of all the contexts.
        transaction = [self sendCommandWithCallback:@selector(contextsReceived:) format:@"context_names -d %d", frame.index];
        [callbackContext_ setObject:routingNumber forKey:transaction];
+       
+       if ([delegate respondsToSelector:@selector(newStackFrame:)])
+               [delegate newStackFrame:frame];
 }
 
 /**
@@ -747,7 +770,9 @@ void SocketAcceptCallback(CFSocketRef socket,
  */
 - (void)setSource:(NSXMLDocument*)response
 {
-       NSNumber* transaction = [NSNumber numberWithInt:[[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue]];
+       NSNumber* transaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]];
+       if ([transaction intValue] < stackFirstTransactionID_)
+               return;
        NSNumber* routingNumber = [callbackContext_ objectForKey:transaction];
        if (!routingNumber)
                return;
@@ -758,7 +783,9 @@ void SocketAcceptCallback(CFSocketRef socket,
                return;
        
        frame.source = [[response rootElement] value];
-       NSLog(@"frame.source = %@", frame.source);
+       
+       if ([delegate respondsToSelector:@selector(sourceUpdated:)])
+               [delegate sourceUpdated:frame];
 }
 
 /**
@@ -768,8 +795,9 @@ void SocketAcceptCallback(CFSocketRef socket,
 - (void)contextsReceived:(NSXMLDocument*)response
 {
        // Get the stack frame's routing ID and use it again.
-       NSNumber* receivedTransaction =
-               [NSNumber numberWithInt:[[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue]];
+       NSNumber* receivedTransaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]];
+       if ([receivedTransaction intValue] < stackFirstTransactionID_)
+               return;
        NSNumber* routingID = [callbackContext_ objectForKey:receivedTransaction];
        if (!routingID)
                return;
@@ -795,8 +823,10 @@ void SocketAcceptCallback(CFSocketRef socket,
 - (void)variablesReceived:(NSXMLDocument*)response
 {
        // Get the stack frame's routing ID and use it again.
-       NSNumber* receivedTransaction =
-       [NSNumber numberWithInt:[[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue]];
+       NSInteger transaction = [self transactionIDFromResponse:response];
+       if (transaction < stackFirstTransactionID_)
+               return;
+       NSNumber* receivedTransaction = [NSNumber numberWithInt:transaction];
        NSNumber* routingID = [callbackContext_ objectForKey:receivedTransaction];
        if (!routingID)
                return;
@@ -889,4 +919,12 @@ void SocketAcceptCallback(CFSocketRef socket,
        return urlString;
 }
 
+/**
+ * Returns the transaction_id from an NSXMLDocument.
+ */
+- (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response
+{
+       return [[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue];
+}
+
 @end