mirror of
https://github.com/gnustep/apps-projectcenter.git
synced 2025-03-18 16:41:35 +00:00
* Modules/Debuggers/ProjectCenter/GNUmakefile: Added PTYView.[hm]
* Modules/Debuggers/ProjectCenter/PCDebugger.[hm]: Simplified to call PCDebuggerView instance with the program to start. * Modules/Debuggers/ProjectCenter/PCDebuggerView.[hm]: Refactored into a subclass of PTYView. * Modules/Debuggers/ProjectCenter/PTYView.[hm]: pty based terminal view which allows us to read and write from a pseudo-terminal. The code in the master/slave methods was inspired by an example given in "UNIX Network Programming" by W. Richard Stevens and also Nicola Vitacolonna. * Modules/Debuggers/ProjectCenter/Resources/PCDebugger.gorm: Added PTYView and made the PCDebuggerView a subclass of it. Also made the window release when closed so that the gdb process gets terminated. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/projectcenter/trunk@27416 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cd2924d9ab
commit
43e24cad84
10 changed files with 550 additions and 245 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2008-12-25 10:30-EST Gregory John Casamento <greg_casamento@yahoo.com>
|
||||
|
||||
* Modules/Debuggers/ProjectCenter/GNUmakefile: Added PTYView.[hm]
|
||||
* Modules/Debuggers/ProjectCenter/PCDebugger.[hm]: Simplified to
|
||||
call PCDebuggerView instance with the program to start.
|
||||
* Modules/Debuggers/ProjectCenter/PCDebuggerView.[hm]: Refactored
|
||||
into a subclass of PTYView.
|
||||
* Modules/Debuggers/ProjectCenter/PTYView.[hm]: pty based terminal
|
||||
view which allows us to read and write from a pseudo-terminal.
|
||||
The code in the master/slave methods was inspired by an example
|
||||
given in "UNIX Network Programming" by W. Richard Stevens and also
|
||||
Nicola Vitacolonna.
|
||||
* Modules/Debuggers/ProjectCenter/Resources/PCDebugger.gorm: Added
|
||||
PTYView and made the PCDebuggerView a subclass of it. Also made
|
||||
the window release when closed so that the gdb process gets
|
||||
terminated.
|
||||
|
||||
2008-12-22 21:51-EST Gregory John Casamento <greg_casamento@yahoo.com>
|
||||
|
||||
* Modules/Debuggers/ProjectCenter/PCDebugger.m: Write to
|
||||
|
|
|
@ -27,14 +27,16 @@ ProjectCenter_RESOURCE_FILES= \
|
|||
#
|
||||
ProjectCenter_HEADERS= \
|
||||
PCDebugger.h \
|
||||
PCDebugggerView.h
|
||||
PCDebugggerView.h \
|
||||
PTYView.h
|
||||
|
||||
#
|
||||
# Class files
|
||||
#
|
||||
ProjectCenter_OBJC_FILES= \
|
||||
PCDebugger.m \
|
||||
PCDebuggerView.m
|
||||
PCDebuggerView.m \
|
||||
PTYView.m
|
||||
|
||||
include ../../GNUmakefile.bundles
|
||||
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
/* All Rights reserved */
|
||||
/*
|
||||
** PCDebugger
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -13,17 +33,8 @@
|
|||
id debuggerWindow;
|
||||
NSString *path;
|
||||
NSString *debuggerPath;
|
||||
NSTask *debuggerTask;
|
||||
NSPipe *standardInput;
|
||||
NSPipe *standardOutput;
|
||||
NSPipe *standardError;
|
||||
NSFileHandle *readHandle;
|
||||
NSFileHandle *errorReadHandle;
|
||||
BOOL _isLogging;
|
||||
BOOL _isErrorLogging;
|
||||
FILE *stdInStream;
|
||||
// BOOL _isLogging;
|
||||
// BOOL _isErrorLogging;
|
||||
// FILE *std_input;
|
||||
}
|
||||
|
||||
- (void)putChar:(unichar)ch;
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
/* All Rights reserved */
|
||||
/*
|
||||
** PCDebugger
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "PCDebugger.h"
|
||||
|
@ -25,7 +45,7 @@
|
|||
}
|
||||
|
||||
-(void) debugExecutableAtPath: (NSString *)filePath
|
||||
withDebugger: (NSString *)debugger
|
||||
withDebugger: (NSString *)debugger
|
||||
{
|
||||
ASSIGN(path,filePath);
|
||||
ASSIGN(debuggerPath,debugger);
|
||||
|
@ -39,210 +59,18 @@
|
|||
[self startDebugger];
|
||||
}
|
||||
|
||||
- (void)logErrorString:(NSString *)string
|
||||
{
|
||||
/*
|
||||
NSArray *items;
|
||||
|
||||
items = [self parseErrorLine:string];
|
||||
if (items)
|
||||
{
|
||||
[errorArray addObjectsFromArray:items];
|
||||
[errorOutput reloadData];
|
||||
[errorOutput scrollRowToVisible:[errorArray count]-1];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
- (void)logString:(NSString *)str
|
||||
error:(BOOL)yn
|
||||
newLine:(BOOL)newLine
|
||||
{
|
||||
NSTextView *out = debuggerView;
|
||||
|
||||
[out replaceCharactersInRange:
|
||||
NSMakeRange([[out string] length],0) withString:str];
|
||||
|
||||
if (newLine)
|
||||
{
|
||||
[out replaceCharactersInRange:
|
||||
NSMakeRange([[out string] length], 0) withString:@"\n"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[out replaceCharactersInRange:
|
||||
NSMakeRange([[out string] length], 0) withString:@" "];
|
||||
}
|
||||
|
||||
[out scrollRangeToVisible:NSMakeRange([[out string] length], 0)];
|
||||
[out setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)logData:(NSData *)data
|
||||
error:(BOOL)yn
|
||||
{
|
||||
NSString *dataString;
|
||||
// NSRange newLineRange;
|
||||
// NSRange lineRange;
|
||||
// NSString *lineString;
|
||||
|
||||
dataString = [[NSString alloc]
|
||||
initWithData:data
|
||||
encoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
// Process new data
|
||||
/*
|
||||
lineRange.location = 0;
|
||||
[errorString appendString:dataString];
|
||||
while (newLineRange.location != NSNotFound)
|
||||
{
|
||||
newLineRange = [errorString rangeOfString:@"\n"];
|
||||
if (newLineRange.location < [errorString length])
|
||||
{
|
||||
lineRange.length = newLineRange.location+1;
|
||||
lineString = [errorString substringWithRange:lineRange];
|
||||
[errorString deleteCharactersInRange:lineRange];
|
||||
|
||||
// [self parseBuildLine:lineString];
|
||||
// if (yn)
|
||||
// {
|
||||
// [self logErrorString:lineString];
|
||||
// }
|
||||
|
||||
[self logString:lineString error:yn newLine:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
newLineRange.location = NSNotFound;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
[self logString:dataString error:yn newLine:NO];
|
||||
|
||||
RELEASE(dataString);
|
||||
}
|
||||
|
||||
- (void)logStdOut:(NSNotification *)aNotif
|
||||
{
|
||||
NSData *data;
|
||||
|
||||
if ((data = [readHandle availableData]) && [data length] > 0)
|
||||
{
|
||||
[self logData:data error:NO];
|
||||
}
|
||||
|
||||
if (debuggerTask)
|
||||
{
|
||||
[readHandle waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
else
|
||||
{
|
||||
_isLogging = NO;
|
||||
[NOTIFICATION_CENTER removeObserver:self
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:readHandle];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logErrOut:(NSNotification *)aNotif
|
||||
{
|
||||
NSData *data;
|
||||
|
||||
if ((data = [errorReadHandle availableData]) && [data length] > 0)
|
||||
{
|
||||
[self logData:data error:YES];
|
||||
}
|
||||
|
||||
if (debuggerTask)
|
||||
{
|
||||
[errorReadHandle waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
else
|
||||
{
|
||||
_isErrorLogging = NO;
|
||||
[NOTIFICATION_CENTER removeObserver:self
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:errorReadHandle];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) startDebugger
|
||||
{
|
||||
int descriptor = 0;
|
||||
|
||||
standardInput = [NSPipe pipe];
|
||||
standardOutput = [NSPipe pipe];
|
||||
standardError = [NSPipe pipe];
|
||||
|
||||
descriptor = [[standardInput fileHandleForWriting] fileDescriptor];
|
||||
stdInStream = fdopen(descriptor, "w");
|
||||
|
||||
readHandle = [standardOutput fileHandleForReading];
|
||||
[readHandle waitForDataInBackgroundAndNotify];
|
||||
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(logStdOut:)
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:readHandle];
|
||||
|
||||
_isLogging = YES;
|
||||
standardError = [NSPipe pipe];
|
||||
errorReadHandle = [standardError fileHandleForReading];
|
||||
[errorReadHandle waitForDataInBackgroundAndNotify];
|
||||
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(logErrOut:)
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:errorReadHandle];
|
||||
_isErrorLogging = YES;
|
||||
|
||||
// [statusField setStringValue:buildStatus];
|
||||
|
||||
// Run make task
|
||||
[debuggerView setString:@""];
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(debuggerDidTerminate:)
|
||||
name:NSTaskDidTerminateNotification
|
||||
object:nil];
|
||||
|
||||
|
||||
debuggerTask = [[NSTask alloc] init];
|
||||
[debuggerTask setArguments: [[NSArray alloc] initWithObjects: @"--args", path, nil]];
|
||||
[debuggerTask setCurrentDirectoryPath: [path stringByDeletingLastPathComponent]];
|
||||
[debuggerTask setLaunchPath: debuggerPath];
|
||||
[debuggerTask setStandardOutput: standardOutput];
|
||||
[debuggerTask setStandardError: standardError];
|
||||
[debuggerTask setStandardInput: standardInput];
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
[self logString: @"\n=== Debugger Started ===\n" error: NO newLine:YES];
|
||||
[debuggerTask launch];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSRunAlertPanel(@"Problem Launching Debugger",
|
||||
[localException reason],
|
||||
@"OK", nil, nil, nil);
|
||||
|
||||
//Clean up after task is terminated
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:NSTaskDidTerminateNotification
|
||||
object:debuggerTask];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[debuggerView runProgram: debuggerPath
|
||||
inCurrentDirectory: [path stringByDeletingLastPathComponent]
|
||||
withArguments: [[NSArray alloc] initWithObjects: @"--args", path, nil]
|
||||
logStandardError: YES];
|
||||
}
|
||||
|
||||
- (void) debuggerDidTerminate: (NSNotification *)notif
|
||||
{
|
||||
NSLog(@"Debugger Terminated...");
|
||||
[self logString: @"\n=== Debugger Terminated ===\n" error: NO newLine:YES];
|
||||
}
|
||||
|
||||
- (void) awakeFromNib
|
||||
{
|
||||
[debuggerView setFont: [NSFont userFixedPitchFontOfSize: 0]];
|
||||
[debuggerWindow setFrameAutosaveName: @"PCDebuggerWindow"];
|
||||
}
|
||||
|
||||
- (NSWindow *)debuggerWindow
|
||||
|
@ -252,7 +80,7 @@
|
|||
|
||||
- (void)setDebuggerWindow: (NSWindow *)window
|
||||
{
|
||||
ASSIGN(debuggerWindow,window);
|
||||
debuggerWindow = window;
|
||||
}
|
||||
|
||||
- (NSView *)debuggerView
|
||||
|
@ -262,7 +90,7 @@
|
|||
|
||||
- (void)setDebuggerView: (id)view
|
||||
{
|
||||
ASSIGN(debuggerView,view);
|
||||
debuggerView = view;
|
||||
}
|
||||
|
||||
- (NSString *)path
|
||||
|
@ -274,12 +102,4 @@
|
|||
{
|
||||
ASSIGN(path,p);
|
||||
}
|
||||
|
||||
- (void)putChar:(unichar)ch
|
||||
{
|
||||
NSData *data = [NSData dataWithBytes: &ch length: 1];
|
||||
NSFileHandle *fh = [standardInput fileHandleForWriting];
|
||||
[fh writeData: data];
|
||||
// fputc(ch, stdInStream);
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -1,10 +1,30 @@
|
|||
/* All Rights reserved */
|
||||
/*
|
||||
** PCDebuggerView
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "PTYView.h"
|
||||
|
||||
#import "PCDebugger.h"
|
||||
@class PCDebugger;
|
||||
|
||||
@interface PCDebuggerView : NSTextView
|
||||
@interface PCDebuggerView : PTYView
|
||||
{
|
||||
PCDebugger *debugger;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,47 @@
|
|||
/* All Rights reserved */
|
||||
/*
|
||||
** PCDebuggerView
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "PCDebuggerView.h"
|
||||
|
||||
@implementation PCDebuggerView
|
||||
|
||||
/** set the controlling debugger instance */
|
||||
-(void)setDebugger:(PCDebugger *)theDebugger
|
||||
{
|
||||
debugger = theDebugger;
|
||||
}
|
||||
|
||||
/** respond to key events and pipe them down to the debugger */
|
||||
-(BOOL)performKeyEquivalent: (NSEvent*)theEvent
|
||||
/**
|
||||
* Log string to the view.
|
||||
*/
|
||||
- (void) logString:(NSString *)str
|
||||
newLine:(BOOL)newLine
|
||||
{
|
||||
NSString *chars;
|
||||
|
||||
chars = [theEvent characters];
|
||||
if ([chars length] == 1)
|
||||
NSRange range;
|
||||
|
||||
// FIXME: Filter this error, until we find a better way to deal with it.
|
||||
range = [str rangeOfString: @"[tcsetpgrp failed in terminal_inferior:"];
|
||||
if (range.location == NSNotFound)
|
||||
{
|
||||
unichar c;
|
||||
c = [chars characterAtIndex: 0];
|
||||
|
||||
NSLog(@"character: %c", c);
|
||||
[debugger putChar:c];
|
||||
}
|
||||
return YES; // [super performKeyEquivalent:theEvent];
|
||||
[super logString: str newLine: newLine];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
62
Modules/Debuggers/ProjectCenter/PTYView.h
Normal file
62
Modules/Debuggers/ProjectCenter/PTYView.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
** PTYView
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
@interface PTYView : NSTextView
|
||||
{
|
||||
char pty_name[12]; /* "/dev/[pt]tyXY" = 10 chars + null byte */
|
||||
NSTask *task;
|
||||
NSFileHandle *master_handle;
|
||||
NSFileHandle *slave_handle;
|
||||
NSFileHandle *error_handle;
|
||||
}
|
||||
|
||||
- (int)master;
|
||||
|
||||
- (int)slave: (int)master;
|
||||
|
||||
- (void)logString:(NSString *)str
|
||||
newLine:(BOOL)newLine;
|
||||
|
||||
- (void)logData:(NSData *)data;
|
||||
|
||||
- (void)logStdOut:(NSNotification *)aNotif;
|
||||
|
||||
- (void)logErrOut:(NSNotification *)aNotif;
|
||||
|
||||
- (void) taskDidTerminate: (NSNotification *)notif;
|
||||
|
||||
- (NSString *) startMessage;
|
||||
|
||||
- (NSString *) stopMessage;
|
||||
|
||||
- (void) runProgram: (NSString *)path
|
||||
inCurrentDirectory: (NSString *)directory
|
||||
withArguments: (NSArray *)array
|
||||
logStandardError: (BOOL)logError;
|
||||
|
||||
- (void) terminate;
|
||||
|
||||
- (void) putChar:(unichar)ch;
|
||||
@end
|
350
Modules/Debuggers/ProjectCenter/PTYView.m
Normal file
350
Modules/Debuggers/ProjectCenter/PTYView.m
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
** PTYView
|
||||
**
|
||||
** Copyright (c) 2008
|
||||
**
|
||||
** Author: Gregory Casamento <greg_casamento@yahoo.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <PTYView.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef NOTIFICATION_CENTER
|
||||
#define NOTIFICATION_CENTER [NSNotificationCenter defaultCenter]
|
||||
#endif
|
||||
|
||||
@implementation PTYView
|
||||
/**
|
||||
* Instantiate this view.
|
||||
*/
|
||||
- (id) initWithCoder: (NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
if(self != nil)
|
||||
{
|
||||
// initialize the pty name field.
|
||||
strcpy(pty_name, "/dev/ptyXY");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates master device.
|
||||
*/
|
||||
- (int) master
|
||||
{
|
||||
struct stat buff;
|
||||
static char hex[] = "0123456789abcdef";
|
||||
static char pty[] = "pqrs";
|
||||
int i, fd;
|
||||
char *p;
|
||||
|
||||
for (p = pty; *p != 0; p++)
|
||||
{
|
||||
pty_name[8] = *p;
|
||||
pty_name[9] = '0';
|
||||
|
||||
if (stat(pty_name, &buff) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
pty_name[9] = hex[i];
|
||||
if ((fd = open(pty_name, O_RDWR)) >= 0)
|
||||
{
|
||||
return(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the slave half of a pseudo-terminal.
|
||||
*/
|
||||
- (int) slave:(int)master_fd
|
||||
{
|
||||
int fd;
|
||||
|
||||
// change to t, for slave tty.
|
||||
pty_name[5] = 't';
|
||||
if ((fd = open(pty_name, O_RDWR)) < 0)
|
||||
{
|
||||
close(master_fd);
|
||||
return(-1);
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log string to the view.
|
||||
*/
|
||||
- (void) logString:(NSString *)str
|
||||
newLine:(BOOL)newLine
|
||||
{
|
||||
NSRange range;
|
||||
|
||||
[self replaceCharactersInRange:
|
||||
NSMakeRange([[self string] length],0) withString:str];
|
||||
|
||||
if (newLine)
|
||||
{
|
||||
[self replaceCharactersInRange:
|
||||
NSMakeRange([[self string] length], 0) withString:@"\n"];
|
||||
}
|
||||
|
||||
//
|
||||
// Is it backspace? If so, remove one character from the terminal to reflect
|
||||
// the deletion. For some reason backspace sends "\b \b", so I have to remove
|
||||
// four characters in order to appropriately delete from the buffer.
|
||||
//
|
||||
range = [str rangeOfString: @"\b"];
|
||||
if (range.location != NSNotFound)
|
||||
{
|
||||
NSString *newString = [[self string] substringToIndex: [[self string] length] - 4];
|
||||
[self setString: newString];
|
||||
}
|
||||
|
||||
[self scrollRangeToVisible:NSMakeRange([[self string] length], 0)];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/**
|
||||
* Log data.
|
||||
*/
|
||||
- (void) logData:(NSData *)data
|
||||
{
|
||||
NSString *dataString;
|
||||
dataString = [[NSString alloc]
|
||||
initWithData:data
|
||||
encoding:[NSString defaultCStringEncoding]];
|
||||
[self logString: dataString newLine: NO];
|
||||
RELEASE(dataString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log standard out.
|
||||
*/
|
||||
- (void) logStdOut:(NSNotification *)aNotif
|
||||
{
|
||||
NSData *data;
|
||||
NSFileHandle *handle = master_handle;
|
||||
|
||||
if ((data = [handle availableData]) && [data length] > 0)
|
||||
{
|
||||
[self logData: data];
|
||||
}
|
||||
|
||||
if (task)
|
||||
{
|
||||
[handle waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NOTIFICATION_CENTER removeObserver: self
|
||||
name: NSFileHandleDataAvailableNotification
|
||||
object: handle];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error out.
|
||||
*/
|
||||
- (void) logErrOut:(NSNotification *)aNotif
|
||||
{
|
||||
NSData *data;
|
||||
NSFileHandle *handle = error_handle;
|
||||
|
||||
if ((data = [handle availableData]) && [data length] > 0)
|
||||
{
|
||||
// [self logString: @"\n" newLine: NO];
|
||||
[self logData: data];
|
||||
}
|
||||
|
||||
if (task)
|
||||
{
|
||||
[handle waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NOTIFICATION_CENTER removeObserver:self
|
||||
name: NSFileHandleDataAvailableNotification
|
||||
object: handle];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notified when the task is completed.
|
||||
*/
|
||||
- (void) taskDidTerminate: (NSNotification *)notif
|
||||
{
|
||||
NSLog(@"Task Terminated...");
|
||||
[self logString: [self stopMessage]
|
||||
newLine:YES];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to print when the task starts
|
||||
*/
|
||||
- (NSString *) startMessage
|
||||
{
|
||||
return @"=== Task Started ===";
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to print when the task stops
|
||||
*/
|
||||
- (NSString *) stopMessage
|
||||
{
|
||||
return @"=== Task Stopped ===";
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the program.
|
||||
*/
|
||||
- (void) runProgram: (NSString *)path
|
||||
inCurrentDirectory: (NSString *)directory
|
||||
withArguments: (NSArray *)array
|
||||
logStandardError: (BOOL)logError
|
||||
{
|
||||
int master_fd, slave_fd;
|
||||
|
||||
task = [[NSTask alloc] init];
|
||||
[task setArguments: array];
|
||||
[task setCurrentDirectoryPath: directory];
|
||||
[task setLaunchPath: path];
|
||||
|
||||
master_fd = [self master];
|
||||
if(master_fd > 0)
|
||||
{
|
||||
slave_fd = [self slave: master_fd];
|
||||
if(slave_fd > 0)
|
||||
{
|
||||
slave_handle = [[NSFileHandle alloc] initWithFileDescriptor: slave_fd];
|
||||
master_handle = [[NSFileHandle alloc] initWithFileDescriptor: master_fd];
|
||||
[task setStandardOutput: slave_handle];
|
||||
[task setStandardInput: slave_handle];
|
||||
|
||||
[master_handle waitForDataInBackgroundAndNotify];
|
||||
|
||||
// Log standard error, if requested.
|
||||
if(logError)
|
||||
{
|
||||
[task setStandardError: [NSPipe pipe]];
|
||||
error_handle = [[task standardError] fileHandleForReading];
|
||||
[error_handle waitForDataInBackgroundAndNotify];
|
||||
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(logErrOut:)
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:error_handle];
|
||||
}
|
||||
|
||||
// set up notifications to get data.
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(logStdOut:)
|
||||
name:NSFileHandleDataAvailableNotification
|
||||
object:master_handle];
|
||||
|
||||
|
||||
[NOTIFICATION_CENTER addObserver:self
|
||||
selector:@selector(taskDidTerminate:)
|
||||
name:NSTaskDidTerminateNotification
|
||||
object:nil];
|
||||
|
||||
// run the task...
|
||||
NS_DURING
|
||||
{
|
||||
[self logString: [self startMessage]
|
||||
newLine:YES];
|
||||
[task launch];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSRunAlertPanel(@"Problem Launching Debugger",
|
||||
[localException reason],
|
||||
@"OK", nil, nil, nil);
|
||||
|
||||
|
||||
NSLog(@"Task Terminated Unexpectedly...");
|
||||
[self logString: @"\n=== Task Terminated Unexpectedly ===\n"
|
||||
newLine:YES];
|
||||
|
||||
//Clean up after task is terminated
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName: NSTaskDidTerminateNotification
|
||||
object: task];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) terminate
|
||||
{
|
||||
if(task)
|
||||
{
|
||||
[task terminate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[NOTIFICATION_CENTER removeObserver: self];
|
||||
[self terminate];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a single character into the stream.
|
||||
*/
|
||||
- (void) putChar:(unichar)ch
|
||||
{
|
||||
NSData *data = [NSData dataWithBytes: &ch length: 1];
|
||||
[master_handle writeData: data];
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to key events and pipe them down to the debugger
|
||||
*/
|
||||
- (void) keyDown: (NSEvent*)theEvent
|
||||
{
|
||||
NSString *chars;
|
||||
|
||||
chars = [theEvent characters];
|
||||
if ([chars length] == 1)
|
||||
{
|
||||
unichar c;
|
||||
c = [chars characterAtIndex: 0];
|
||||
|
||||
if (c == 3) // ETX, Control-C
|
||||
{
|
||||
[task interrupt]; // send the interrupt signal to the subtask
|
||||
}
|
||||
else
|
||||
{
|
||||
[self putChar: c];
|
||||
}
|
||||
}
|
||||
}
|
||||
@end
|
|
@ -10,6 +10,13 @@
|
|||
Super = NSObject;
|
||||
};
|
||||
PCDebuggerView = {
|
||||
Actions = (
|
||||
);
|
||||
Outlets = (
|
||||
);
|
||||
Super = PTYView;
|
||||
};
|
||||
PTYView = {
|
||||
Actions = (
|
||||
);
|
||||
Outlets = (
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue