This is DebuggerController.m in view mode; [Download] [Up]
#import "DebuggerController_Private.h"
#import <Foundation/Foundation.h>
/* for the kill() call in -interrupt */
#import <sys/types.h>
#import <sys/signal.h>
#import "debug.h"
static DebuggerController *debuggerController;
void
fork_and_start_debugger_controller(GdbManager *gm)
{
(void)[NSRunLoop class]; // workaround: force RunLoop to go thru +initialize
// and setup support for multithreading
debuggerController = [[DebuggerController alloc] init];
[NSThread detachNewThreadSelector: @selector(startController:)
toTarget: debuggerController
withObject: gm];
}
@implementation DebuggerController
- init
{
[super init];
displayProvider = nil;
stdinPFD = nil;
return self;
}
#if 1
- (id) displayProvider
{
return displayProvider;
}
#endif
//
// This is the first method called in the new thread.
// Advertise ourself using the given name for the connection.
// A Gui system, like ProjectBuilder, will be looking for
// us at that name.
//
// Also, create a connection for our local (i.e. same process)
// connection to the GuiGdbManager.
//
// Then go into the runloop and wait for the Gui system to
// give us the DisplayProvider object.
//
- (void) startController: gm
{
NSString *localName;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDistantObject *dP;
gdbManager = (GdbManager <GuiGdbManagerInternal,
GuiGdbManagerExecLock> *)gm;
NSLog(@"Debugger Controller: looking for connection named %@ on host %@",
[gdbManager displayProviderConnectionName],
[gdbManager displayProviderHostName]);
dP = [NSConnection
rootProxyForConnectionWithRegisteredName:[gdbManager displayProviderConnectionName]
host:[gdbManager displayProviderHostName]];
if ([dP conformsToProtocol:@protocol(GuiDisplayProvider2)])
[dP setProtocolForProxy:@protocol(GuiDisplayProvider2)];
else
[dP setProtocolForProxy:@protocol(GuiDisplayProvider)];
displayProviderConnection = [dP connectionForProxy];
displayProvider = (id<GuiDisplayProvider>)[dP retain];
[displayProvider setDebuggerController:self];
localName = [[NSProcessInfo processInfo] globallyUniqueString];
[gdbManager setDebuggerControllerConnectionName:localName];
gdbConnection = [[NSConnection alloc] init];
[gdbConnection setRootObject: self];
[gdbConnection registerName: localName];
DEBUG_PRINT("Dbg Controller: start: exported connections\n");
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(handleConnectionDeath:)
name: NSConnectionDidDieNotification
object: displayProviderConnection];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(handleConnectionDeath:)
name: NSConnectionDidDieNotification
object: gdbConnection];
// This has the side-effect of unblocking the gdbManager.
[gdbManager setDisplayProvider: dP];
[pool release];
[[NSRunLoop currentRunLoop] run];
}
//
// Sent by the gdb thread; tells us to look for
// activity on stdin.
//
- (oneway void) gdbReadyForInput
{
if (stdinPFD == nil) {
stdinPFD = [[NSPosixFileDescriptor alloc]
initWithFileDescriptor:fileno(stdin)];
[stdinPFD monitorFileActivity: NSPosixReadableActivity
delegate: self];
}
else
[stdinPFD monitorFileActivity: NSPosixReadableActivity];
}
// Called from (remote) client of us, e.g. ProjectBuilder
// execute cmd in gdb
- (oneway void) executeCmd:(NSString *)c
withTty:(BOOL)t
withAnnotation:(BOOL)a
{
GdbCmd *cmd;
// send cmd to Gdb
/* copy of command c should not be needed;
work around for DO problems */
cmd = [[GdbCmd alloc] initWithCmd:[c copy]
ofType:GDB_CMD_EXEC
useTty:t
useAnnotation:a];
[gdbManager enqueueCmd:cmd];
}
- (oneway void)executeCmd:(NSString*)c
withTty:(BOOL)tty
withAnnotation:(BOOL)annotation
catchOutput:(BOOL)catch
{
GdbCmd *cmd;
// send cmd to Gdb
/* copy of command c should not be needed;
work around for DO problems */
cmd = [[GdbCmd alloc] initWithCmd:[c copy]
ofType:GDB_CMD_EXEC
useTty:tty
useAnnotation:annotation
catchOutput:catch];
[gdbManager enqueueCmd:cmd];
}
/*
Interrupt; right now, this only interrupts the inferior.
Might want to extend this to interrupt gdb thread someday.
*/
- (oneway void) interrupt
{
extern int inferior_pid;
if (inferior_pid > 0)
kill(inferior_pid, SIGINT);
}
- (void) handleConnectionDeath: (NSNotification *) notification
{
if ([notification object] == displayProviderConnection) {
// client has gone away
}
else {
// gdb connection
}
// FIXME: do a better job of cleanning up
exit(22);
}
@end
// Called when input is pending on stdin
@implementation DebuggerController (NSPosixFileDescriptorDelegateMethods)
- (void) posixFileDescriptor:(NSPosixFileDescriptor *)pfd
currentActivity:(NSPosixFileActivity) activity
{
GdbCmd *cmd;
// turn off monitoring until GDB tells to turn it back on
[pfd monitorFileActivity: NSPosixNoActivity];
// send cmd to Gdb (which will wake it up); gdb will read stdin
cmd = [[GdbCmd alloc] initWithCmd:nil ofType:GDB_CMD_INPUT_PENDING];
[gdbManager enqueueCmd:cmd];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.