[Lldb-commits] [lldb] r136525 - in /lldb/trunk: examples/synthetic/CFString.py test/functionalities/data-formatter/data-formatter-objc/CFString.py test/functionalities/data-formatter/data-formatter-objc/Makefile test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py test/functionalities/data-formatter/data-formatter-objc/main.m

Enrico Granata granata.enrico at gmail.com
Fri Jul 29 14:31:47 PDT 2011


Author: enrico
Date: Fri Jul 29 16:31:46 2011
New Revision: 136525

URL: http://llvm.org/viewvc/llvm-project?rev=136525&view=rev
Log:
new synthetic children provider for CFString and related classes ; test case for it

Added:
    lldb/trunk/examples/synthetic/CFString.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m

Added: lldb/trunk/examples/synthetic/CFString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/CFString.py?rev=136525&view=auto
==============================================================================
--- lldb/trunk/examples/synthetic/CFString.py (added)
+++ lldb/trunk/examples/synthetic/CFString.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,206 @@
+# synthetic children provider for CFString
+# (and related NSString class)
+import lldb
+class CFStringSynthProvider:
+	def __init__(self,valobj,dict):
+		self.valobj = valobj;
+		self.update()
+	# children other than "content" are for debugging only and must not be used in production code
+	def num_children(self):
+		return 6;
+	def read_unicode(self, pointer):
+		process = self.valobj.GetTarget().GetProcess()
+		error = lldb.SBError()
+		pystr = u''
+		# cannot do the read at once because the length value has
+		# a weird encoding. better play it safe here
+		while True:
+			content = process.ReadMemory(pointer, 2, error)
+			new_bytes = bytearray(content)
+			b0 = new_bytes[0]
+			b1 = new_bytes[1]
+			pointer = pointer + 2
+			if b0 == 0 and b1 == 0:
+				break
+			# rearrange bytes depending on endianness
+			# (do we really need this or is Cocoa going to
+			#  use Windows-compatible little-endian even
+			#  if the target is big endian?)
+			if self.is_little:
+				value = b1 * 256 + b0
+			else:
+				value = b0 * 256 + b1
+			pystr = pystr + unichr(value)
+		return pystr
+	# handle the special case strings
+	# only use the custom code for the tested LP64 case
+	def handle_special(self):
+		if self.lp64 == False:
+			# for 32bit targets, use safe ObjC code
+			return self.handle_unicode_string_safe()
+		offset = 12
+		pointer = int(self.valobj.GetValue(), 0) + offset
+		pystr = self.read_unicode(pointer)
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+	# last resort call, use ObjC code to read; the final aim is to
+	# be able to strip this call away entirely and only do the read
+	# ourselves
+	def handle_unicode_string_safe(self):
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + self.valobj.GetObjectDescription() + "\"");
+	def handle_unicode_string(self):
+		# step 1: find offset
+		if self.inline:
+			pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+			if self.explicit == False:
+				# untested, use the safe code path
+				return self.handle_unicode_string_safe();
+			else:
+				# not sure why 8 bytes are skipped here
+				# (lldb) mem read -c 50 0x00000001001154f0
+				# 0x1001154f0: 98 1a 85 71 ff 7f 00 00 90 07 00 00 01 00 00 00  ...q?...........
+				# 0x100115500: 03 00 00 00 00 00 00 00 *c3 03 78 00 78 00 00 00  ........?.x.x...
+				# 0x100115510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+				# 0x100115520: 00 00                                            ..
+				# content begins at * (i.e. 8 bytes into variants, skipping void* buffer in
+				# __notInlineImmutable1 entirely, while the length byte is correctly located
+				# for an inline string)
+				pointer = pointer + 8;
+		else:
+			pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+			# read 8 bytes here and make an address out of them
+			vopointer = self.valobj.CreateChildAtOffset("dummy",
+				pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+			pointer = int(vopointer.GetValue(), 0)
+		# step 2: read Unicode data at pointer
+		pystr = self.read_unicode(pointer)
+		# step 3: return it
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+	# we read at "the right place" into the __CFString object instead of running code
+	# we are replicating the functionality of __CFStrContents in CFString.c here
+	def handle_UTF8_inline(self):
+		offset = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+		if self.explicit == False:
+			offset = offset + 1;
+		return self.valobj.CreateValueFromAddress("content",
+				offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+	def handle_UTF8_not_inline(self):
+		offset = self.size_of_cfruntime_base();
+		return self.valobj.CreateChildAtOffset("content",
+				offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+	def get_child_at_index(self,index):
+		if index == 0:
+			return self.valobj.CreateValueFromExpression("mutable",
+				str(int(self.mutable)));
+		if index == 1:
+			return self.valobj.CreateValueFromExpression("inline",
+				str(int(self.inline)));
+		if index == 2:
+			return self.valobj.CreateValueFromExpression("explicit",
+				str(int(self.explicit)));
+		if index == 3:
+			return self.valobj.CreateValueFromExpression("unicode",
+				str(int(self.unicode)));
+		if index == 4:
+			return self.valobj.CreateValueFromExpression("special",
+				str(int(self.special)));
+		if index == 5:
+			if self.unicode == True:
+				return self.handle_unicode_string();
+			elif self.special == True:
+				return self.handle_special();
+			elif self.inline == True:
+				return self.handle_UTF8_inline();
+			else:
+				return self.handle_UTF8_not_inline();
+	def get_child_index(self,name):
+		if name == "content":
+			return self.num_children() - 1;
+		if name == "mutable":
+			return 0;
+		if name == "inline":
+			return 1;
+		if name == "explicit":
+			return 2;
+		if name == "unicode":
+			return 3;
+		if name == "special":
+			return 4;
+	def is_64bit(self):
+		if self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8:
+			return True;
+		else:
+			return False;
+	def is_little_endian(self):
+		# 4 is eByteOrderLittle
+		if self.valobj.GetTarget().GetProcess().GetByteOrder() == 4:
+			return True;
+		else:
+			return False;
+	# CFRuntimeBase is defined as having an additional
+	# 4 bytes (padding?) on LP64 architectures
+	# to get its size we add up sizeof(pointer)+4
+	# and then add 4 more bytes if we are on a 64bit system
+	def size_of_cfruntime_base(self):
+		if self.lp64 == True:
+			return 8+4+4;
+		else:
+			return 4+4;
+	# the info bits are part of the CFRuntimeBase structure
+	# to get at them we have to skip a uintptr_t and then get
+	# at the least-significant byte of a 4 byte array. If we are
+	# on big-endian this means going to byte 3, if we are on
+	# little endian (OSX & iOS), this means reading byte 0
+	def offset_of_info_bits(self):
+		if self.lp64 == True:
+			offset = 8;
+		else:
+			offset = 4;
+		if self.is_little == False:
+			offset = offset + 3;
+		return offset;
+	def read_info_bits(self):
+		cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
+					self.offset_of_info_bits(),
+					self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+		cfinfo.SetFormat(11)
+		info = cfinfo.GetValue();
+		return int(info,0);
+	# calculating internal flag bits of the CFString object
+	# this stuff is defined and discussed in CFString.c
+	def is_mutable(self):
+		return (self.info_bits & 1) == 1;
+	def is_inline(self):
+		return (self.info_bits & 0x60) == 0;
+	# this flag's name is ambiguous, it turns out
+	# we must skip a length byte to get at the data
+	# when this flag is False
+	def has_explicit_length(self):
+		return (self.info_bits & (1 | 4)) != 4;
+	# probably a subclass of NSString. obtained this from [str pathExtension]
+	# here info_bits = 0 and Unicode data at the start of the padding word
+	# in the long run using the isa value might be safer as a way to identify this
+	# instead of reading the info_bits
+	def is_special_case(self):
+		return self.info_bits == 0;
+	def is_unicode(self):
+		return (self.info_bits & 0x10) == 0x10;
+	# preparing ourselves to read into memory
+	# by adjusting architecture-specific info
+	def adjust_for_architecture(self):
+		self.lp64 = self.is_64bit();
+		self.is_little = self.is_little_endian();
+	# reading info bits out of the CFString and computing
+	# useful values to get at the real data
+	def compute_flags(self):
+		self.info_bits = self.read_info_bits();
+		self.mutable = self.is_mutable();
+		self.inline = self.is_inline();
+		self.explicit = self.has_explicit_length();
+		self.unicode = self.is_unicode();
+		self.special = self.is_special_case();
+	def update(self):
+		self.adjust_for_architecture();
+		self.compute_flags();

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,206 @@
+# synthetic children provider for CFString
+# (and related NSString class)
+import lldb
+class CFStringSynthProvider:
+	def __init__(self,valobj,dict):
+		self.valobj = valobj;
+		self.update()
+	# children other than "content" are for debugging only and must not be used in production code
+	def num_children(self):
+		return 6;
+	def read_unicode(self, pointer):
+		process = self.valobj.GetTarget().GetProcess()
+		error = lldb.SBError()
+		pystr = u''
+		# cannot do the read at once because the length value has
+		# a weird encoding. better play it safe here
+		while True:
+			content = process.ReadMemory(pointer, 2, error)
+			new_bytes = bytearray(content)
+			b0 = new_bytes[0]
+			b1 = new_bytes[1]
+			pointer = pointer + 2
+			if b0 == 0 and b1 == 0:
+				break
+			# rearrange bytes depending on endianness
+			# (do we really need this or is Cocoa going to
+			#  use Windows-compatible little-endian even
+			#  if the target is big endian?)
+			if self.is_little:
+				value = b1 * 256 + b0
+			else:
+				value = b0 * 256 + b1
+			pystr = pystr + unichr(value)
+		return pystr
+	# handle the special case strings
+	# only use the custom code for the tested LP64 case
+	def handle_special(self):
+		if self.lp64 == False:
+			# for 32bit targets, use safe ObjC code
+			return self.handle_unicode_string_safe()
+		offset = 12
+		pointer = int(self.valobj.GetValue(), 0) + offset
+		pystr = self.read_unicode(pointer)
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+	# last resort call, use ObjC code to read; the final aim is to
+	# be able to strip this call away entirely and only do the read
+	# ourselves
+	def handle_unicode_string_safe(self):
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + self.valobj.GetObjectDescription() + "\"");
+	def handle_unicode_string(self):
+		# step 1: find offset
+		if self.inline:
+			pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+			if self.explicit == False:
+				# untested, use the safe code path
+				return self.handle_unicode_string_safe();
+			else:
+				# not sure why 8 bytes are skipped here
+				# (lldb) mem read -c 50 0x00000001001154f0
+				# 0x1001154f0: 98 1a 85 71 ff 7f 00 00 90 07 00 00 01 00 00 00  ...q?...........
+				# 0x100115500: 03 00 00 00 00 00 00 00 *c3 03 78 00 78 00 00 00  ........?.x.x...
+				# 0x100115510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+				# 0x100115520: 00 00                                            ..
+				# content begins at * (i.e. 8 bytes into variants, skipping void* buffer in
+				# __notInlineImmutable1 entirely, while the length byte is correctly located
+				# for an inline string)
+				pointer = pointer + 8;
+		else:
+			pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+			# read 8 bytes here and make an address out of them
+			vopointer = self.valobj.CreateChildAtOffset("dummy",
+				pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+			pointer = int(vopointer.GetValue(), 0)
+		# step 2: read Unicode data at pointer
+		pystr = self.read_unicode(pointer)
+		# step 3: return it
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+	# we read at "the right place" into the __CFString object instead of running code
+	# we are replicating the functionality of __CFStrContents in CFString.c here
+	def handle_UTF8_inline(self):
+		offset = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+		if self.explicit == False:
+			offset = offset + 1;
+		return self.valobj.CreateValueFromAddress("content",
+				offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+	def handle_UTF8_not_inline(self):
+		offset = self.size_of_cfruntime_base();
+		return self.valobj.CreateChildAtOffset("content",
+				offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+	def get_child_at_index(self,index):
+		if index == 0:
+			return self.valobj.CreateValueFromExpression("mutable",
+				str(int(self.mutable)));
+		if index == 1:
+			return self.valobj.CreateValueFromExpression("inline",
+				str(int(self.inline)));
+		if index == 2:
+			return self.valobj.CreateValueFromExpression("explicit",
+				str(int(self.explicit)));
+		if index == 3:
+			return self.valobj.CreateValueFromExpression("unicode",
+				str(int(self.unicode)));
+		if index == 4:
+			return self.valobj.CreateValueFromExpression("special",
+				str(int(self.special)));
+		if index == 5:
+			if self.unicode == True:
+				return self.handle_unicode_string();
+			elif self.special == True:
+				return self.handle_special();
+			elif self.inline == True:
+				return self.handle_UTF8_inline();
+			else:
+				return self.handle_UTF8_not_inline();
+	def get_child_index(self,name):
+		if name == "content":
+			return self.num_children() - 1;
+		if name == "mutable":
+			return 0;
+		if name == "inline":
+			return 1;
+		if name == "explicit":
+			return 2;
+		if name == "unicode":
+			return 3;
+		if name == "special":
+			return 4;
+	def is_64bit(self):
+		if self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8:
+			return True;
+		else:
+			return False;
+	def is_little_endian(self):
+		# 4 is eByteOrderLittle
+		if self.valobj.GetTarget().GetProcess().GetByteOrder() == 4:
+			return True;
+		else:
+			return False;
+	# CFRuntimeBase is defined as having an additional
+	# 4 bytes (padding?) on LP64 architectures
+	# to get its size we add up sizeof(pointer)+4
+	# and then add 4 more bytes if we are on a 64bit system
+	def size_of_cfruntime_base(self):
+		if self.lp64 == True:
+			return 8+4+4;
+		else:
+			return 4+4;
+	# the info bits are part of the CFRuntimeBase structure
+	# to get at them we have to skip a uintptr_t and then get
+	# at the least-significant byte of a 4 byte array. If we are
+	# on big-endian this means going to byte 3, if we are on
+	# little endian (OSX & iOS), this means reading byte 0
+	def offset_of_info_bits(self):
+		if self.lp64 == True:
+			offset = 8;
+		else:
+			offset = 4;
+		if self.is_little == False:
+			offset = offset + 3;
+		return offset;
+	def read_info_bits(self):
+		cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
+					self.offset_of_info_bits(),
+					self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+		cfinfo.SetFormat(11)
+		info = cfinfo.GetValue();
+		return int(info,0);
+	# calculating internal flag bits of the CFString object
+	# this stuff is defined and discussed in CFString.c
+	def is_mutable(self):
+		return (self.info_bits & 1) == 1;
+	def is_inline(self):
+		return (self.info_bits & 0x60) == 0;
+	# this flag's name is ambiguous, it turns out
+	# we must skip a length byte to get at the data
+	# when this flag is False
+	def has_explicit_length(self):
+		return (self.info_bits & (1 | 4)) != 4;
+	# probably a subclass of NSString. obtained this from [str pathExtension]
+	# here info_bits = 0 and Unicode data at the start of the padding word
+	# in the long run using the isa value might be safer as a way to identify this
+	# instead of reading the info_bits
+	def is_special_case(self):
+		return self.info_bits == 0;
+	def is_unicode(self):
+		return (self.info_bits & 0x10) == 0x10;
+	# preparing ourselves to read into memory
+	# by adjusting architecture-specific info
+	def adjust_for_architecture(self):
+		self.lp64 = self.is_64bit();
+		self.is_little = self.is_little_endian();
+	# reading info bits out of the CFString and computing
+	# useful values to get at the real data
+	def compute_flags(self):
+		self.info_bits = self.read_info_bits();
+		self.mutable = self.is_mutable();
+		self.inline = self.is_inline();
+		self.explicit = self.has_explicit_length();
+		self.unicode = self.is_unicode();
+		self.special = self.is_special_case();
+	def update(self):
+		self.adjust_for_architecture();
+		self.compute_flags();

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile Fri Jul 29 16:31:46 2011
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,231 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class DataFormatterTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "data-formatter", "data-formatter-objc")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    def test_with_dsym_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDsym()
+        self.data_formatter_commands()
+
+    def test_with_dwarf_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDwarf()
+        self.data_formatter_commands()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to break at.
+        self.line = line_number('main.m', '// Set break point at this line.')
+
+    def data_formatter_commands(self):
+        """Test that that file and class static variables display correctly."""
+        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+        self.expect("breakpoint set -f main.m -l %d" % self.line,
+                    BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: file ='main.m', line = %d, locations = 1" %
+                        self.line)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # This is the function to remove the custom formats in order to have a
+        # clean slate for the next test case.
+        def cleanup():
+            self.runCmd('type format clear', check=False)
+            self.runCmd('type summary clear', check=False)
+            self.runCmd('type synth clear', check=False)
+
+        # Execute the cleanup function during test case tear down.
+        self.addTearDownHook(cleanup)
+
+        self.runCmd("type summary add -f \"${var%@}\" MyClass")
+
+        self.expect("frame variable object2",
+            substrs = ['MyOtherClass']);
+        
+        self.expect("frame variable *object2",
+            substrs = ['MyOtherClass']);
+
+        # Now let's delete the 'MyClass' custom summary.
+        self.runCmd("type summary delete MyClass")
+
+        # The type format list should not show 'MyClass' at this point.
+        self.expect("type summary list", matching=False,
+            substrs = ['MyClass'])
+
+        self.runCmd("type summary add -f \"a test\" MyClass")
+        
+        self.expect("frame variable object2",
+                    substrs = ['a test']);
+        
+        self.expect("frame variable *object2",
+                    substrs = ['a test']);
+
+        self.expect("frame variable object",
+                    substrs = ['a test']);
+        
+        self.expect("frame variable *object",
+                    substrs = ['a test']);
+
+        self.runCmd("type summary add -f \"a test\" MyClass -C no")
+        
+        self.expect("frame variable *object2",
+                    substrs = ['*object2 = {',
+                               'MyClass = a test',
+                               'backup = ']);
+        
+        self.expect("frame variable object2", matching=False,
+                    substrs = ['a test']);
+        
+        self.expect("frame variable object",
+                    substrs = ['a test']);
+        
+        self.expect("frame variable *object",
+                    substrs = ['a test']);
+
+        # Now check that the synth for CFString works
+        self.runCmd("script from CFString import *")
+        self.runCmd("type synth add -l CFStringSynthProvider NSString")
+
+        self.expect('frame variable str -P 1',
+            substrs = ['mutable =',
+                       'inline = ',
+                       'explicit = ',
+                       'content = ',
+                       'A rather short ASCII NSString object is here'])
+
+        self.expect('frame variable str2 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'A rather short UTF8 NSString object is here'])
+
+        self.expect('frame variable str3 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'A string made with the at sign is here'])
+
+        self.expect('frame variable str4 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'This is string number 4 right here'])
+        
+        self.expect('frame variable str5 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               '{{1, 1}, {5, 5}}'])
+                
+        self.expect('frame variable str6 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               '1ST'])
+        
+        self.expect('frame variable str7 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               '\\xcf\\x83xx'])
+        
+        self.expect('frame variable str8 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'hasVeryLongExtensionThisTime'])
+
+        self.expect('frame variable str9 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+        
+        self.expect('frame variable str10 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'This is a Unicode string \\xcf\\x83 number 4 right here'])
+        
+        self.expect('frame variable str11 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               '__NSCFString'])
+        
+        self.expect('frame variable processName -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'a.out'])
+        
+        self.expect('frame variable str12 -P 1',
+                    substrs = ['mutable =',
+                               'inline = ',
+                               'explicit = ',
+                               'content = ',
+                               'Process Name:  a.out Process Id:'])
+        
+        # make it a summary
+        self.runCmd("type summary add -f \"${svar.content}\" NSString")
+
+        self.expect('frame variable str',
+            substrs = ['A rather short ASCII NSString object is here'])
+        self.expect('frame variable str2',
+                    substrs = ['A rather short UTF8 NSString object is here'])
+        self.expect('frame variable str3',
+                    substrs = ['A string made with the at sign is here'])
+        self.expect('frame variable str4',
+                    substrs = ['This is string number 4 right here'])
+        self.expect('frame variable str5',
+                    substrs = ['{{1, 1}, {5, 5}}'])
+        self.expect('frame variable str6',
+                    substrs = ['1ST'])
+        self.expect('frame variable str7',
+                    substrs = ['\\xcf\\x83xx'])
+        self.expect('frame variable str8',
+                    substrs = ['hasVeryLongExtensionThisTime'])
+        self.expect('frame variable str9',
+                    substrs = ['a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+        self.expect('frame variable str10',
+                    substrs = ['This is a Unicode string \\xcf\\x83 number 4 right here'])
+        self.expect('frame variable str11',
+                    substrs = ['__NSCFString'])
+        self.expect('frame variable processName',
+                    substrs = ['a.out'])        
+        self.expect('frame variable str12',
+                    substrs = ['Process Name:  a.out Process Id:'])
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m Fri Jul 29 16:31:46 2011
@@ -0,0 +1,124 @@
+//===-- main.m ------------------------------------------------*- ObjC -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#import <Foundation/Foundation.h>
+
+ at interface MyClass : NSObject
+{
+    int i;
+    char c;
+    float f; 
+}
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z;
+- (int)doIncrementByInt: (int)x;
+
+ at end
+
+ at interface MyOtherClass : MyClass
+{
+    int i2;
+    MyClass *backup;
+}
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q;
+
+ at end
+
+ at implementation MyClass
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z
+{
+    self = [super init];
+    if (self) {
+        self->i = x;
+        self->f = y;
+        self->c = z;
+    }    
+    return self;
+}
+
+- (int)doIncrementByInt: (int)x
+{
+    self->i += x;
+    return self->i;
+}
+
+ at end
+
+ at implementation MyOtherClass
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q
+{
+    self = [super initWithInt:x andFloat:y andChar:z];
+    if (self) {
+        self->i2 = q;
+        self->backup = [[MyClass alloc] initWithInt:x andFloat:y andChar:z];
+    }    
+    return self;
+}
+
+ at end
+
+int main (int argc, const char * argv[])
+{
+    
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    
+    MyClass *object = [[MyClass alloc] initWithInt:1 andFloat:3.14 andChar: 'E'];
+    
+    [object doIncrementByInt:3];
+    
+    MyOtherClass *object2 = [[MyOtherClass alloc] initWithInt:2 andFloat:6.28 andChar: 'G' andOtherInt:-1];
+    
+    [object2 doIncrementByInt:3];
+    
+    NSString *str = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding];
+    
+    NSString *str2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"];
+    
+    NSString *str3 = @"A string made with the at sign is here";
+    
+    NSString *str4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4];
+    
+    NSRect rect = NSMakeRect(1,1,5,5);
+    
+    NSString* str5 = NSStringFromRect(rect);
+    
+    NSString* str6 = [@"/usr/doc/README.1ST" pathExtension];
+    
+    const unichar myCharacters[] = {0x03C3,'x','x'};
+    NSString *str7 = [NSString stringWithCharacters: myCharacters
+                                                 length: sizeof myCharacters / sizeof *myCharacters];
+        
+    NSString* str8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension];
+    
+    const unichar myOtherCharacters[] = {'a',' ', 'v','e','r','y',' ',
+    'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k',
+    ' ','t','o',' ','w','r','i','t','e', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ',
+    't','h','i','s',' ','w','a','y','!','!','0x03C3'};
+    NSString *str9 = [NSString stringWithCharacters: myOtherCharacters
+                                             length: sizeof myOtherCharacters / sizeof *myOtherCharacters];
+    
+    const unichar myNextCharacters[] = {0x03C3, 0x0000};
+    
+    NSString *str10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4];
+    
+    NSString *str11 = [str10 className];
+    
+    NSString *label1 = @"Process Name: ";
+    NSString *label2 = @"Process Id: ";
+    NSString *processName = [[NSProcessInfo processInfo] processName];
+    NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];
+    NSString *str12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID];
+    
+    // Set break point at this line.
+    [pool drain];
+    return 0;
+}
+





More information about the lldb-commits mailing list