1E027F0B0D36F23F00885DEE /* StepOver.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E027F090D36F23F00885DEE /* StepOver.png */; };
1E027F390D36F60800885DEE /* Reconnect.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E027F380D36F60800885DEE /* Reconnect.png */; };
1E02C3D50C60EC2C006F1752 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E02C3D40C60EC2C006F1752 /* AppDelegate.m */; };
- 1E02C5710C610158006F1752 /* GDBpConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E02C5700C610158006F1752 /* GDBpConnection.m */; };
+ 1E02C5710C610158006F1752 /* DebuggerConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E02C5700C610158006F1752 /* DebuggerConnection.m */; };
1E02C5F60C610724006F1752 /* DebuggerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E02C5F50C610724006F1752 /* DebuggerController.m */; };
1E0AFBB90FC2518700C67031 /* HUDIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E0AFBB80FC2518700C67031 /* HUDIcon.png */; };
1E1E53030DF9B89800D334F9 /* Breakpoints.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E1E53010DF9B89800D334F9 /* Breakpoints.xib */; };
1E027F380D36F60800885DEE /* Reconnect.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Reconnect.png; path = Icons/Reconnect.png; sourceTree = "<group>"; };
1E02C3D30C60EC2C006F1752 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Source/AppDelegate.h; sourceTree = "<group>"; };
1E02C3D40C60EC2C006F1752 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Source/AppDelegate.m; sourceTree = "<group>"; };
- 1E02C56F0C610158006F1752 /* GDBpConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBpConnection.h; path = Source/GDBpConnection.h; sourceTree = "<group>"; };
- 1E02C5700C610158006F1752 /* GDBpConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GDBpConnection.m; path = Source/GDBpConnection.m; sourceTree = "<group>"; };
+ 1E02C56F0C610158006F1752 /* DebuggerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebuggerConnection.h; path = Source/DebuggerConnection.h; sourceTree = "<group>"; };
+ 1E02C5700C610158006F1752 /* DebuggerConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DebuggerConnection.m; path = Source/DebuggerConnection.m; sourceTree = "<group>"; };
1E02C5F40C610724006F1752 /* DebuggerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebuggerController.h; path = Source/DebuggerController.h; sourceTree = "<group>"; };
1E02C5F50C610724006F1752 /* DebuggerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DebuggerController.m; path = Source/DebuggerController.m; sourceTree = "<group>"; };
1E0AFBB80FC2518700C67031 /* HUDIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HUDIcon.png; path = Icons/HUDIcon.png; sourceTree = "<group>"; };
1E1E52C10DF9B1FB00D334F9 /* Connection */ = {
isa = PBXGroup;
children = (
- 1E02C56F0C610158006F1752 /* GDBpConnection.h */,
- 1E02C5700C610158006F1752 /* GDBpConnection.m */,
+ 1E02C56F0C610158006F1752 /* DebuggerConnection.h */,
+ 1E02C5700C610158006F1752 /* DebuggerConnection.m */,
1E35FFB00C65A74C0030F527 /* NSXMLElementAdditions.h */,
1E35FC750C6579CA0030F527 /* NSXMLElementAdditions.m */,
);
files = (
8D11072D0486CEB800E47090 /* main.m in Sources */,
1E02C3D50C60EC2C006F1752 /* AppDelegate.m in Sources */,
- 1E02C5710C610158006F1752 /* GDBpConnection.m in Sources */,
+ 1E02C5710C610158006F1752 /* DebuggerConnection.m in Sources */,
1E02C5F60C610724006F1752 /* DebuggerController.m in Sources */,
1E35FC760C6579CA0030F527 /* NSXMLElementAdditions.m in Sources */,
1E35FEA10C6599040030F527 /* base64.c in Sources */,
#import <Cocoa/Cocoa.h>
#import "Breakpoint.h"
-#import "GDBpConnection.h"
+#import "DebuggerConnection.h"
@interface BreakpointManager : NSObject
{
NSMutableArray* breakpoints;
NSMutableArray* savedBreakpoints;
- GDBpConnection* connection;
+ DebuggerConnection* connection;
}
-@property(readwrite, assign) GDBpConnection* connection;
+@property(readwrite, assign) DebuggerConnection* connection;
@property(readonly) NSMutableArray* breakpoints;
+ (BreakpointManager*)sharedManager;
#import "Breakpoint.h"
#import "StackFrame.h"
-@protocol GDBpConnectionDelegate;
-
-@interface GDBpConnection : NSObject
+@protocol DebuggerConnectionDelegate;
+
+// The DebuggerConnection is the communication layer between the application
+// and the Xdebug engine. Clients can issue debugger commands using this class,
+// which are sent in an asynchronous manner. Reads are also asynchronous and
+// the primary client of this class should set itself as the delegate. The
+// primary unit that this class deals with is the StackFrame; clients should
+// maintain a stack structure and the Connection will inform the delegate when
+// a new frame is created or the stack should be destroyed.
+@interface DebuggerConnection : NSObject
{
+ // The port to connect on.
NSUInteger port;
- BOOL connected;
- /**
- * An ever-increasing integer that gives each transaction a unique ID for
- * the debugging engine. Managed by |-createCommand:|.
- */
- NSUInteger transactionID;
+ // If the connection to the debugger engine is currently active.
+ BOOL connected;
- /**
- * Human-readable status of the connection
- */
+ // Human-readable status of the connection.
NSString* status;
+ // The connection's delegate.
+ id <DebuggerConnectionDelegate> delegate;
+
// The raw CFSocket on which the two streams are based. Strong.
CFSocketRef socket_;
// The read stream that is scheduled on the main run loop. Weak.
CFReadStreamRef readStream_;
+ // The write stream. Weak.
+ CFWriteStreamRef writeStream_;
+
+ // An ever-increasing integer that gives each transaction a unique ID for the
+ // debugging engine.
+ NSUInteger transactionID;
+
// The most recently received transaction ID.
NSUInteger lastReadTransaction_;
- // Information about the current read loop. We append to |currentPacket_|
- // until |currentPacketSize_| has reached |packetSize_|.
- NSMutableString* currentPacket_;
- int packetSize_;
- int currentPacketIndex_;
+ // The last transactionID written to the stream.
+ NSUInteger lastWrittenTransaction_;
+
+ // Callback table. This maps transaction IDs to selectors. When the engine
+ // returns a response to the debugger, we will dispatch the response XML to
+ // the selector, based on transaction_id.
+ NSMutableDictionary* callTable_;
// To prevent blocked writing, we enqueue all writes and then wait for the
// write stream to tell us it's ready. We store the pending commands in this
// array. We use this as a stack (FIFO), with index 0 being first.
NSMutableArray* queuedWrites_;
- // We send queued writes in multiple places, sometimes of a run loop event.
+ // We send queued writes in multiple places, sometimes off a run loop event.
// Because of this, we need to ensure that only one client is dequeing and
// sending at a time.
NSRecursiveLock* writeQueueLock_;
- // The write stream. Weak.
- CFWriteStreamRef writeStream_;
-
- // The last transactionID written to the stream.
- NSUInteger lastWrittenTransaction_;
+ // Information about the current read loop. We append to |currentPacket_|
+ // until |currentPacketSize_| has reached |packetSize_|.
+ NSMutableString* currentPacket_;
+ int packetSize_;
+ int currentPacketIndex_;
// A dictionary that maps routingIDs to StackFrame objects.
NSMutableDictionary* stackFrames_;
// The earliest transaction ID for the current build of |stackFrames_|.
NSInteger stackFirstTransactionID_;
- // Callback table. This maps transaction IDs to selectors. When the engine
- // returns a response to the debugger, we will dispatch the response XML to
- // the selector, based on transaction_id.
- NSMutableDictionary* callTable_;
-
// This stores additional context information for the callback selector.
// This dictionary is keyed by the same transaction IDs in |callTable_|, but
// also stores some other object that can be accessed in the callback.
NSMutableDictionary* callbackContext_;
-
- id <GDBpConnectionDelegate> delegate;
}
@property (readonly, copy) NSString* status;
-@property (assign) id <GDBpConnectionDelegate> delegate;
+@property (assign) id <DebuggerConnectionDelegate> delegate;
// initializer
- (id)initWithPort:(NSUInteger)aPort;
@end
-@protocol GDBpConnectionDelegate <NSObject>
+// Delegate ////////////////////////////////////////////////////////////////////
+
+@protocol DebuggerConnectionDelegate <NSObject>
// Passes up errors from SocketWrapper and any other errors generated by the
// GDBpConnection.
#import <sys/socket.h>
#import <netinet/in.h>
-#import "GDBpConnection.h"
+#import "DebuggerConnection.h"
#import "AppDelegate.h"
// GDBpConnection (Private) ////////////////////////////////////////////////////
-@interface GDBpConnection ()
+@interface DebuggerConnection ()
@property (readwrite, copy) NSString* status;
@property (assign) CFSocketRef socket;
@property (assign) CFReadStreamRef readStream;
void ReadStreamCallback(CFReadStreamRef stream, CFStreamEventType eventType, void* connectionRaw)
{
- GDBpConnection* connection = (GDBpConnection*)connectionRaw;
+ DebuggerConnection* connection = (DebuggerConnection*)connectionRaw;
switch (eventType)
{
case kCFStreamEventHasBytesAvailable:
void WriteStreamCallback(CFWriteStreamRef stream, CFStreamEventType eventType, void* connectionRaw)
{
- GDBpConnection* connection = (GDBpConnection*)connectionRaw;
+ DebuggerConnection* connection = (DebuggerConnection*)connectionRaw;
switch (eventType)
{
case kCFStreamEventCanAcceptBytes:
assert(callbackType == kCFSocketAcceptCallBack);
NSLog(@"SocketAcceptCallback()");
- GDBpConnection* connection = (GDBpConnection*)connectionRaw;
+ DebuggerConnection* connection = (DebuggerConnection*)connectionRaw;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
// GDBpConnection //////////////////////////////////////////////////////////////
-@implementation GDBpConnection
+@implementation DebuggerConnection
@synthesize socket = socket_;
@synthesize readStream = readStream_;
@synthesize lastReadTransaction = lastReadTransaction_;
[super dealloc];
}
+
+// Getters /////////////////////////////////////////////////////////////////////
+#pragma mark Getters
+
/**
* Gets the port number
*/
return connected;
}
-/**
- * Called by SocketWrapper after the connection is successful. This immediately calls
- * -[SocketWrapper receive] to clear the way for communication, though the information
- * could be useful server information that we don't use right now.
- */
-- (void)socketDidAccept
-{
- connected = YES;
- transactionID = 1;
- stackFrames_ = [[NSMutableDictionary alloc] init];
- self.queuedWrites = [NSMutableArray array];
- writeQueueLock_ = [NSRecursiveLock new];
- callTable_ = [NSMutableDictionary new];
- callbackContext_ = [NSMutableDictionary new];
-}
-
-/**
- * Receives errors from the SocketWrapper and updates the display
- */
-- (void)errorEncountered:(NSString*)error
-{
- [delegate errorEncountered:error];
-}
+// Commands ////////////////////////////////////////////////////////////////////
+#pragma mark Commands
/**
* Reestablishes communication with the remote debugger so that a new connection doesn't have to be
return children;
}
+// Breakpoint Management ///////////////////////////////////////////////////////
#pragma mark Breakpoints
/**
[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]];
-}
-
/**
* Removes a breakpoint
*/
[self sendCommandWithCallback:nil format:@"breakpoint_remove -d %i", [bp debuggerId]];
}
-#pragma mark Socket and Stream Callbacks
+
+// Socket and Stream Callbacks /////////////////////////////////////////////////
+#pragma mark Callbacks
+
+/**
+ * Called by SocketWrapper after the connection is successful. This immediately calls
+ * -[SocketWrapper receive] to clear the way for communication, though the information
+ * could be useful server information that we don't use right now.
+ */
+- (void)socketDidAccept
+{
+ connected = YES;
+ transactionID = 1;
+ stackFrames_ = [[NSMutableDictionary alloc] init];
+ self.queuedWrites = [NSMutableArray array];
+ writeQueueLock_ = [NSRecursiveLock new];
+ callTable_ = [NSMutableDictionary new];
+ callbackContext_ = [NSMutableDictionary new];
+}
+
+/**
+ * Receives errors from the SocketWrapper and updates the display
+ */
+- (void)errorEncountered:(NSString*)error
+{
+ [delegate errorEncountered:error];
+}
/**
* Creates, connects to, and schedules a CFSocket.
}
}
-#pragma mark Response Handlers
-
- (void)handleResponse:(NSXMLDocument*)response
{
// Check and see if there's an error.
[self sendQueuedWrites];
}
+// Specific Response Handlers //////////////////////////////////////////////////
+#pragma mark Response Handlers
+
/**
* Initial packet received. We've started a brand-new connection to the engine.
*/
frame.variables = variables;
}
+/**
+ * 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]];
+}
+
#pragma mark Private
/**
#import <Cocoa/Cocoa.h>
#import "BSSourceView.h"
-#import "GDBpConnection.h"
+#import "DebuggerConnection.h"
#import "StackController.h"
-@interface DebuggerController : NSWindowController <GDBpConnectionDelegate>
+@interface DebuggerController : NSWindowController <DebuggerConnectionDelegate>
{
- GDBpConnection* connection;
+ DebuggerConnection* connection;
// This is true when the |connection| has told us to clobber. We will do
// so upon receipt of the first new stack frame.
IBOutlet BSSourceView* sourceViewer;
}
-@property(readonly) GDBpConnection* connection;
+@property(readonly) DebuggerConnection* connection;
@property(readonly) BSSourceView* sourceViewer;
@property(readonly) NSWindow* inspector;
stackController = [[StackController alloc] init];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
- connection = [[GDBpConnection alloc] initWithPort:[defaults integerForKey:@"Port"]];
+ connection = [[DebuggerConnection alloc] initWithPort:[defaults integerForKey:@"Port"]];
connection.delegate = self;
expandedVariables = [[NSMutableSet alloc] init];
[[self window] makeKeyAndOrderFront:nil];