diff --git a/Source/CDLCSymbolTable.m b/Source/CDLCSymbolTable.m index 080890be..8a0cb18b 100644 --- a/Source/CDLCSymbolTable.m +++ b/Source/CDLCSymbolTable.m @@ -127,6 +127,11 @@ - (void)loadSymbols; CDSymbol *symbol = [[CDSymbol alloc] initWithName:str machOFile:self.machOFile nlist32:nlist]; [_symbols addObject:symbol]; + + if ([str hasPrefix:ObjCClassSymbolPrefix] && symbol.value != 0) { + NSString *className = [str substringFromIndex:[ObjCClassSymbolPrefix length]]; + [_classSymbols setObject:symbol forKey:className]; + } } //NSLog(@"Loaded %lu 32-bit symbols", [symbols count]); @@ -151,7 +156,7 @@ - (void)loadSymbols; CDSymbol *symbol = [[CDSymbol alloc] initWithName:str machOFile:self.machOFile nlist64:nlist]; [_symbols addObject:symbol]; - if ([str hasPrefix:ObjCClassSymbolPrefix] && [symbol value] != 0) { + if ([str hasPrefix:ObjCClassSymbolPrefix] && symbol.value != 0) { NSString *className = [str substringFromIndex:[ObjCClassSymbolPrefix length]]; [_classSymbols setObject:symbol forKey:className]; } diff --git a/Source/CDMultiFileVisitor.m b/Source/CDMultiFileVisitor.m index 2e6fbdd5..d7a17267 100644 --- a/Source/CDMultiFileVisitor.m +++ b/Source/CDMultiFileVisitor.m @@ -235,9 +235,9 @@ - (NSString *)importStringForProtocolName:(NSString *)name; if (name != nil) { NSString *framework = [self frameworkForProtocolName:name]; if (framework == nil) - return [NSString stringWithFormat:@"#import \"%@.h\"\n", name]; + return [NSString stringWithFormat:@"#import \"%@-Protocol.h\"\n", name]; else - return [NSString stringWithFormat:@"#import <%@/%@.h>\n", framework, name]; + return [NSString stringWithFormat:@"#import <%@/%@-Protocol.h>\n", framework, name]; } return nil; diff --git a/Source/CDOCIvar.h b/Source/CDOCIvar.h index d565c13f..4545bfda 100644 --- a/Source/CDOCIvar.h +++ b/Source/CDOCIvar.h @@ -9,11 +9,13 @@ @interface CDOCIvar : NSObject -- (id)initWithName:(NSString *)name type:(NSString *)aType offset:(NSUInteger)offset; +- (id)initWithName:(NSString *)name type:(NSString *)aType offset:(NSUInteger)offset alignment:(NSUInteger)alignment size:(NSUInteger)size; @property (readonly) NSString *name; @property (readonly) NSString *type; @property (readonly) NSUInteger offset; +@property (readonly) NSUInteger alignment; +@property (readonly) NSUInteger size; @property (nonatomic, readonly) CDType *parsedType; diff --git a/Source/CDOCIvar.m b/Source/CDOCIvar.m index 41e82a40..ec4e8108 100644 --- a/Source/CDOCIvar.m +++ b/Source/CDOCIvar.m @@ -22,17 +22,21 @@ @implementation CDOCIvar NSString *name; NSString *type; NSUInteger offset; + NSUInteger alignment; + NSUInteger size; BOOL hasParsedType; CDType *parsedType; } -- (id)initWithName:(NSString *)aName type:(NSString *)aType offset:(NSUInteger)anOffset; +- (id)initWithName:(NSString *)aName type:(NSString *)aType offset:(NSUInteger)anOffset alignment:(NSUInteger)anAlignment size:(NSUInteger)aSize; { if ((self = [super init])) { name = aName; type = aType; offset = anOffset; + alignment = anAlignment; + size = aSize; hasParsedType = NO; parsedType = nil; @@ -54,6 +58,8 @@ - (NSString *)description; @synthesize name; @synthesize type; @synthesize offset; +@synthesize alignment; +@synthesize size; @synthesize hasParsedType; - (CDType *)parsedType; @@ -66,6 +72,10 @@ - (CDType *)parsedType; if (parsedType == nil) NSLog(@"Warning: Parsing ivar type failed, %@", name); + if (parsedType.isBitfieldType) { + [parsedType setUnderlyingType:size]; + } + self.hasParsedType = YES; } @@ -74,7 +84,7 @@ - (CDType *)parsedType; - (void)appendToString:(NSMutableString *)resultString typeController:(CDTypeController *)typeController; { - NSString *formattedString = [[typeController ivarTypeFormatter] formatVariable:name type:type]; + NSString *formattedString = [[typeController ivarTypeFormatter] formatVariable:name parsedType:[self parsedType]]; if (formattedString != nil) { [resultString appendString:formattedString]; [resultString appendString:@";"]; diff --git a/Source/CDOCMethod.m b/Source/CDOCMethod.m index 32d12374..2166b836 100644 --- a/Source/CDOCMethod.m +++ b/Source/CDOCMethod.m @@ -53,7 +53,7 @@ - (id)initWithName:(NSString *)aName type:(NSString *)aType; - (id)copyWithZone:(NSZone *)zone; { - return [[CDOCMethod alloc] initWithName:name type:type imp:imp]; + return [[CDOCMethod allocWithZone:zone] initWithName:name type:type imp:imp]; } #pragma mark - Debugging diff --git a/Source/CDObjectiveC1Processor.m b/Source/CDObjectiveC1Processor.m index d82d016c..c292cd03 100644 --- a/Source/CDObjectiveC1Processor.m +++ b/Source/CDObjectiveC1Processor.m @@ -288,7 +288,7 @@ - (CDOCClass *)processClassDefinitionAtAddress:(uint32_t)address; // bitfields don't need names. // NSIconRefBitmapImageRep in AppKit on 10.5 has a single-bit bitfield, plus an unnamed 31-bit field. if (type != nil) { - CDOCIvar *anIvar = [[CDOCIvar alloc] initWithName:name type:type offset:objcIvar.offset]; + CDOCIvar *anIvar = [[CDOCIvar alloc] initWithName:name type:type offset:objcIvar.offset alignment:0 size:0]; [ivars addObject:anIvar]; } } diff --git a/Source/CDObjectiveC2Processor.m b/Source/CDObjectiveC2Processor.m index 0af6e295..19f1d311 100644 --- a/Source/CDObjectiveC2Processor.m +++ b/Source/CDObjectiveC2Processor.m @@ -411,7 +411,7 @@ - (NSArray *)loadIvarsAtAddress:(uint64_t)address; NSString *name = [self.machOFile stringAtAddress:objc2Ivar.name]; NSString *type = [self.machOFile stringAtAddress:objc2Ivar.type]; - CDOCIvar *ivar = [[CDOCIvar alloc] initWithName:name type:type offset:objc2Ivar.offset]; + CDOCIvar *ivar = [[CDOCIvar alloc] initWithName:name type:type offset:objc2Ivar.offset alignment:objc2Ivar.alignment size:objc2Ivar.size]; [ivars addObject:ivar]; } else { //NSLog(@"%016lx %016lx %016lx %08x %08x", objc2Ivar.offset, objc2Ivar.name, objc2Ivar.type, objc2Ivar.alignment, objc2Ivar.size); diff --git a/Source/CDStructureInfo.m b/Source/CDStructureInfo.m index 82815a0a..c7062cdb 100644 --- a/Source/CDStructureInfo.m +++ b/Source/CDStructureInfo.m @@ -34,7 +34,7 @@ - (id)initWithType:(CDType *)type; - (id)copyWithZone:(NSZone *)zone; { - CDStructureInfo *copy = [[CDStructureInfo alloc] initWithType:self.type]; // type gets copied + CDStructureInfo *copy = [[CDStructureInfo allocWithZone:zone] initWithType:self.type]; // type gets copied copy.referenceCount = self.referenceCount; copy.isUsedInMethod = self.isUsedInMethod; copy.typedefName = self.typedefName; diff --git a/Source/CDStructureTable.m b/Source/CDStructureTable.m index dae1bbdc..9479fe2f 100644 --- a/Source/CDStructureTable.m +++ b/Source/CDStructureTable.m @@ -825,6 +825,7 @@ - (void)appendTypedefsToString:(NSMutableString *)resultString [resultString appendFormat:@"// depth: %u, ref: %u, used in method? %u\n", info.type.structureDepth, info.referenceCount, info.isUsedInMethod]; } + typeFormatter.shouldExpand = NO; NSString *formattedString = [typeFormatter formatVariable:nil parsedType:info.type]; if (formattedString != nil) { //[resultString appendFormat:@"%@;\n\n", formattedString]; diff --git a/Source/CDTextClassDumpVisitor.m b/Source/CDTextClassDumpVisitor.m index 909d9885..663a4b7e 100644 --- a/Source/CDTextClassDumpVisitor.m +++ b/Source/CDTextClassDumpVisitor.m @@ -10,6 +10,7 @@ #import "CDOCCategory.h" #import "CDOCMethod.h" #import "CDOCProperty.h" +#import "CDType.h" #import "CDTypeController.h" #import "CDTypeFormatter.h" #import "CDVisitorPropertyState.h" @@ -45,7 +46,7 @@ - (id)init; - (void)willVisitClass:(CDOCClass *)aClass; { if (aClass.isExported == NO) - [self.resultString appendString:@"// Not exported\n"]; + [self.resultString appendString:@"__attribute__((visibility(\"hidden\")))\n"]; [self.resultString appendFormat:@"@interface %@", aClass.name]; if (aClass.superClassName != nil) @@ -284,6 +285,10 @@ - (void)_visitProperty:(CDOCProperty *)property parsedType:(CDType *)parsedType if (isWeak) [self.resultString appendString:@"__weak "]; + if ([alist containsObject:@"retain"] || [alist containsObject:@"copy"]) + if (!parsedType.isGarbageCollectedType) + [self.resultString appendString:@"__attribute__((NSObject)) "]; + NSString *formattedString = [self.classDump.typeController.propertyTypeFormatter formatVariable:property.name parsedType:parsedType]; [self.resultString appendFormat:@"%@;", formattedString]; diff --git a/Source/CDType.h b/Source/CDType.h index 79462338..ca43cf44 100644 --- a/Source/CDType.h +++ b/Source/CDType.h @@ -15,17 +15,23 @@ - (id)initIDTypeWithProtocols:(NSArray *)protocols; - (id)initStructType:(CDTypeName *)name members:(NSArray *)members; - (id)initUnionType:(CDTypeName *)name members:(NSArray *)members; -- (id)initBitfieldType:(NSString *)bitfieldSize; -- (id)initArrayType:(CDType *)type count:(NSString *)count; +- (id)initBitfieldType:(int)bitfieldSize; +- (id)initArrayType:(CDType *)type count:(int)count; - (id)initPointerType:(CDType *)type; +- (id)initFunctionPointerType; +- (id)initBlockType; - (id)initModifier:(int)modifier type:(CDType *)type; +- (void)setUnderlyingType:(NSUInteger)underlyingWidth; + @property (strong) NSString *variableName; @property (nonatomic, readonly) int type; @property (readonly) BOOL isIDType; @property (readonly) BOOL isNamedObject; @property (readonly) BOOL isTemplateType; +@property (readonly) BOOL isGarbageCollectedType; +@property (readonly) BOOL isBitfieldType; @property (nonatomic, readonly) CDType *subtype; @property (nonatomic, readonly) CDTypeName *typeName; @@ -64,3 +70,5 @@ - (void)phase3MergeWithTypeController:(CDTypeController *)typeController; @end + +extern BOOL global_shouldMangleTemplateTypes; diff --git a/Source/CDType.m b/Source/CDType.m index d460219b..b3f9fec8 100644 --- a/Source/CDType.m +++ b/Source/CDType.m @@ -11,6 +11,8 @@ #import "CDTypeFormatter.h" #import "CDTypeParser.h" +BOOL global_shouldMangleTemplateTypes = NO; + static BOOL debugMerge = NO; @interface CDType () @@ -38,8 +40,9 @@ @implementation CDType CDType *subtype; CDTypeName *typeName; NSMutableArray *members; - NSString *bitfieldSize; - NSString *arraySize; + int bitfieldSize; + int widthOfUnderlyingType; + int arraySize; NSString *variableName; } @@ -53,8 +56,9 @@ - (id)init; typeName = nil; members = nil; variableName = nil; - bitfieldSize = nil; - arraySize = nil; + bitfieldSize = -1; + widthOfUnderlyingType = -1; + arraySize = -1; } return self; @@ -120,17 +124,18 @@ - (id)initUnionType:(CDTypeName *)aName members:(NSArray *)someMembers; return self; } -- (id)initBitfieldType:(NSString *)aBitfieldSize; +- (id)initBitfieldType:(int)aBitfieldSize; { if ((self = [self init])) { type = 'b'; bitfieldSize = aBitfieldSize; + widthOfUnderlyingType = 0; /* to be set later */ } return self; } -- (id)initArrayType:(CDType *)aType count:(NSString *)aCount; +- (id)initArrayType:(CDType *)aType count:(int)aCount; { if ((self = [self init])) { type = '['; @@ -151,6 +156,24 @@ - (id)initPointerType:(CDType *)aType; return self; } +- (id)initFunctionPointerType +{ + if ((self = [self init])) { + type = T_FUNCTION_POINTER_TYPE; + } + + return self; +} + +- (id)initBlockType +{ + if ((self = [self init])) { + type = T_BLOCK_TYPE; + } + + return self; +} + - (id)initModifier:(int)aModifier type:(CDType *)aType; { if ((self = [self init])) { @@ -161,6 +184,12 @@ - (id)initModifier:(int)aModifier type:(CDType *)aType; return self; } +- (void)setUnderlyingType:(int)aWidth; +{ + assert(type == 'b'); + widthOfUnderlyingType = aWidth; +} + #pragma mark - NSCopying // An easy deep copy. @@ -179,6 +208,7 @@ - (id)copyWithZone:(NSZone *)zone; NSParameterAssert([str isEqualToString:copiedType.typeString]); [copiedType setVariableName:variableName]; + copiedType->widthOfUnderlyingType = widthOfUnderlyingType; return copiedType; } @@ -195,7 +225,7 @@ - (BOOL)isEqual:(CDType *)otherType; - (NSString *)description; { - return [NSString stringWithFormat:@"[%@] type: %d('%c'), name: %@, subtype: %@, bitfieldSize: %@, arraySize: %@, members: %@, variableName: %@", + return [NSString stringWithFormat:@"[%@] type: %d('%c'), name: %@, subtype: %@, bitfieldSize: %d, arraySize: %d, members: %@, variableName: %@", NSStringFromClass([self class]), type, type, typeName, subtype, bitfieldSize, arraySize, members, variableName]; } @@ -223,6 +253,17 @@ - (BOOL)isTemplateType; return typeName.isTemplateType; } +- (BOOL)isGarbageCollectedType; +{ + return self.isIDType || self.isNamedObject || + self.type == '#' || self.type == T_BLOCK_TYPE; +} + +- (BOOL)isBitfieldType; +{ + return self.type == 'b'; +} + - (CDType *)subtype; { return subtype; @@ -273,7 +314,6 @@ - (NSUInteger)structureDepth; - (NSString *)formattedString:(NSString *)previousName formatter:(CDTypeFormatter *)typeFormatter level:(NSUInteger)level; { NSString *result, *currentName; - NSString *baseType, *memberString; assert(variableName == nil || previousName == nil); if (variableName != nil) @@ -305,78 +345,81 @@ - (NSString *)formattedString:(NSString *)previousName formatter:(CDTypeFormatte } break; - case 'b': - if (currentName == nil) { - // This actually compiles! - result = [NSString stringWithFormat:@"unsigned int :%@", bitfieldSize]; - } else - result = [NSString stringWithFormat:@"unsigned int %@:%@", currentName, bitfieldSize]; + case 'b': { + switch (widthOfUnderlyingType) { + case 1: result = @"unsigned char "; break; + case 2: result = @"unsigned short "; break; + case 4: result = @"unsigned int "; break; + case 8: result = @"unsigned long long "; break; + default: + /* This path is reachable in ObjC 1.0, where ivars don't + * specify their sizes. It's also reachable if the bitfield + * is a member of a C struct. */ + if (bitfieldSize > 32) { + result = @"unsigned long long "; + } else { + result = @"unsigned int "; + } + break; + } + if (currentName != nil) { + result = [result stringByAppendingString:currentName]; + } + result = [NSString stringWithFormat:@"%@:%d", result, bitfieldSize]; break; + } case '[': if (currentName == nil) - result = [NSString stringWithFormat:@"[%@]", arraySize]; + result = [NSString stringWithFormat:@"[%d]", arraySize]; else - result = [NSString stringWithFormat:@"%@[%@]", currentName, arraySize]; + result = [NSString stringWithFormat:@"%@[%d]", currentName, arraySize]; result = [subtype formattedString:result formatter:typeFormatter level:level]; break; - case '(': - baseType = nil; - /*if (typeName == nil || [@"?" isEqual:[typeName description]])*/ { - NSString *typedefName = [typeFormatter typedefNameForStruct:self level:level]; - if (typedefName != nil) { - baseType = typedefName; - } - } - - if (baseType == nil) { - if (typeName == nil || [@"?" isEqual:[typeName description]]) - baseType = @"union"; - else - baseType = [NSString stringWithFormat:@"union %@", typeName]; - - if ((typeFormatter.shouldAutoExpand && [typeFormatter.typeController shouldExpandType:self] && [members count] > 0) - || (level == 0 && typeFormatter.shouldExpand && [members count] > 0)) - memberString = [NSString stringWithFormat:@" {\n%@%@}", - [self formattedStringForMembersAtLevel:level + 1 formatter:typeFormatter], - [NSString spacesIndentedToLevel:typeFormatter.baseLevel + level spacesPerLevel:4]]; - else - memberString = @""; - - baseType = [baseType stringByAppendingString:memberString]; - } - - if (currentName == nil /*|| [currentName hasPrefix:@"?"]*/) // Not sure about this - result = baseType; - else - result = [NSString stringWithFormat:@"%@ %@", baseType, currentName]; - break; - case '{': - baseType = nil; - /*if (typeName == nil || [@"?" isEqual:[typeName description]])*/ { - NSString *typedefName = [typeFormatter typedefNameForStruct:self level:level]; - if (typedefName != nil) { - baseType = typedefName; - } + case '(': { + NSString *struct_or_union = (type == '{' ? @"struct" : @"union"); + NSString *baseType = [typeFormatter typedefNameForStruct:self level:level]; + NSString *type_name = [self.typeName description]; + + if ([@"?" isEqual:type_name]) + type_name = nil; + + if (global_shouldMangleTemplateTypes && (type_name != nil)) { + NSString *legitCharacters = @"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" "0123456789"; + + NSCharacterSet *illegitCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:legitCharacters] invertedSet]; + type_name = [[type_name componentsSeparatedByCharactersInSet:illegitCharacterSet] componentsJoinedByString:@"_"]; } + if (baseType == nil) { - if (typeName == nil || [@"?" isEqual:[typeName description]]) - baseType = @"struct"; - else - baseType = [NSString stringWithFormat:@"struct %@", typeName]; - - if ((typeFormatter.shouldAutoExpand && [typeFormatter.typeController shouldExpandType:self] && [members count] > 0) - || (level == 0 && typeFormatter.shouldExpand && [members count] > 0)) - memberString = [NSString stringWithFormat:@" {\n%@%@}", - [self formattedStringForMembersAtLevel:level + 1 formatter:typeFormatter], - [NSString spacesIndentedToLevel:typeFormatter.baseLevel + level spacesPerLevel:4]]; - else - memberString = @""; + BOOL print_members = NO; + + if (typeFormatter.shouldAutoExpand && [typeFormatter.typeController shouldExpandType:self]) { + /* In these cases, "members" may be empty to indicate that + * this type is already defined and must not be repeated. */ + print_members = ([members count] > 0); + } else if (level == 0 && typeFormatter.shouldExpand) { + print_members = ([members count] > 0); + } + + if (type_name == nil) { + /* If the type has no name, we MUST print its members. */ + baseType = struct_or_union; + print_members = YES; + } else { + baseType = [NSString stringWithFormat:@"%@ %@", struct_or_union, type_name]; + } - baseType = [baseType stringByAppendingString:memberString]; + if (print_members) { + NSString *memberString = [NSString stringWithFormat:@" {\n%@%@}", + [self formattedStringForMembersAtLevel:level + 1 formatter:typeFormatter], + [NSString spacesIndentedToLevel:typeFormatter.baseLevel + level spacesPerLevel:4]]; + baseType = [baseType stringByAppendingString:memberString]; + } } if (currentName == nil /*|| [currentName hasPrefix:@"?"]*/) // Not sure about this @@ -384,7 +427,7 @@ - (NSString *)formattedString:(NSString *)previousName formatter:(CDTypeFormatte else result = [NSString stringWithFormat:@"%@ %@", baseType, currentName]; break; - + } case '^': if (currentName == nil) result = @"*"; @@ -397,6 +440,20 @@ - (NSString *)formattedString:(NSString *)previousName formatter:(CDTypeFormatte result = [subtype formattedString:result formatter:typeFormatter level:level]; break; + case T_FUNCTION_POINTER_TYPE: + if (currentName == nil) + result = @"void(*)()"; + else + result = [NSString stringWithFormat:@"void(*%@)()", currentName]; + break; + + case T_BLOCK_TYPE: + if (currentName == nil) + result = @"void(^)()"; + else + result = [NSString stringWithFormat:@"void(^%@)()", currentName]; + break; + case 'j': case 'r': case 'n': @@ -521,11 +578,11 @@ - (NSString *)_typeStringWithVariableNamesToLevel:(NSUInteger)level showObjectTy break; case 'b': - result = [NSString stringWithFormat:@"b%@", bitfieldSize]; + result = [NSString stringWithFormat:@"b%d", bitfieldSize]; break; case '[': - result = [NSString stringWithFormat:@"[%@%@]", arraySize, [subtype _typeStringWithVariableNamesToLevel:level showObjectTypes:shouldShowObjectTypes]]; + result = [NSString stringWithFormat:@"[%d%@]", arraySize, [subtype _typeStringWithVariableNamesToLevel:level showObjectTypes:shouldShowObjectTypes]]; break; case '(': @@ -563,6 +620,14 @@ - (NSString *)_typeStringWithVariableNamesToLevel:(NSUInteger)level showObjectTy result = [NSString stringWithFormat:@"%c%@", type, [subtype _typeStringWithVariableNamesToLevel:level showObjectTypes:shouldShowObjectTypes]]; break; + case T_FUNCTION_POINTER_TYPE: + result = @"^?"; + break; + + case T_BLOCK_TYPE: + result = @"@?"; + break; + default: result = [NSString stringWithFormat:@"%c", type]; break; diff --git a/Source/CDTypeLexer.h b/Source/CDTypeLexer.h index 8dcd76ac..1cffe865 100644 --- a/Source/CDTypeLexer.h +++ b/Source/CDTypeLexer.h @@ -11,6 +11,8 @@ #define T_NAMED_OBJECT 259 #define TK_QUOTED_STRING 260 #define TK_TEMPLATE_TYPE TK_IDENTIFIER +#define T_FUNCTION_POINTER_TYPE 1001 +#define T_BLOCK_TYPE 1002 enum { CDTypeLexerState_Normal = 0, diff --git a/Source/CDTypeName.m b/Source/CDTypeName.m index a17ff66f..66c14a01 100644 --- a/Source/CDTypeName.m +++ b/Source/CDTypeName.m @@ -27,12 +27,12 @@ - (id)init; - (id)copyWithZone:(NSZone *)zone; { - CDTypeName *copy = [[CDTypeName alloc] init]; + CDTypeName *copy = [[CDTypeName allocWithZone:zone] init]; copy.name = self.name; copy.suffix = self.suffix; for (CDTypeName *subtype in self.templateTypes) { - CDTypeName *subcopy = [subtype copy]; + CDTypeName *subcopy = [subtype copyWithZone:zone]; [copy.templateTypes addObject:subcopy]; } diff --git a/Source/CDTypeParser.m b/Source/CDTypeParser.m index 4907f461..72dbc060 100644 --- a/Source/CDTypeParser.m +++ b/Source/CDTypeParser.m @@ -247,14 +247,17 @@ - (CDType *)_parseTypeInStruct:(BOOL)isInStruct; type = [[CDType alloc] initSimpleType:'v']; // Safari on 10.5 has: "m_function"{?="__pfn"^"__delta"i} result = [[CDType alloc] initPointerType:type]; + } else if (lookahead == '?') { + [self match:'?']; + result = [[CDType alloc] initFunctionPointerType]; } else { type = [self _parseTypeInStruct:isInStruct]; result = [[CDType alloc] initPointerType:type]; } } else if (lookahead == 'b') { // bitfield [self match:'b']; - NSString *number = [self parseNumber]; - result = [[CDType alloc] initBitfieldType:number]; + int width = [[self parseNumber] intValue]; + result = [[CDType alloc] initBitfieldType:width]; } else if (lookahead == '@') { // id [self match:'@']; #if 0 @@ -277,6 +280,9 @@ - (CDType *)_parseTypeInStruct:(BOOL)isInStruct; } [self match:TK_QUOTED_STRING]; + } else if (lookahead == '?') { + [self match:'?']; + result = [[CDType alloc] initBlockType]; } else { result = [[CDType alloc] initIDType:nil]; } @@ -305,11 +311,11 @@ - (CDType *)_parseTypeInStruct:(BOOL)isInStruct; } } else if (lookahead == '[') { // array [self match:'[']; - NSString *number = [self parseNumber]; + int elements = [[self parseNumber] intValue]; CDType *type = [self _parseType]; [self match:']']; - result = [[CDType alloc] initArrayType:type count:number]; + result = [[CDType alloc] initArrayType:type count:elements]; } else if ([self isTokenInSimpleTypeSet:lookahead]) { // simple type int simpleType = lookahead; [self match:simpleType]; diff --git a/class-dump.m b/class-dump.m index 174fcf65..b4ded1e2 100644 --- a/class-dump.m +++ b/class-dump.m @@ -22,6 +22,8 @@ #import "CDFatArch.h" #import "CDSearchPathState.h" +extern BOOL global_shouldMangleTemplateTypes; + void print_usage(void) { fprintf(stderr, @@ -45,6 +47,7 @@ void print_usage(void) " --sdk-ios specify iOS SDK version (will look in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk\n" " --sdk-mac specify Mac OS X version (will look in /Developer/SDKs/MacOSX.sdk\n" " --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)\n" + " --mangle-template-types mangle non-alnum characters in type names\n" , CLASS_DUMP_VERSION ); @@ -56,6 +59,7 @@ void print_usage(void) #define CD_OPT_SDK_IOS 4 #define CD_OPT_SDK_MAC 5 #define CD_OPT_SDK_ROOT 6 +#define CD_OPT_MANGLE_TEMPLATE_TYPES 7 int main(int argc, char *argv[]) { @@ -89,6 +93,7 @@ int main(int argc, char *argv[]) { "sdk-ios", required_argument, NULL, CD_OPT_SDK_IOS }, { "sdk-mac", required_argument, NULL, CD_OPT_SDK_MAC }, { "sdk-root", required_argument, NULL, CD_OPT_SDK_ROOT }, + { "mangle-template-types", no_argument, NULL, CD_OPT_MANGLE_TEMPLATE_TYPES }, { NULL, 0, NULL, 0 }, }; @@ -146,6 +151,11 @@ int main(int argc, char *argv[]) break; } + + case CD_OPT_MANGLE_TEMPLATE_TYPES: { + global_shouldMangleTemplateTypes = YES; + break; + } case 'a': classDump.shouldShowIvarOffsets = YES;