Merge pull request #18 from gnustep/DebuggerRefactor

Debugger refactor
This commit is contained in:
Riccardo 2021-07-30 01:20:55 +02:00 committed by GitHub
commit 25f423bebd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 434 additions and 313 deletions

View file

@ -1,3 +1,21 @@
2021-07-16 Riccardo Mottola <rm@gnu.org>
* Modules/Debuggers/ProjectCenter/GDBWrapper.h
* Modules/Debuggers/ProjectCenter/GDBWrapper.m
Don't send keystrokes directly to gdb, but accumulate a line until return and send, allows to handle backspaces.
2021-07-09 Riccardo Mottola <rm@gnu.org>
* Framework/PCProjectLauncher.m
If we already instantiated a Debugger, reuse it.
2021-07-06 Riccardo Mottola <rm@gnu.org>
* Modules/Debuggers/ProjectCenter/PCDebugger.h
* Modules/Debuggers/ProjectCenter/PCDebugger.m
Change parsing of MI interface to a LAR parser and avoid issue
of recursive [] {} values in the previous parser.
2021-06-22 Riccardo Mottola <rm@gnu.org>
* Modules/Debuggers/ProjectCenter/PCDebugger.h

View file

@ -293,12 +293,20 @@ enum {
// Debugger
debugger = [bundleManager objectForBundleType: @"debugger"
protocol: @protocol(CodeDebugger)
fileName: [executablePath stringByDeletingLastPathComponent]];
[debugger debugExecutableAtPath: executablePath
withDebugger: gdbPath];
if (!debugger)
if (nil == debugger)
{
debugger = [bundleManager objectForBundleType: @"debugger"
protocol: @protocol(CodeDebugger)
fileName: [executablePath stringByDeletingLastPathComponent]];
[debugger debugExecutableAtPath: executablePath
withDebugger: gdbPath];
}
else
{
[debugger show];
}
if (nil == debugger)
NSLog(@"No debugger module found");
// turn debug button off...

View file

@ -1,7 +1,7 @@
/*
** PipeDelegate
** GDBWrapper
**
** Copyright (c) 2008-2016
** Copyright (c) 2008-2021
**
** Author: Gregory Casamento <greg.casamento@gmail.com>
** Riccardo Mottola <rm@gnu.org>
@ -24,7 +24,7 @@
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import "PCDebuggerViewDelegateProtocol.h"
#import "PCDebuggerWrapperProtocol.h"
typedef enum PCDebuggerOutputType_enum {
PCDBNotFoundRecord = 0,
@ -32,9 +32,10 @@ typedef enum PCDebuggerOutputType_enum {
PCDBResultRecord,
PCDBConsoleStreamRecord,
PCDBTargetStreamRecord,
PCDBDebugStreamRecord,
PCDBLogStreamRecord,
PCDBAsyncStatusRecord,
PCDBAsyncInfoRecord,
PCDBAsyncExecRecord,
PCDBAsyncNotifyRecord,
PCDBBreakpointRecord,
PCDBFrameRecord,
PCDBThreadRecord,
@ -42,14 +43,16 @@ typedef enum PCDebuggerOutputType_enum {
PCDBEmptyRecord
} PCDebuggerOutputTypes;
@interface PipeDelegate : NSObject <PCDebuggerViewDelegateProtocol>
@interface GDBWrapper : NSObject <PCDebuggerWrapperProtocol>
{
NSString *debuggerPath;
PCDebugger *debugger;
NSTextView *tView;
NSMutableString *singleInputLine;
NSTask *task;
NSFileHandle *stdinHandle;
NSFileHandle *stdoutHandle;
NSFileHandle *error_handle;
NSFileHandle *errorHandle;
NSColor *userInputColor;
NSColor *debuggerColor;
@ -59,8 +62,14 @@ typedef enum PCDebuggerOutputType_enum {
NSFont *font;
BOOL debuggerStarted;
float debuggerVersion;
NSDictionary *lastMIDictionary;
NSString *lastMIString;
}
- (float) debuggerVersion;
- (void) setDebuggerVersion:(float)ver;
- (void)logStdOut:(NSNotification *)aNotif;
- (void)logErrOut:(NSNotification *)aNotif;
@ -73,4 +82,20 @@ typedef enum PCDebuggerOutputType_enum {
- (void) putChar:(unichar)ch;
// methods for a look-ahead recursive parser which attempts to parse
// gdb's output to a Dictionary/Array structure representable in a plist
// LAR parser - single string element (-> NSString value)
- (NSString *) parseString: (NSScanner *)scanner;
// LAR parser - array element (-> NSArray value)
- (NSArray *) parseArray: (NSScanner *)scanner;
// LAR parser - key-value list (-> NSDictionary value)
- (NSDictionary *) parseKeyValue: (NSScanner *)scanner;
// parses a single line from the debugger or the machine interface
// it splits out the type then recurses in the LAR methods
- (PCDebuggerOutputTypes) parseStringLine: (NSString *)stringInput;
@end

View file

@ -1,7 +1,7 @@
/*
** PipeDelegate.m
** GDBWrapper.m
**
** Copyright (c) 2008-2020 Free Software Foundation
** Copyright (c) 2008-2021 Free Software Foundation
**
** Author: Gregory Casamento <greg.casamento@gmail.com>
** Riccardo Mottola <rm@gnu.org>
@ -35,14 +35,14 @@
#include <stdlib.h>
#include <string.h>
#import "PipeDelegate.h"
#import "GDBWrapper.h"
#import "PCDebugger.h"
#ifndef NOTIFICATION_CENTER
#define NOTIFICATION_CENTER [NSNotificationCenter defaultCenter]
#endif
@implementation PipeDelegate
@implementation GDBWrapper
- (id)init
@ -56,6 +56,8 @@
promptColor = [[NSColor purpleColor] retain];
debuggerStarted = NO;
debuggerVersion = 0.0;
singleInputLine = [[NSMutableString alloc] init];
}
return self;
}
@ -90,6 +92,26 @@
}
}
- (NSString *)debuggerPath
{
return debuggerPath;
}
- (void)setDebuggerPath:(NSString *)path
{
if (debuggerPath != path)
{
[debuggerPath release];
debuggerPath = path;
[debuggerPath retain];
}
}
- (BOOL)debuggerStarted
{
return debuggerStarted;
}
- (void)setFont:(NSFont *)aFont
{
if (font != aFont)
@ -121,6 +143,16 @@
return errorColor;
}
- (float) debuggerVersion
{
return debuggerVersion;
}
- (void) setDebuggerVersion:(float)ver
{
debuggerVersion = ver;
}
/**
* Log string to the view.
*/
@ -156,75 +188,124 @@
[tView setNeedsDisplay:YES];
}
- (NSArray *) parseArray: (NSString *)stringInput
{
if (nil != stringInput)
{
NSMutableArray *mArray;
NSScanner *stringScanner;
NSString *value;
/* == parsing methods == */
mArray = [[NSMutableArray alloc] init];
stringScanner = [NSScanner scannerWithString: stringInput];
while([stringScanner isAtEnd] == NO)
- (NSString *) parseString: (NSScanner *)scanner
{
NSString *str;
[scanner scanString: @"\"" intoString: NULL];
[scanner scanUpToString: @"\"" intoString: &str];
[scanner scanString: @"\"" intoString: NULL];
return str;
}
- (NSArray *) parseArray: (NSScanner *)scanner
{
NSMutableArray *mArray;
id value;
NSString *string = [scanner string];
BOOL elementEnd;
// NSLog(@"parseArray in: %@", [string substringFromIndex: [scanner scanLocation]]);
mArray = [[NSMutableArray alloc] init];
// we chomp up the first opening [
if (![scanner isAtEnd])
[scanner scanString: @"[" intoString: NULL];
elementEnd = NO;
value = nil;
while([scanner isAtEnd] == NO && elementEnd == NO)
{
if ([string characterAtIndex:[scanner scanLocation]] == '\"')
{
value = [self parseString: scanner];
}
else if ([string characterAtIndex:[scanner scanLocation]] == '{')
{
value = [self parseKeyValue: scanner];
}
else if ([string characterAtIndex:[scanner scanLocation]] == ']')
{
[scanner scanString: @"]" intoString: NULL];
elementEnd = YES;
}
if (![scanner isAtEnd] && [string characterAtIndex:[scanner scanLocation]] == ',')
{
[scanner scanString: @"," intoString: NULL];
}
// NSLog(@"Array Element: %@", value);
if (value)
{
[stringScanner scanString: @"{" intoString: NULL];
[stringScanner scanUpToString: @"}" intoString: &value];
[stringScanner scanString: @"}" intoString: NULL];
NSLog(@"Array Element: %@", value);
[mArray addObject: value];
}
return [mArray autorelease];
}
return nil;
return [mArray autorelease];
}
/*
parse subpart of the MI reply which may look like this:
bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0804872c",func="main",file="main.m",fullname="/home/multix/code/gnustep-svc/DirectoryTest/main.m",line="23",thread-groups=["i1"],times="1",original-location="main.m:23"}
*/
- (NSDictionary *) parseKeyValueString: (NSString *)stringInput
- (NSDictionary *) parseKeyValue: (NSScanner *)scanner
{
if (nil != stringInput)
NSMutableDictionary *mdict;
NSString *key = NULL;
id value;
NSString *string = [scanner string];
BOOL elementEnd;
// NSLog(@"scanning KV: %@", [[scanner string] substringFromIndex:[scanner scanLocation]]);
mdict = [[NSMutableDictionary alloc] init];
value = nil;
elementEnd = NO;
// we chomp up the first opening { which may not be always present
if (![scanner isAtEnd])
[scanner scanString: @"{" intoString: NULL];
while([scanner isAtEnd] == NO && elementEnd == NO)
{
NSMutableDictionary *mdict;
NSScanner *stringScanner;
NSString *key = NULL;
NSString *value = NULL;
mdict = [[NSMutableDictionary alloc] init];
stringScanner = [NSScanner scannerWithString: stringInput];
while([stringScanner isAtEnd] == NO)
[scanner scanUpToString: @"=" intoString: &key];
[scanner scanString: @"=" intoString: NULL];
// NSLog(@"KV key found: %@", key);
if ([string characterAtIndex:[scanner scanLocation]] == '\"')
{
[stringScanner scanUpToString: @"=" intoString: &key];
[stringScanner scanString: @"=" intoString: NULL];
if ([stringInput characterAtIndex:[stringScanner scanLocation]] == '[')
{
[stringScanner scanString: @"[" intoString: NULL];
[stringScanner scanUpToString: @"]" intoString: &value];
[stringScanner scanString: @"]" intoString: NULL];
value = [self parseArray: value];
}
else
{
[stringScanner scanString: @"\"" intoString: NULL];
[stringScanner scanUpToString: @"\"" intoString: &value];
[stringScanner scanString: @"\"" intoString: NULL];
[stringScanner scanString: @"," intoString: NULL];
}
// NSLog(@"parse KVS: key %@ value %@", key, value);
if (key != nil && value != nil)
[mdict setObject:value forKey:key];
value = [self parseString: scanner];
}
return [mdict autorelease];
else if ([string characterAtIndex:[scanner scanLocation]] == '[')
{
value = [self parseArray: scanner];
}
else if ([string characterAtIndex:[scanner scanLocation]] == '{')
{
value = [self parseKeyValue: scanner];
}
if (![scanner isAtEnd] && [string characterAtIndex:[scanner scanLocation]] == '}')
{
[scanner scanString: @"}" intoString: NULL];
elementEnd = YES;
}
if (![scanner isAtEnd] && [string characterAtIndex:[scanner scanLocation]] == ',')
{
[scanner scanString: @"," intoString: NULL];
}
if (key != nil && value != nil)
[mdict setObject:value forKey:key];
}
return nil;
return [mdict autorelease];
}
/*
Parses a line coming from the debugger. It could be eiher a stanard outpu or it may come from the machine
Parses a line coming from the debugger. It could be eiher a standard output or it may come from the machine
interface of gdb.
*/
- (PCDebuggerOutputTypes) parseStringLine: (NSString *)stringInput
@ -237,7 +318,7 @@
stringScanner = [NSScanner scannerWithString: stringInput];
//NSLog(@"parsing: |%@|", stringInput);
NSLog(@"parsing: |%@|", stringInput);
[stringScanner scanString: @"(gdb)" intoString: &prefix];
if(prefix != nil)
{
@ -250,104 +331,126 @@
return PCDBPromptRecord;
}
// notify-async-output
[stringScanner scanString: @"=" intoString: &prefix];
if(prefix != nil)
{
NSString *dictionaryName = NULL;
NSLog(@"scanning MI |%@|", stringInput);
NSLog(@"scanning NotifyAsyncInfo |%@|", stringInput);
[stringScanner scanUpToString: @"," intoString: &dictionaryName];
if([dictionaryName isEqualToString: @"thread-group-started"])
{
NSLog(@"%@",dictionaryName);
}
if(dictionaryName != nil)
{
NSString *key = NULL;
{
NSString *key = nil;
id value = nil;
NSDictionary *dict;
while([stringScanner isAtEnd] == NO)
[stringScanner scanString: @"," intoString: NULL];
dict = [self parseKeyValue: stringScanner];
NSLog(@"type %@ value %@", dictionaryName, dict);
lastMIDictionary = dict;
if([dict objectForKey:@"pid"] != nil &&
[dictionaryName isEqualToString: @"thread-group-started"])
{
[stringScanner scanString: @"," intoString: NULL];
[stringScanner scanUpToString: @"=" intoString: &key];
[stringScanner scanString: @"=" intoString: NULL];
if ([stringInput characterAtIndex:[stringScanner scanLocation]] == '[')
[debugger setSubProcessId: [[dict objectForKey:@"pid"] intValue]];
}
else if ([dict objectForKey:@"bkpt"] != nil)
{
NSDictionary *bkpDict;
// gdb specific
NSString *fileName;
NSString *lineNum;
bkpDict = [value objectForKey:@"bkpt"];
fileName = [bkpDict objectForKey:@"fullname"];
lineNum = [bkpDict objectForKey:@"line"];
NSLog(@"parsed from GDB bkpt: %@:%@", fileName, lineNum);
if (fileName != nil && lineNum != nil)
{
[stringScanner scanString: @"[" intoString: NULL];
[stringScanner scanUpToString: @"]" intoString: &value];
[stringScanner scanString: @"]" intoString: NULL];
value = [self parseArray: value];
}
else if ([stringInput characterAtIndex:[stringScanner scanLocation]] == '{')
{
[stringScanner scanString: @"{" intoString: NULL];
[stringScanner scanUpToString: @"}" intoString: &value];
[stringScanner scanString: @"}" intoString: NULL];
value = [self parseKeyValueString: value];
[debugger setLastFileNameParsed: fileName];
[debugger setLastLineNumberParsed: [lineNum intValue]];
}
else
{
[stringScanner scanString: @"\"" intoString: NULL];
[stringScanner scanUpToString: @"\"" intoString: &value];
[stringScanner scanString: @"\"" intoString: NULL];
}
NSLog(@"key %@ value %@", key, value);
if([key isEqualToString:@"pid"] &&
[dictionaryName isEqualToString: @"thread-group-started"])
{
[debugger setSubProcessId: [value intValue]];
}
else if ([key isEqualToString:@"bkpt"])
{
// gdb specific
NSString *fileName;
NSString *lineNum;
fileName = [value objectForKey:@"file"];
lineNum = [value objectForKey:@"line"];
NSLog(@"parsed from GDB bkpt: %@:%@", fileName, lineNum);
if (fileName != nil && lineNum != nil)
{
[debugger setLastFileNameParsed: fileName];
[debugger setLastLineNumberParsed: [lineNum intValue]];
}
else
{
[debugger setLastFileNameParsed: nil];
[debugger setLastLineNumberParsed: NSNotFound];
}
[debugger setLastFileNameParsed: nil];
[debugger setLastLineNumberParsed: NSNotFound];
}
}
}
return PCDBAsyncInfoRecord;
else
{
NSLog(@"error parsing type of: %@", stringInput);
}
return PCDBAsyncNotifyRecord;
}
// exec-async-output
[stringScanner scanString: @"*" intoString: &prefix];
if(prefix != nil)
{
NSString *dictionaryName = NULL;
NSDictionary *dict = nil;
NSLog(@"scanning ExecAsyncStatus |%@|", stringInput);
[stringScanner scanUpToString: @"," intoString: &dictionaryName];
if(dictionaryName != nil)
{
[stringScanner scanString: @"," intoString: NULL];
dict = [self parseKeyValue: stringScanner];
NSLog(@"type %@ value %@", dictionaryName, dict);
lastMIDictionary = dict;
}
if ([dictionaryName isEqualToString:@"stopped"])
{
[debugger setStatus:@"Stopped"];
if ([dict objectForKey:@"reason"] != nil)
{
NSDictionary *frameDict;
NSString *fileName;
NSString *lineNum;
frameDict = [dict objectForKey:@"frame"];
fileName = [frameDict objectForKey:@"fullname"];
lineNum = [frameDict objectForKey:@"line"];
NSLog(@"parsed from GDB %@ : %@:%@", [dict objectForKey:@"reason"], fileName, lineNum);
if (fileName != nil && lineNum != nil)
{
[debugger setLastFileNameParsed: fileName];
[debugger setLastLineNumberParsed: [lineNum intValue]];
}
else
{
[debugger setLastFileNameParsed: nil];
[debugger setLastLineNumberParsed: NSNotFound];
}
}
}
return PCDBAsyncExecRecord;
}
// status-async-output
[stringScanner scanString: @"+" intoString: &prefix];
if(prefix != nil)
{
NSString *dictionaryName = NULL;
NSDictionary *dict = nil;
NSLog(@"scanning AsyncStatus |%@|", stringInput);
return PCDBAsyncStatusRecord;
}
[stringScanner scanString: @"<-" intoString: &prefix];
if(prefix != nil)
{
return PCDBBreakpointRecord;
}
[stringScanner scanString: @"->" intoString: &prefix];
if(prefix != nil)
{
return PCDBBreakpointRecord;
}
// console-stream-output
[stringScanner scanString: @"~" intoString: &prefix];
if(prefix != nil)
{
if ([debugger debuggerVersion] == 0.0)
if (debuggerVersion == 0.0)
{
NSString *str1 = nil;
NSString *str2 = nil;
@ -365,11 +468,11 @@
if ([stringScanner scanFloat:&v])
{
NSLog(@"GDB version string: %f", v);
[debugger setDebuggerVersion:v];
[self setDebuggerVersion:v];
}
}
}
if (([debugger debuggerVersion] < 7) && [debugger subProcessId] == 0)
if ((debuggerVersion < 7) && [debugger subProcessId] == 0)
{
NSString *str1;
// we attempt to parse: [New thread 6800.0x18ec]
@ -387,23 +490,30 @@
return PCDBConsoleStreamRecord;
}
// target-stream-output
[stringScanner scanString: @"@" intoString: &prefix];
if(prefix != nil)
{
lastMIString = [[stringScanner string] substringFromIndex: [stringScanner scanLocation]];
return PCDBTargetStreamRecord;
}
// log-stream-output
[stringScanner scanString: @"&" intoString: &prefix];
if(prefix != nil)
{
return PCDBDebugStreamRecord;
lastMIString = [[stringScanner string] substringFromIndex: [stringScanner scanLocation]];
return PCDBLogStreamRecord;
}
// result-record
[stringScanner scanString: @"^" intoString: &prefix];
if(prefix != nil)
{
NSString *result = nil;
NSLog(@"scanning Result Record |%@|", stringInput);
[stringScanner scanString: @"done" intoString: &result];
if(result != nil)
{
@ -436,7 +546,23 @@
}
return PCDBResultRecord;
}
NSLog(@"No match found parse: |%@|", stringInput);
[stringScanner scanString: @"<-" intoString: &prefix];
if(prefix != nil)
{
lastMIString = [[stringScanner string] substringFromIndex: [stringScanner scanLocation]];
return PCDBBreakpointRecord;
}
[stringScanner scanString: @"->" intoString: &prefix];
if(prefix != nil)
{
lastMIString = [[stringScanner string] substringFromIndex: [stringScanner scanLocation]];
return PCDBBreakpointRecord;
}
NSLog(@"No match found parsing: |%@|", stringInput);
return PCDBNotFoundRecord;
}
@ -446,7 +572,7 @@
if ([unescapedString hasPrefix:@"~\""])
unescapedString = [unescapedString substringFromIndex:2];
if ([unescapedString hasSuffix:@"\""])\
if ([unescapedString hasSuffix:@"\""])
unescapedString = [unescapedString substringToIndex: [unescapedString length] - 1];
unescapedString = [unescapedString stringByReplacingOccurrencesOfString: @"\\\"" withString: @"\""];
unescapedString = [unescapedString stringByReplacingOccurrencesOfString: @"\\n" withString: @"\n"];
@ -456,7 +582,7 @@
return unescapedString;
}
- (void) parseString: (NSString *)inputString
- (void) parseLine: (NSString *)inputString
{
NSArray *components;
NSEnumerator *en;
@ -482,26 +608,25 @@
{
[self logString: item newLine: NO withColor:promptColor];
}
/*
else if(outtype == PCDBNotFoundRecord)
else if(outtype == PCDBAsyncStatusRecord || outtype == PCDBAsyncExecRecord || outtype == PCDBAsyncNotifyRecord)
{
[self logString: item newLine: NO withColor:promptColor];
}
*/
else if(outtype == PCDBLogStreamRecord)
{
NSString *unescapedString = [self unescapeOutputRecord: lastMIString];
// this should usually stay silent, log for debugging purposes
[self logString: unescapedString newLine: NO withColor:debuggerColor];
}
else if(outtype == PCDBNotFoundRecord)
{
[self logString: item newLine: NO withColor:errorColor];
}
}
/*
stringRange = [inputString rangeOfString: "(gdb)" options: NULL];
if(stringRange.location == NSNotFound)
{
[self logString: inputString newLine: NO withColor:debuggerColor];
}
else
{
}
*/
}
/* == end of parsing methods */
/**
* Log standard out.
*/
@ -518,7 +643,7 @@
encoding:[NSString defaultCStringEncoding]];
// if( !
[self parseString: dataString]; // )
[self parseLine: dataString]; // )
// {
// [self logString: dataString newLine: NO withColor:debuggerColor];
// }
@ -543,7 +668,7 @@
- (void) logErrOut:(NSNotification *)aNotif
{
NSData *data;
NSFileHandle *handle = error_handle;
NSFileHandle *handle = errorHandle;
if ((data = [handle availableData]) && [data length] > 0)
{
@ -604,16 +729,19 @@
*/
- (void) runProgram: (NSString *)path
inCurrentDirectory: (NSString *)directory
withArguments: (NSArray *)array
logStandardError: (BOOL)logError
{
NSPipe *inPipe;
NSPipe *outPipe;
NSArray *argArray;
argArray = [[NSArray alloc] initWithObjects: @"--interpreter=mi", @"-f", path, nil];
task = [[NSTask alloc] init];
[task setArguments: array];
[task setArguments: argArray];
[argArray release];
[task setCurrentDirectoryPath: directory];
[task setLaunchPath: path];
[task setLaunchPath: debuggerPath];
inPipe = [NSPipe pipe];
outPipe = [NSPipe pipe];
@ -628,13 +756,13 @@
if(logError)
{
[task setStandardError: [NSPipe pipe]];
error_handle = [[task standardError] fileHandleForReading];
[error_handle waitForDataInBackgroundAndNotify];
errorHandle = [[task standardError] fileHandleForReading];
[errorHandle waitForDataInBackgroundAndNotify];
[NOTIFICATION_CENTER addObserver:self
selector:@selector(logErrOut:)
name:NSFileHandleDataAvailableNotification
object:error_handle];
object:errorHandle];
}
// set up notifications to get data.
@ -694,7 +822,10 @@
[debuggerColor release];
[messageColor release];
[errorColor release];
[debuggerPath release];
[debugger release];
[tView release];
[singleInputLine release];
[super dealloc];
}
@ -708,24 +839,45 @@
}
/* for input as typed from the user */
/* since the underlying tty to gdb doesn't handle control characters,
we fake editing with a single line of text being a buffer, it is displayed
but sent complete to gdb only on Enter, backspace being handled */
- (void) typeString: (NSString *)string
{
NSUInteger strLen;
strLen = [string length];
[self putString:string];
// if we have a single backspace or delete character
if (strLen == 1 && [string characterAtIndex:strLen-1] == '\177')
if (strLen == 1)
{
NSUInteger textLen;
textLen = [[tView string] length];
[tView setSelectedRange:NSMakeRange(textLen-1, 1)];
[tView delete:nil];
return;
// if we have a single backspace or delete character
if([string characterAtIndex:0] == '\177') // del (maybe backspace)
{
if ([singleInputLine length])
{
[singleInputLine deleteCharactersInRange: NSMakeRange([singleInputLine length]-1, 1)];
[tView setSelectedRange:NSMakeRange([[tView string] length]-1, 1)];
[tView delete:nil];
return;
}
}
else if([string characterAtIndex:0] == '\n')
{
NSLog(@"full command is: |%@|", singleInputLine);
// we end our single line and pipe it down
[singleInputLine appendString:string];
[self putString:singleInputLine];
[singleInputLine setString:@""];
}
else
{
[singleInputLine appendString:string];
}
}
else
{
NSLog(@"strlen > 1 |%@|", string);
[singleInputLine appendString:string];
}
[self logString:string newLine:NO withColor:userInputColor];
}
@ -758,7 +910,7 @@
{
unichar c;
c = [chars characterAtIndex: 0];
//NSLog(@"char: %d", c);
// NSLog(@"char: %o", c);
if (c == 3) // ETX, Control-C
{
@ -768,15 +920,7 @@
{
[self typeString: @"\n"];
}
else if (c == 127) // del (usually backspace)
{
NSString *tss = [[tView textStorage] string];
if (![tss hasSuffix:@"\n"] && ![tss hasSuffix:@"(gdb) "])
{
[self typeString: chars];
}
}
else
else if (c < 255) // helps ignoring arrows, pgup/pgdown which gets 2-byte chars
{
[self typeString: chars];
}

View file

@ -37,9 +37,9 @@ ProjectCenter_RESOURCE_FILES= \
#
ProjectCenter_HEADERS= \
PCDebugger.h \
PCDebugggerView.h \
PCDebuggerViewDelegateProtocol.h \
PipeDelegate.h
PCDebuggerView.h \
PCDebuggerWrapperProtocol.h \
GDBWrapper.h
#
# Class files
@ -47,7 +47,7 @@ ProjectCenter_HEADERS= \
ProjectCenter_OBJC_FILES= \
PCDebugger.m \
PCDebuggerView.m \
PipeDelegate.m
GDBWrapper.m
#ADDITIONAL_OBJC_LIBS=

View file

@ -27,14 +27,15 @@
#import <Foundation/Foundation.h>
#import <Protocols/CodeDebugger.h>
#import "PCDebuggerWrapperProtocol.h"
extern const NSString *PCBreakTypeKey;
extern NSString *PCBreakTypeKey;
extern NSString *PCBreakTypeByLine;
extern NSString *PCBreakTypeMethod;
extern NSString *PCBreakMethod;
extern NSString *PCBreakFilename;
extern NSString *PCBreakLineNumber;
extern const NSString *PCBreakMethod;
extern const NSString *PCBreakFilename;
extern const NSString *PCBreakLineNumber;
extern NSString *PCDBDebuggerStartedNotification;
@interface PCDebugger : NSObject <CodeDebugger>
@ -43,15 +44,15 @@ extern NSString *PCDBDebuggerStartedNotification;
id debuggerWindow;
id statusField;
NSString *executablePath;
NSString *debuggerPath;
int subProcessId;
float debuggerVersion;
NSDictionary *lastInfoParsed;
NSString *lastFileNameParsed;
NSUInteger lastLineNumberParsed;
NSMutableArray *breakpoints;
id <PCDebuggerWrapperProtocol> debuggerWrapper;
}
- (id <PCDebuggerWrapperProtocol>)debuggerWrapper;
- (void) setStatus: (NSString *) status;
- (NSString *) status;
- (NSString *)executablePath;
@ -59,8 +60,6 @@ extern NSString *PCDBDebuggerStartedNotification;
- (void) interrupt;
- (int) subProcessId;
- (void) setSubProcessId:(int)pid;
- (float) debuggerVersion;
- (void) setDebuggerVersion:(float)ver;
- (NSDictionary *)lastInfoParsed;
- (void)setSetInfoParsed: (NSDictionary *)dict;
- (NSString *)lastFileNameParsed;

View file

@ -34,8 +34,8 @@
#import "PCDebuggerView.h"
#import "Modules/Preferences/EditorFSC/PCEditorFSCPrefs.h"
#import "PCDebuggerViewDelegateProtocol.h"
#import "PipeDelegate.h"
#import "PCDebuggerWrapperProtocol.h"
#import "GDBWrapper.h"
#ifndef NOTIFICATION_CENTER
@ -52,12 +52,12 @@ static NSImage *stepOutImage = nil;
static NSImage *upImage = nil;
static NSImage *downImage = nil;
const NSString *PCBreakTypeKey = @"BreakType";
NSString *PCBreakTypeKey = @"BreakType";
NSString *PCBreakTypeByLine = @"BreakTypeLine";
NSString *PCBreakTypeMethod = @"BreakTypeMethod";
const NSString *PCBreakMethod = @"BreakMethod";
const NSString *PCBreakFilename = @"BreakFilename";
const NSString *PCBreakLineNumber = @"BreakLineNumber";
NSString *PCBreakMethod = @"BreakMethod";
NSString *PCBreakFilename = @"BreakFilename";
NSString *PCBreakLineNumber = @"BreakLineNumber";
NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
@implementation PCDebugger
@ -139,8 +139,7 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
{
if((self = [super init]) != nil)
{
NSLog(@"PCDebugger Init");
id <PCDebuggerViewDelegateProtocol> viewDelegate;
NSLog(@"PCDebugger Init");
// initialization here...
if([NSBundle loadNibNamed: @"PCDebugger" owner: self] == NO)
{
@ -148,16 +147,12 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
}
[(PCDebuggerView *)debuggerView setDebugger:self];
viewDelegate = [[PipeDelegate alloc] init];
[debuggerView setDelegate:viewDelegate];
[viewDelegate setTextView:debuggerView];
[viewDelegate setDebugger:self];
[viewDelegate release];
debuggerWrapper = [[GDBWrapper alloc] init];
[debuggerWrapper setTextView:debuggerView];
[debuggerWrapper setDebugger:self];
[debuggerView setFont: [self consoleFont]];
subProcessId = 0;
debuggerVersion = 0.0;
lastInfoParsed = nil;
lastFileNameParsed = nil;
lastLineNumberParsed = NSNotFound;
@ -176,7 +171,7 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
withDebugger: (NSString *)debugger
{
ASSIGN(executablePath,filePath);
ASSIGN(debuggerPath,debugger);
[debuggerWrapper setDebuggerPath: debugger];
[debuggerWindow setTitle: [NSString stringWithFormat: @"Debugger (%@)",filePath]];
[self show];
}
@ -184,22 +179,20 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
- (void) show
{
[debuggerWindow makeKeyAndOrderFront: self];
[self startDebugger];
if (![debuggerWrapper debuggerStarted])
[self startDebugger];
}
- (void) startDebugger
{
[debuggerView runProgram: debuggerPath
inCurrentDirectory: [executablePath stringByDeletingLastPathComponent]
withArguments: [[NSArray alloc] initWithObjects: @"--interpreter=mi", @"-f", executablePath, nil] // gdb dependent - should be generalized
[debuggerView runProgram: executablePath
inCurrentDirectory: [executablePath stringByDeletingLastPathComponent]
logStandardError: YES];
}
- (void) initBreakpoints
{
id <PCDebuggerViewDelegateProtocol> viewDelegate;
breakpoints = [[NSMutableArray alloc] init];
/* CRUDE EXAMPLES * TODO FIXME *
NSDictionary *dP;
@ -210,16 +203,12 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
dP = [NSDictionary dictionaryWithObjectsAndKeys: PCBreakTypeByLine, PCBreakTypeKey, @"AppController.m", PCBreakFilename, [NSNumber numberWithInt:100], PCBreakLineNumber, nil];
[breakpoints addObject:dP];
*/
viewDelegate = [debuggerView delegate];
[viewDelegate setBreakpoints:breakpoints];
[debuggerWrapper setBreakpoints:breakpoints];
}
- (void) debuggerSetup
{
id <PCDebuggerViewDelegateProtocol> viewDelegate;
viewDelegate = [debuggerView delegate];
[viewDelegate debuggerSetup];
[debuggerWrapper debuggerSetup];
}
- (void) handleNotification: (NSNotification *)notification
@ -241,6 +230,11 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
[self setStatus: @"Idle."];
}
- (id <PCDebuggerWrapperProtocol>)debuggerWrapper
{
return debuggerWrapper;
}
- (NSWindow *)debuggerWindow
{
return debuggerWindow;
@ -278,19 +272,10 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
- (void) setSubProcessId: (int)pid
{
NSLog(@"PCDebugger setSubProcessId: %d", pid);
subProcessId = pid;
}
- (float) debuggerVersion
{
return debuggerVersion;
}
- (void) setDebuggerVersion:(float)ver
{
debuggerVersion = ver;
}
- (NSDictionary *)lastInfoParsed
{
return lastInfoParsed;
@ -368,47 +353,39 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
- (void) continue: (id) sender
{
// [self setStatus: @"Continue..."];
[debuggerView putString: @"continue\n"];
}
- (void) restart: (id) sender
{
// [self setStatus: @"Restarting..."];
[self interrupt];
/* each run makes a new PID but we parse it only if non-zero */
[self setSubProcessId:0];
[debuggerView putString: @"run\n"];
// [self setStatus: @"Running..."];
}
- (void) next: (id) sender
{
// [self setStatus: @"Going to next line."];
[debuggerView putString: @"next\n"];
}
- (void) stepInto: (id) sender
{
// [self setStatus: @"Stepping into method."];
[debuggerView putString: @"step\n"];
}
- (void) stepOut: (id) sender
{
// [self setStatus: @"Finishing method."];
[debuggerView putString: @"finish\n"];
}
- (void) up: (id) sender
{
// [self setStatus: @"Up to calling method."];
[debuggerView putString: @"up\n"];
}
- (void) down: (id) sender
{
// [self setStatus: @"Down to called method."];
[debuggerView putString: @"down\n"];
}
@ -425,6 +402,7 @@ NSString *PCDBDebuggerStartedNotification = @"PCDBDebuggerStartedNotification";
- (void) dealloc
{
[debuggerWrapper release];
[breakpoints release];
[super dealloc];
}

View file

@ -1,7 +1,7 @@
/*
** PCDebuggerView
**
** Copyright (c) 2008-2020
** Copyright (c) 2008-2021
**
** Author: Gregory Casamento <greg.casamento@gmail.com>
** Riccardo Mottola <rm@gnu.org>
@ -24,30 +24,21 @@
#import <Foundation/NSString.h>
#import <AppKit/NSTextView.h>
#import "PCDebuggerViewDelegateProtocol.h"
@class PCDebugger;
@interface PCDebuggerView : NSTextView
{
PCDebugger *debugger;
id <PCDebuggerViewDelegateProtocol> viewDelegate;
NSString *currentFile;
}
- (void) setDebugger:(PCDebugger *)theDebugger;
- (id <PCDebuggerViewDelegateProtocol>)delegate;
- (void) setDelegate:(id <PCDebuggerViewDelegateProtocol>) vd;
- (void) setCurrentFile: (NSString *)fileName;
- (NSString *) currentFile;
- (void)setFont:(NSFont *)font;
- (void) runProgram: (NSString *)path
inCurrentDirectory: (NSString *)directory
withArguments: (NSArray *)array
logStandardError: (BOOL)logError;
- (void) putString: (NSString *)string;

View file

@ -1,7 +1,7 @@
/*
** PCDebuggerView
**
** Copyright (c) 2008-2016
** Copyright (c) 2008-2021
**
** Author: Gregory Casamento <greg.casamento@gmail.com>
** Riccardo Mottola <rm@gnu.org>
@ -41,25 +41,10 @@
debugger = theDebugger;
}
- (id <PCDebuggerViewDelegateProtocol>)delegate
{
return viewDelegate;
}
- (void) setDelegate:(id <PCDebuggerViewDelegateProtocol>) vd
{
if (viewDelegate != vd)
{
[viewDelegate release];
viewDelegate = vd;
[viewDelegate retain];
}
}
- (void)setFont:(NSFont *)aFont
{
[viewDelegate setFont:aFont];
[[debugger debuggerWrapper] setFont:aFont];
}
/**
@ -68,22 +53,13 @@
- (void) logString:(NSString *)str
newLine:(BOOL)newLine
{
[viewDelegate logString: str newLine: newLine withColor:[viewDelegate debuggerColor]];
[[debugger debuggerWrapper] logString: str newLine: newLine withColor:[[debugger debuggerWrapper] debuggerColor]];
}
- (void) setCurrentFile: (NSString *)fileName
{
ASSIGN(currentFile,fileName);
}
- (NSString *) currentFile
{
return currentFile;
}
- (void) terminate
{
[viewDelegate terminate];
[[debugger debuggerWrapper] terminate];
}
- (void) mouseDown: (NSEvent *)event
@ -96,13 +72,11 @@
*/
- (void) runProgram: (NSString *)path
inCurrentDirectory: (NSString *)directory
withArguments: (NSArray *)array
logStandardError: (BOOL)logError
{
[viewDelegate runProgram: path
inCurrentDirectory: directory
withArguments: array
logStandardError: logError];
[[debugger debuggerWrapper] runProgram: path
inCurrentDirectory: directory
logStandardError: logError];
}
- (void) putString: (NSString *)string
@ -110,12 +84,12 @@
NSAttributedString* attr = [[NSAttributedString alloc] initWithString:string];
[[self textStorage] appendAttributedString:attr];
[self scrollRangeToVisible:NSMakeRange([[self string] length], 0)];
[viewDelegate putString:string];
[[debugger debuggerWrapper] putString:string];
}
- (void) keyDown: (NSEvent*)theEvent
{
[viewDelegate keyDown:theEvent];
[[debugger debuggerWrapper] keyDown:theEvent];
}
@end

View file

@ -1,7 +1,7 @@
/*
** PCDebuggerViewDelegateProtocol.h
** PCDebuggerWrapperProtocol.h
**
** Copyright (c) 2016-2020
** Copyright (c) 2016-2021
**
** Author: Riccardo Mottola <rm@gnu.org>
**
@ -28,7 +28,7 @@
@class NSString;
@class PCDebugger;
@protocol PCDebuggerViewDelegateProtocol <NSObject>
@protocol PCDebuggerWrapperProtocol <NSObject>
- (void)setFont:(NSFont *)font;
@ -42,9 +42,13 @@
- (PCDebugger *)debugger;
- (void)setDebugger:(PCDebugger *)dbg;
- (NSString *)debuggerPath;
- (void)setDebuggerPath:(NSString *)path;
- (BOOL)debuggerStarted;
- (void) runProgram: (NSString *)path
inCurrentDirectory: (NSString *)directory
withArguments: (NSArray *)array
logStandardError: (BOOL)logError;
- (void)logString:(NSString *)str

View file

@ -170,7 +170,6 @@
tSelCol, NSForegroundColorAttributeName,
nil];
[ev setSelectedTextAttributes:selAttributes];
[ev setSelectedTextAttributes:selAttributes];
// Activate undo
[ev setAllowsUndo: YES];

View file

@ -470,25 +470,6 @@ static int ComputeIndentingOffset(NSString * string, unsigned int start)
return editor;
}
- (void)awakeFromNib
{
/* NSData * data;
NSUserDefaults * df = [NSUserDefaults standardUserDefaults];
drawCrosshairs = [df boolForKey: @"DrawCrosshairs"];
if (drawCrosshairs)
{
if ((data = [df dataForKey: @"CrosshairColor"]) == nil ||
(crosshairColor = [NSUnarchiver unarchiveObjectWithData: data]) == nil)
{
crosshairColor = [NSColor lightGrayColor];
}
[crosshairColor retain];
}
guides = [NSMutableArray new];*/
}
- (void)drawRect:(NSRect)r
{
if (highlighter)