1E95834C0E2531D5001A3D89 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1E95831F0E2531BD001A3D89 /* Sparkle.framework */; };
1EB7BED50ECF3CA90033283A /* StackFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB7BED40ECF3CA90033283A /* StackFrame.m */; };
1EBF4D5D0EE35F0700B62769 /* StackController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EBF4D5C0EE35F0700B62769 /* StackController.m */; };
+ 1EC1337E127DBB00007946FC /* VariableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC1337D127DBB00007946FC /* VariableNode.m */; };
1EEBFBE50D34C793008F835B /* Debugger.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1EEBFBE30D34C793008F835B /* Debugger.xib */; };
1EEBFC2B0D358EBD008F835B /* StepIn.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EEBFC2A0D358EBD008F835B /* StepIn.png */; };
1EEBFC370D358F1B008F835B /* StepOut.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EEBFC360D358F1B008F835B /* StepOut.png */; };
1EB7BED40ECF3CA90033283A /* StackFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StackFrame.m; path = Source/StackFrame.m; sourceTree = "<group>"; };
1EBF4D5B0EE35F0700B62769 /* StackController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackController.h; path = Source/StackController.h; sourceTree = "<group>"; };
1EBF4D5C0EE35F0700B62769 /* StackController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StackController.m; path = Source/StackController.m; sourceTree = "<group>"; };
+ 1EC1337C127DBB00007946FC /* VariableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VariableNode.h; path = Source/VariableNode.h; sourceTree = "<group>"; };
+ 1EC1337D127DBB00007946FC /* VariableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VariableNode.m; path = Source/VariableNode.m; sourceTree = "<group>"; };
1EEBFBE40D34C793008F835B /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/Debugger.xib; sourceTree = "<group>"; };
1EEBFC2A0D358EBD008F835B /* StepIn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StepIn.png; path = Icons/StepIn.png; sourceTree = "<group>"; };
1EEBFC360D358F1B008F835B /* StepOut.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StepOut.png; path = Icons/StepOut.png; sourceTree = "<group>"; };
1EB7BED40ECF3CA90033283A /* StackFrame.m */,
1EBF4D5B0EE35F0700B62769 /* StackController.h */,
1EBF4D5C0EE35F0700B62769 /* StackController.m */,
+ 1EC1337C127DBB00007946FC /* VariableNode.h */,
+ 1EC1337D127DBB00007946FC /* VariableNode.m */,
);
name = Debugger;
sourceTree = "<group>";
1E67E6FD0F3C052000E68F1B /* PreferencesPathsArrayController.m in Sources */,
1E6B5947116106FE001189D2 /* LoggingController.m in Sources */,
1E0724E311B47BCC0017AD3C /* DebuggerConnection.m in Sources */,
+ 1EC1337E127DBB00007946FC /* VariableNode.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+/*
+ * MacGDBp
+ * Copyright (c) 2010, Blue Static <http://www.bluestatic.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#import <Cocoa/Cocoa.h>
+
+// A VariableNode represents a property in the variable list display. It
+// converts XML response nodes to this format and extracts all the necessary
+// information. The fields of this class are defined by the spec:
+// http://www.xdebug.org/docs-dbgp.php#properties-variables-and-values
+@interface VariableNode : NSObject
+{
+ NSString* name_;
+ NSString* fullName_;
+ NSString* className_;
+ NSString* type_;
+ NSString* value_;
+ NSMutableArray* children_;
+ NSInteger childCount_;
+}
+
+@property (readonly, copy) NSString* name;
+@property (readonly, copy) NSString* fullName;
+@property (readonly, copy) NSString* className;
+@property (readonly, copy) NSString* type;
+@property (readonly, copy) NSString* value;
+@property (readonly, retain) NSArray* children;
+@property (readonly) NSInteger childCount;
+
+// Creates and initializes a new VariableNode from the XML response from the
+// debugger backend.
+- (id)initWithXMLNode:(NSXMLElement*)node;
+
+// When properties are asynchrnously loaded, this method can be used to set
+// the children on a node from the list of children from the XML response.
+- (void)setChildrenFromXMLChildren:(NSArray*)children;
+
+// Returns the children and requests any unloaded ones.
+- (NSArray*)dynamicChildren;
+
+// Whether or not this is a leaf node (i.e. does not have child properties).
+- (BOOL)isLeaf;
+
+// Returns a formatted type and classname display.
+- (NSString*)displayType;
+
+@end
--- /dev/null
+/*
+ * MacGDBp
+ * Copyright (c) 2010, Blue Static <http://www.bluestatic.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#import "VariableNode.h"
+
+#import "AppDelegate.h"
+#include "base64.h"
+
+// Private Properties //////////////////////////////////////////////////////////
+
+@interface VariableNode ()
+
+@property (copy) NSString* name;
+@property (copy) NSString* fullName;
+@property (copy) NSString* className;
+@property (copy) NSString* type;
+@property (copy) NSString* value;
+@property (retain) NSMutableArray* children;
+
+// Takes an XML node and computes the value.
+- (NSString*)decodeValueForNode:(NSXMLElement*)node;
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////
+
+@implementation VariableNode
+
+@synthesize name = name_;
+@synthesize fullName = fullName_;
+@synthesize className = className_;
+@synthesize type = type_;
+@synthesize value = value_;
+@synthesize children = children_;
+@synthesize childCount = childCount_;
+
+- (id)initWithXMLNode:(NSXMLElement*)node
+{
+ if (self = [super init]) {
+ self.name = [[node attributeForName:@"name"] stringValue];
+ self.fullName = [[node attributeForName:@"fullName"] stringValue];
+ self.className = [[node attributeForName:@"className"] stringValue];
+ self.type = [[node attributeForName:@"type"] stringValue];
+ self.value = [self decodeValueForNode:node];
+ self.children = [NSMutableArray array];
+ if ([node children]) {
+ [self setChildrenFromXMLChildren:[node children]];
+ }
+ childCount_ = [[[node attributeForName:@"numchildren"] stringValue] integerValue];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ self.name = nil;
+ self.fullName = nil;
+ self.className = nil;
+ self.type = nil;
+ self.value = nil;
+ self.children = nil;
+ [super dealloc];
+}
+
+- (void)setChildrenFromXMLChildren:(NSArray*)children
+{
+ for (NSXMLElement* child in children) {
+ VariableNode* node = [[VariableNode alloc] initWithXMLNode:child];
+ [children_ addObject:[node autorelease]];
+ }
+}
+
+- (NSArray*)dynamicChildren
+{
+ NSArray* children = self.children;
+ if (![self isLeaf] && [children count] < 1) {
+ // If this node has children but they haven't been loaded from the backend,
+ // request them asynchronously.
+ [[AppDelegate instance].debugger fetchProperty:self.fullName forNode:self];
+ }
+ return children;
+}
+
+- (BOOL)isLeaf
+{
+ return (self.childCount == 0);
+}
+
+- (NSString*)displayType
+{
+ if (self.className != nil) {
+ return [NSString stringWithFormat:@"%@ (%@)", self.className, self.type];
+ }
+ return self.type;
+}
+
+// Private /////////////////////////////////////////////////////////////////////
+
+- (NSString*)decodeValueForNode:(NSXMLElement*)node
+{
+ // Non-leaf nodes do not have a value:
+ // https://www.bluestatic.org/bugs/showreport.php?bugid=168
+ if (![self isLeaf]) {
+ return @"...";
+ }
+
+ // The value of the node is base64 encoded.
+ if ([[[node attributeForName:@"encoding"] stringValue] isEqualToString:@"base64"]) {
+ const char* str = [[node stringValue] UTF8String];
+ int strlen = [[node stringValue] length];
+
+ char* data;
+ size_t datalen;
+
+ if (!base64_decode_alloc(str, strlen, &data, &datalen))
+ NSLog(@"error in converting %@ from base64", self);
+
+ NSString* ret = nil;
+ if (data) {
+ ret = [NSString stringWithUTF8String:data];
+ free(data);
+ }
+
+ return ret;
+ }
+
+ // The value is just a normal string.
+ return [node stringValue];
+}
+
+@end