*/
- (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
- (void)sendQueuedWrites;
- (NSString*)escapedURIPath:(NSString*)path;
+- (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response;
@end
// CFNetwork Callbacks /////////////////////////////////////////////////////////
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]];
}
/**
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);
// 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];
}
}
{
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++)
- (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:|.
// 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];
}
/**
*/
- (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;
return;
frame.source = [[response rootElement] value];
- NSLog(@"frame.source = %@", frame.source);
+
+ if ([delegate respondsToSelector:@selector(sourceUpdated:)])
+ [delegate sourceUpdated:frame];
}
/**
- (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;
- (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;
return urlString;
}
+/**
+ * Returns the transaction_id from an NSXMLDocument.
+ */
+- (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response
+{
+ return [[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue];
+}
+
@end