This is GdbDisplayController.m in view mode; [Download] [Up]
/* GdbDisplayController.m created by ovidiu on Wed 19-Mar-1997 */
#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <AppKit/NSWindow.h>
#import <AppKit/NSBrowser.h>
#import "GdbDisplayController.h"
#import "../Document.h"
#import "DebuggerController_Protocol.h"
#import "Stack.h"
#import "Frame.h"
#import "Variable.h"
#import "GdbBrowserCell.h"
#import "FrameBrowserCell.h"
/* Private class used to store an object and a selector */
@interface ObjectSelector : NSObject
{
id object;
SEL selector;
}
+ (ObjectSelector*)newWithObject:(id)anObject selector:(SEL)aSelector;
- (void)invokeWithArg:(id)gdbOutput type:(GdbOutputType)outputType;
@end
@implementation ObjectSelector
+ (ObjectSelector*)newWithObject:(id)anObject selector:(SEL)aSelector
{
ObjectSelector* obj = [[self new] autorelease];
obj->object = [anObject retain];
obj->selector = aSelector;
return obj;
}
- (void)dealloc
{
[object release];
[super dealloc];
}
- (void)invokeWithArg:(id)gdbOutput type:(GdbOutputType)outputType
{
IMP imp = [object methodForSelector:selector];
// NSLog (@"%@ output = %@", NSStringFromSelector (_cmd), gdbOutput);
(*((void (*)(id, SEL, id, GdbOutputType))imp))
(object, selector, gdbOutput, outputType);
}
@end
@implementation GdbDisplayController
static NSString* stackBrowserFrameName = @"Stack Browser Window";
static NSString* selectionMatrixFrameName = @"Gdb Controller Window";
- init
{
self = [super init];
stack = [Stack new];
[stack setGdbController:self];
objectsToBeNotified = [NSMutableArray new];
currentFrame = -1;
return self;
}
- (void)awakeFromNib
{
NSWindow* stackBrowserWindow = [stackBrowser window];
NSWindow* selectionMatrixWindow = [selectionMatrix window];
NSString* frameString;
NSLog (@"awakeFromNib");
[stackBrowserWindow setFrameAutosaveName:stackBrowserFrameName];
[selectionMatrixWindow setFrameAutosaveName:selectionMatrixFrameName];
#if 0
frameString = [stackBrowserWindow stringWithSavedFrame];
if (frameString)
[[stackBrowser window] setFrameFromString:frameString];
NSLog (@"frame1 = %@", frameString);
frameString = [selectionMatrixWindow stringWithSavedFrame];
if (frameString)
[[selectionMatrix window] setFrameFromString:frameString];
NSLog (@"frame2 = %@/n", frameString);
#endif
}
- (void)dealloc
{
[stack release];
[objectsToBeNotified release];
[super dealloc];
}
/* GuiDisplayProvider2 protocol methods */
- (oneway void) setDebuggerController:(id)dC
{
gdbManager = [dC retain];
[gdbManager executeCmd:@"set print repeats 0"
withTty:YES
withAnnotation:NO
catchOutput:NO];
[gdbManager executeCmd:@"set print elements 0"
withTty:YES
withAnnotation:NO
catchOutput:NO];
}
- (oneway void) breakpointChanged:(int)bpNum
newState:(BreakpointState)state
inFile:(NSString *)fileName
atLine:(int)lineNumber
{
// NSLog (@"%@: bkpNum %d, file %@, line %d",
// NSStringFromSelector(_cmd), bpNum, fileName, lineNumber);
}
- (oneway void) frameChanged:(int)newFrame
{
// NSLog (@"frameChanged: newFrame %d", newFrame);
[stackBrowser selectRow:[self browserCellForFrame:newFrame] inColumn:0];
currentFrame = newFrame;
}
- (void)executeGDBCommand:(NSString*)command
annotate:(BOOL)flag
notifyObject:object
selector:(SEL)selector
{
[gdbManager executeCmd:command
withTty:YES
withAnnotation:flag
catchOutput:YES];
/* Disable all the buttons until we receive the backtrace result */
[self disableAllButtons];
/* Queue the object and selector. The GDB commands are executed in FIFO
order, when GDB sends outputFromGDB:type: the first object in array is
dequeued. */
[objectsToBeNotified addObject:
[ObjectSelector newWithObject:object selector:selector]];
}
- (oneway void) stackChanged:(int)newSize limitReached:(BOOL)maxedOut
{
// NSLog (@"%@", NSStringFromSelector(_cmd));
[self executeGDBCommand:@"backtrace"
annotate:YES
notifyObject:stack
selector:@selector(createStackFromGdbBacktrace:type:)];
[stackBrowser selectRow:[[stackBrowser matrixInColumn:0] numberOfRows] - 1
inColumn:0];
}
- (oneway void) lineChangedForThread:(int) t
inFile:(NSString *)f
atStartLine:(int)sl
toEndLine:(int)el
{
// NSLog (@"lineChangedForThread: file = %@, line = %d", f, sl);
[self selectInFile:f startLine:sl endLine:el];
if (currentFrame >= 0) {
[[[stack frames] objectAtIndex:currentFrame]
setFilename:f startLine:sl endLine:el];
[stackBrowser selectRow:[self browserCellForFrame:currentFrame]
inColumn:0];
}
}
- (oneway void) inferiorStateChanged:(DebuggerState) newState
{
#if 0
NSString* states[] = {
@"DBG_STATE_NOT_ACTIVE",
@"DBG_STATE_ACTIVE",
@"DBG_STATE_INFERIOR_LOADED",
@"DBG_STATE_INFERIOR_EXITED",
@"DBG_STATE_INFERIOR_LOGICALLY_RUNNING",
@"DBG_STATE_INFERIOR_RUNNING",
@"DBG_STATE_INFERIOR_STOPPED"
};
NSLog (@"inferiorStateChanged: %@", states[newState]);
#endif
debuggerState = newState;
[self setButtonsConformingToState:newState];
}
- (int)query:(NSString*)queryString
{
// NSLog (@"%@", NSStringFromSelector (_cmd));
return 0;
}
- (oneway void) outputFromGDB:(NSString*)output
type:(GdbOutputType)outputType
{
id invoke = [objectsToBeNotified objectAtIndex:0];
[invoke invokeWithArg:output type:outputType];
/* Remove the invocation object when all the output has been received.
The message with GDB_OUTPUT_ANNOTATION as argument must be the last
message sent by GDB. */
if (outputType == GDB_OUTPUT_ANNOTATION)
[objectsToBeNotified removeObjectAtIndex:0];
/* If all the commands sent to GDB have been executed display the state */
if (![objectsToBeNotified count])
[self setButtonsConformingToState:debuggerState];
}
/* Our methods */
- (void)display:sender
{
[[selectionMatrix window] makeKeyAndOrderFront:nil];
}
- (void)close
{
[[selectionMatrix window] orderOut:nil];
[[stackBrowser window] orderOut:nil];
}
- (void)setButtonsConformingToState:(DebuggerState)state
{
switch (state) {
case DBG_STATE_NOT_ACTIVE:
case DBG_STATE_ACTIVE:
[runButton setEnabled:NO];
[stopButton setEnabled:NO];
[quitButton setEnabled:NO];
[execCmdMatrix setEnabled:NO];
[lineMatrix setEnabled:NO];
[selectionMatrix setEnabled:NO];
break;
case DBG_STATE_INFERIOR_LOADED:
case DBG_STATE_INFERIOR_EXITED:
[runButton setEnabled:YES];
[stopButton setEnabled:NO];
[quitButton setEnabled:YES];
[execCmdMatrix setEnabled:NO];
[lineMatrix setEnabled:YES];
[selectionMatrix setEnabled:NO];
break;
case DBG_STATE_INFERIOR_STOPPED:
case DBG_STATE_INFERIOR_LOGICALLY_RUNNING:
[runButton setEnabled:YES];
[stopButton setEnabled:NO];
[quitButton setEnabled:YES];
[execCmdMatrix setEnabled:YES];
[lineMatrix setEnabled:YES];
[selectionMatrix setEnabled:YES];
break;
case DBG_STATE_INFERIOR_RUNNING:
[runButton setEnabled:NO];
[stopButton setEnabled:YES];
[quitButton setEnabled:NO];
[execCmdMatrix setEnabled:NO];
[lineMatrix setEnabled:NO];
[selectionMatrix setEnabled:NO];
break;
}
}
- (void)disableAllButtons
{
[self setButtonsConformingToState:DBG_STATE_NOT_ACTIVE];
}
/* Outlet methods */
- (void)run:sender
{
int start = YES;
if ((debuggerState == DBG_STATE_INFERIOR_STOPPED
|| debuggerState == DBG_STATE_INFERIOR_LOGICALLY_RUNNING)
&& !NSRunAlertPanel (@"Warning", @"Program is running. Do you really "
@"want to restart it?", @"Yes", @"No", NULL))
start = NO;
if (start) {
[gdbManager executeCmd:@"set confirm off" withTty:YES withAnnotation:NO];
[gdbManager executeCmd:@"run" withTty:YES withAnnotation:NO];
[gdbManager executeCmd:@"set confirm on" withTty:YES withAnnotation:NO];
}
}
- (void)interrupt:sender
{
[gdbManager interrupt];
}
- (void)quit:sender
{
int quit = YES;
if ((debuggerState == DBG_STATE_INFERIOR_STOPPED
|| debuggerState == DBG_STATE_INFERIOR_LOGICALLY_RUNNING)
&& !NSRunAlertPanel (@"Warning", @"Program is running. Do you really "
@"want to quit?", @"Yes", @"No", NULL))
quit = NO;
if (quit) {
[gdbManager executeCmd:@"set confirm off" withTty:YES withAnnotation:NO];
[gdbManager executeCmd:@"quit" withTty:YES withAnnotation:NO];
// [[stackBrowser window] saveFrameUsingName:stackBrowserFrameName];
// [[selectionMatrix window] saveFrameUsingName:selectionMatrixFrameName];
[[stackBrowser window] setFrameUsingName:[[stackBrowser window] stringWithSavedFrame]];
[[selectionMatrix window] setFrameUsingName:[[selectionMatrix window] stringWithSavedFrame]];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog (@"stack frame %@", NSStringFromRect([[stackBrowser window] frame]));
NSLog (@"matrix frame %@", NSStringFromRect([[selectionMatrix window] frame]));
}
}
- (void)continue:sender
{
[gdbManager executeCmd:@"continue" withTty:YES withAnnotation:NO];
}
- (void)step:sender
{
[gdbManager executeCmd:@"step" withTty:YES withAnnotation:NO];
}
- (void)finish:sender
{
[gdbManager executeCmd:@"finish" withTty:YES withAnnotation:NO];
}
- (void)next:sender
{
[gdbManager executeCmd:@"next" withTty:YES withAnnotation:NO];
[self invalidateCurrentFrameVariables];
}
- (void)breakAt:sender
{
Document* document = [Document currentDocument];
int line;
NSString* command;
[document getStartLine:&line endLine:NULL];
command = [NSString stringWithFormat:@"future-break %@:%d",
[[document documentName] lastPathComponent], line];
[gdbManager executeCmd:command withTty:YES withAnnotation:NO];
}
- (void)runUntil:sender
{
Document* document = [Document currentDocument];
int line;
NSString* command;
[document getStartLine:&line endLine:NULL];
command = [NSString stringWithFormat:@"until %@:%d",
[[document documentName] lastPathComponent], line];
[gdbManager executeCmd:command withTty:YES withAnnotation:NO];
}
- (void)print:sender
{
Document* document = [Document currentDocument];
NSString* selection = [document selection];
NSString* command = [NSString stringWithFormat:@"print %@", selection];
[gdbManager executeCmd:command withTty:YES withAnnotation:NO];
}
- (void)printIndirect:sender
{
Document* document = [Document currentDocument];
NSString* selection = [document selection];
NSString* command = [NSString stringWithFormat:@"print *(%@)", selection];
[gdbManager executeCmd:command withTty:YES withAnnotation:NO];
}
- (void)showStackFrameWindow:sender
{
[stackBrowser loadColumnZero];
[[stackBrowser window] makeKeyAndOrderFront:nil];
}
/* Browser delegate methods */
- (void)browser:(NSBrowser*)sender
createRowsForColumn:(int)column
inMatrix:(NSMatrix*)matrix
{
int i, count = 0;
if (column == 0) {
NSArray* frames = [stack frames];
Frame* frame;
FrameBrowserCell* cell;
[matrix setPrototype:[[FrameBrowserCell new] autorelease]];
for (i = 0, count = [[stack frames] count]; i < count; i++) {
[matrix addRow];
cell = [matrix cellAtRow:i column:0];
frame = [frames objectAtIndex:[self frameNumberForBrowserCell:i]];
[cell setStringValue:[frame functionName]];
[cell setLeaf:([frame fileName] == nil)];
[cell setFrame:frame];
[cell setTarget:cell];
[cell setAction:@selector(_selectLineInFile:)];
[cell setTag:i];
}
}
else if (column == 1) {
int frameNumber = [self frameNumberForBrowserCell:[sender selectedRowInColumn:0]];
Frame* frame = [[stack frames] objectAtIndex:frameNumber];
id cell;
[matrix setPrototype:[[GdbBrowserCell new] autorelease]];
[stack setSelectedFrame:frameNumber];
if ([frame variablesAreValid]) {
count = [frame numberOfVariables];
for (i = 0; i < count; i++) {
[matrix addRow];
cell = [matrix cellAtRow:i column:0];
[cell setObjectToDisplay:[frame variableAtIndex:i]];
}
}
else
[frame getVariablesFromGDB];
}
else if (column > 1) {
int frameNumber = [self frameNumberForBrowserCell:[sender selectedRowInColumn:0]];
Frame* frame = [[stack frames] objectAtIndex:frameNumber];
id displayableObject;
NSArray* components;
int i, count, index;
[matrix setPrototype:[[GdbBrowserCell new] autorelease]];
[stack setSelectedFrame:frameNumber];
index = [[sender matrixInColumn:1] selectedRow];
displayableObject = [frame variableAtIndex:index];
/* Determine the indirected variable we must show */
for (i = 2; i < column; i++) {
index = [[sender matrixInColumn:i] selectedRow];
displayableObject = [[displayableObject indirectedComponents] objectAtIndex:index];
}
/* Now we have the variable we have to display. If its indirected value is
known already display them, otherwise issue a query to gdb to get them.
*/
if ([displayableObject indirectedComponentsAreKnown]) {
BOOL displayableObjectIsArray
= [[displayableObject value] isKindOfClass:[ArrayValue class]];
id cell;
components = [displayableObject indirectedComponents];
count = [components count];
for (i = 0; i < count; i++) {
[matrix addRow];
cell = [matrix cellAtRow:i column:0];
[cell setObjectToDisplay:[components objectAtIndex:i]];
[cell setObjectIsArrayComponent:displayableObjectIsArray];
}
}
else
[displayableObject getIndirectedComponentsFromGDB];
}
}
- (int)frameNumberForBrowserCell:(int)row
{
return [[stack frames] count] - row - 1;
}
- (int)browserCellForFrame:(int)frameNumber
{
return [[stack frames] count] - frameNumber - 1;
}
/* Changing the appearence of stack browser */
- (void)stackChanged
{
[stackBrowser loadColumnZero];
}
- (void)updateCurrentFrame
{
[stackBrowser reloadColumn:[stackBrowser lastColumn]];
}
/* Other methods */
- (id)gdbManager { return gdbManager; }
- (id)stackBrowser { return stackBrowser; }
- (void)selectInFile:(NSString*)file startLine:(int)sl endLine:(int)el
{
Document* document;
if ([Document openDocumentWithPath:file encoding:UnknownStringEncoding]) {
document = [Document documentForPath:file];
[document selectFromLine:sl toEndLine:el];
[document jumpToSelection:nil];
}
}
- (void)invalidateCurrentFrameVariables
{
int selectedRow, frameNumber;
if ((selectedRow = [stackBrowser selectedRowInColumn:0]) >= 0) {
frameNumber = [self frameNumberForBrowserCell:selectedRow];
[[[stack frames] objectAtIndex:frameNumber]
invalidateCurrentVariables];
[self updateCurrentFrame];
}
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.