From 420eed3a17a6cdabf26d74f4ddb05553b036c1b8 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sun, 21 Feb 2010 11:32:50 -0500 Subject: [PATCH] * Start plumbing data back to the UI now that we're partially working asynchronously * Set up a callback for |-addBreakpoint:| * Create |-transactionIDFromResponse:| helper --- Source/DebuggerController.h | 4 +++ Source/DebuggerController.m | 48 ++++++++++++++++++++------- Source/GDBpConnection.h | 8 +++-- Source/GDBpConnection.m | 66 +++++++++++++++++++++++++++++-------- 4 files changed, 98 insertions(+), 28 deletions(-) diff --git a/Source/DebuggerController.h b/Source/DebuggerController.h index 99ad1db..20fdd05 100644 --- a/Source/DebuggerController.h +++ b/Source/DebuggerController.h @@ -23,6 +23,10 @@ { 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; diff --git a/Source/DebuggerController.m b/Source/DebuggerController.m index 8bfa2c4..00621df 100644 --- a/Source/DebuggerController.m +++ b/Source/DebuggerController.m @@ -254,29 +254,29 @@ */ - (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]; } @@ -353,4 +353,28 @@ [[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 diff --git a/Source/GDBpConnection.h b/Source/GDBpConnection.h index 096a98b..0687432 100644 --- a/Source/GDBpConnection.h +++ b/Source/GDBpConnection.h @@ -70,6 +70,10 @@ // 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 @@ -128,8 +132,8 @@ // 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 diff --git a/Source/GDBpConnection.m b/Source/GDBpConnection.m index a065bc4..e9b9b26 100644 --- a/Source/GDBpConnection.m +++ b/Source/GDBpConnection.m @@ -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 -- 2.22.5