Index: class-dump/src/CDTypeController.m |
=================================================================== |
--- class-dump/src/CDTypeController.m (revision 0) |
+++ class-dump/src/CDTypeController.m (revision 0) |
@@ -0,0 +1,379 @@ |
+// -*- mode: ObjC -*- |
+ |
+// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. |
+// Copyright (C) 1997-1998, 2000-2001, 2004-2010 Steve Nygard. |
+ |
+#import "CDTypeController.h" |
+ |
+#import "CDStructureTable.h" |
+#import "CDClassDump.h" |
+#import "CDTypeFormatter.h" |
+#import "CDType.h" |
+ |
+static BOOL debug = NO; |
+ |
+@implementation CDTypeController |
+ |
+- (id)initWithClassDump:(CDClassDump *)aClassDump; |
+{ |
+ if ([super init] == nil) |
+ return nil; |
+ |
+ ivarTypeFormatter = [[CDTypeFormatter alloc] init]; |
+ [ivarTypeFormatter setShouldExpand:NO]; |
+ [ivarTypeFormatter setShouldAutoExpand:YES]; |
+ [ivarTypeFormatter setBaseLevel:1]; |
+ [ivarTypeFormatter setTypeController:self]; |
+ |
+ methodTypeFormatter = [[CDTypeFormatter alloc] init]; |
+ [methodTypeFormatter setShouldExpand:NO]; |
+ [methodTypeFormatter setShouldAutoExpand:NO]; |
+ [methodTypeFormatter setBaseLevel:0]; |
+ [methodTypeFormatter setTypeController:self]; |
+ |
+ propertyTypeFormatter = [[CDTypeFormatter alloc] init]; |
+ [propertyTypeFormatter setShouldExpand:NO]; |
+ [propertyTypeFormatter setShouldAutoExpand:NO]; |
+ [propertyTypeFormatter setBaseLevel:0]; |
+ [propertyTypeFormatter setTypeController:self]; |
+ |
+ structDeclarationTypeFormatter = [[CDTypeFormatter alloc] init]; |
+ [structDeclarationTypeFormatter setShouldExpand:YES]; // But don't expand named struct members... |
+ [structDeclarationTypeFormatter setShouldAutoExpand:YES]; |
+ [structDeclarationTypeFormatter setBaseLevel:0]; |
+ [structDeclarationTypeFormatter setTypeController:self]; // But need to ignore some things? |
+ |
+ structureTable = [[CDStructureTable alloc] init]; |
+ [structureTable setAnonymousBaseName:@"CDStruct_"]; |
+ [structureTable setIdentifier:@"Structs"]; |
+ |
+ unionTable = [[CDStructureTable alloc] init]; |
+ [unionTable setAnonymousBaseName:@"CDUnion_"]; |
+ [unionTable setIdentifier:@"Unions"]; |
+ |
+ nonretained_classDump = aClassDump; |
+ |
+ //[structureTable debugName:@"_xmlSAXHandler"]; |
+ //[structureTable debugName:@"UCKeyboardTypeHeader"]; |
+ //[structureTable debugName:@"UCKeyboardLayout"]; |
+ //[structureTable debugName:@"ppd_group_s"]; |
+ //[structureTable debugName:@"stat"]; |
+ //[structureTable debugName:@"timespec"]; |
+ //[structureTable debugName:@"AudioUnitEvent"]; |
+ //[structureTable debugAnon:@"{?=II}"]; |
+ //[structureTable debugName:@"_CommandStackEntry"]; |
+ //[structureTable debugName:@"_flags"]; |
+ |
+ return self; |
+} |
+ |
+- (void)dealloc; |
+{ |
+ [ivarTypeFormatter release]; |
+ [methodTypeFormatter release]; |
+ [propertyTypeFormatter release]; |
+ [structDeclarationTypeFormatter release]; |
+ |
+ [structureTable release]; |
+ [unionTable release]; |
+ |
+ [super dealloc]; |
+} |
+ |
+- (CDTypeFormatter *)ivarTypeFormatter; |
+{ |
+ return ivarTypeFormatter; |
+} |
+ |
+- (CDTypeFormatter *)methodTypeFormatter; |
+{ |
+ return methodTypeFormatter; |
+} |
+ |
+- (CDTypeFormatter *)propertyTypeFormatter; |
+{ |
+ return propertyTypeFormatter; |
+} |
+ |
+- (CDTypeFormatter *)structDeclarationTypeFormatter; |
+{ |
+ return structDeclarationTypeFormatter; |
+} |
+ |
+- (CDType *)typeFormatter:(CDTypeFormatter *)aFormatter replacementForType:(CDType *)aType; |
+{ |
+#if 0 |
+ if ([aType type] == '{') |
+ return [structureTable replacementForType:aType]; |
+ |
+ if ([aType type] == '(') |
+ return [unionTable replacementForType:aType]; |
+#endif |
+ return nil; |
+} |
+ |
+- (NSString *)typeFormatter:(CDTypeFormatter *)aFormatter typedefNameForStruct:(CDType *)structType level:(NSUInteger)level; |
+{ |
+ //CDType *searchType; |
+ //CDStructureTable *targetTable; |
+ |
+ if (level == 0 && aFormatter == structDeclarationTypeFormatter) |
+ return nil; |
+ |
+ if ([self shouldExpandType:structType] == NO) |
+ return [self typedefNameForType:structType]; |
+ |
+ return nil; |
+} |
+ |
+- (void)appendStructuresToString:(NSMutableString *)resultString symbolReferences:(CDSymbolReferences *)symbolReferences; |
+{ |
+ [structureTable appendNamedStructuresToString:resultString formatter:structDeclarationTypeFormatter symbolReferences:symbolReferences |
+ markName:@"Named Structures"]; |
+ [structureTable appendTypedefsToString:resultString formatter:structDeclarationTypeFormatter symbolReferences:symbolReferences |
+ markName:@"Typedef'd Structures"]; |
+ |
+ [unionTable appendNamedStructuresToString:resultString formatter:structDeclarationTypeFormatter symbolReferences:symbolReferences |
+ markName:@"Named Unions"]; |
+ [unionTable appendTypedefsToString:resultString formatter:structDeclarationTypeFormatter symbolReferences:symbolReferences |
+ markName:@"Typedef'd Unions"]; |
+} |
+ |
+// Call this before calling generateMemberNames. |
+- (void)generateTypedefNames; |
+{ |
+ [structureTable generateTypedefNames]; |
+ [unionTable generateTypedefNames]; |
+} |
+ |
+- (void)generateMemberNames; |
+{ |
+ [structureTable generateMemberNames]; |
+ [unionTable generateMemberNames]; |
+} |
+ |
+// |
+// Run phase 1+ |
+// |
+ |
+- (void)workSomeMagic; |
+{ |
+ [self startPhase1]; |
+ [self startPhase2]; |
+ [self startPhase3]; |
+ |
+ [self generateTypedefNames]; |
+ [self generateMemberNames]; |
+ |
+ if (debug) { |
+ NSMutableString *str; |
+ |
+ str = [NSMutableString string]; |
+ [structureTable appendNamedStructuresToString:str formatter:structDeclarationTypeFormatter symbolReferences:nil |
+ markName:@"Named Structures"]; |
+ [unionTable appendNamedStructuresToString:str formatter:structDeclarationTypeFormatter symbolReferences:nil |
+ markName:@"Named Unions"]; |
+ [str writeToFile:@"/tmp/out.struct" atomically:NO encoding:NSUTF8StringEncoding error:NULL]; |
+ |
+ str = [NSMutableString string]; |
+ [structureTable appendTypedefsToString:str formatter:structDeclarationTypeFormatter symbolReferences:nil |
+ markName:@"Typedef'd Structures"]; |
+ [unionTable appendTypedefsToString:str formatter:structDeclarationTypeFormatter symbolReferences:nil |
+ markName:@"Typedef'd Unions"]; |
+ [str writeToFile:@"/tmp/out.typedef" atomically:NO encoding:NSUTF8StringEncoding error:NULL]; |
+ //NSLog(@"str =\n%@", str); |
+ } |
+} |
+ |
+// |
+// Phase 0 |
+// |
+ |
+- (void)phase0RegisterStructure:(CDType *)aStructure usedInMethod:(BOOL)isUsedInMethod; |
+{ |
+ if ([aStructure type] == '{') { |
+ [structureTable phase0RegisterStructure:aStructure usedInMethod:isUsedInMethod]; |
+ } else if ([aStructure type] == '(') { |
+ [unionTable phase0RegisterStructure:aStructure usedInMethod:isUsedInMethod]; |
+ } else { |
+ NSLog(@"%s, unknown structure type: %d", _cmd, [aStructure type]); |
+ } |
+} |
+ |
+- (void)endPhase:(NSUInteger)phase; |
+{ |
+ if (phase == 0) { |
+ [structureTable finishPhase0]; |
+ [unionTable finishPhase0]; |
+ } |
+} |
+ |
+// |
+// Phase 1 |
+// |
+ |
+// Phase one builds a list of all of the named and unnamed structures. |
+// It does this by going through all the top level structures we found in phase 0. |
+- (void)startPhase1; |
+{ |
+ //NSLog(@" > %s", _cmd); |
+ // Structures and unions can be nested, so do phase 1 on each table before finishing the phase. |
+ [structureTable phase1WithTypeController:self]; |
+ [unionTable phase1WithTypeController:self]; |
+ |
+ [structureTable finishPhase1]; |
+ [unionTable finishPhase1]; |
+ //NSLog(@"< %s", _cmd); |
+} |
+ |
+- (void)phase1RegisterStructure:(CDType *)aStructure; |
+{ |
+ if ([aStructure type] == '{') { |
+ [structureTable phase1RegisterStructure:aStructure]; |
+ } else if ([aStructure type] == '(') { |
+ [unionTable phase1RegisterStructure:aStructure]; |
+ } else { |
+ NSLog(@"%s, unknown structure type: %d", _cmd, [aStructure type]); |
+ } |
+} |
+ |
+// |
+// Phase 2 |
+// |
+ |
+- (void)startPhase2; |
+{ |
+ NSUInteger maxDepth, depth; |
+ |
+ //NSLog(@" > %s", _cmd); |
+ |
+ maxDepth = [structureTable phase1_maxDepth]; |
+ if (maxDepth < [unionTable phase1_maxDepth]) |
+ maxDepth = [unionTable phase1_maxDepth]; |
+ |
+ if (debug) NSLog(@"max structure/union depth is: %u", maxDepth); |
+ |
+ for (depth = 1; depth <= maxDepth; depth++) { |
+ [structureTable phase2AtDepth:depth typeController:self]; |
+ [unionTable phase2AtDepth:depth typeController:self]; |
+ } |
+ |
+ //[structureTable logPhase2Info]; |
+ [structureTable finishPhase2]; |
+ [unionTable finishPhase2]; |
+} |
+ |
+- (void)startPhase3; |
+{ |
+ // do phase2 merge on all the types from phase 0 |
+ [structureTable phase2ReplacementOnPhase0WithTypeController:self]; |
+ [unionTable phase2ReplacementOnPhase0WithTypeController:self]; |
+ |
+ // Any info referenced by a method, or with >1 reference, gets typedef'd. |
+ // - Generate name hash based on full type string at this point |
+ // - Then fill in unnamed fields |
+ |
+ // Print method/>1 ref names and typedefs |
+ // Go through all updated phase0_structureInfo types |
+ // - start merging these into a new table |
+ // - If this is the first time a structure has been added: |
+ // - add one reference for each subtype |
+ // - otherwise just merge them. |
+ // - end result should be CDStructureInfos with counts and method reference flags |
+ [structureTable buildPhase3Exceptions]; |
+ [unionTable buildPhase3Exceptions]; |
+ |
+ [structureTable phase3WithTypeController:self]; |
+ [unionTable phase3WithTypeController:self]; |
+ |
+ [structureTable finishPhase3]; |
+ [unionTable finishPhase3]; |
+ //[structureTable logPhase3Info]; |
+ |
+ // - All named structures (minus exceptions like struct _flags) get declared at the top level |
+ // - All anonymous structures (minus exceptions) referenced by a method |
+ // OR references >1 time gets typedef'd at the top and referenced by typedef subsequently |
+ // Celebrate! |
+ |
+ // Then... what do we do when printing ivars/method types? |
+ // CDTypeController - (BOOL)shouldExpandType:(CDType *)type; |
+ // CDTypeController - (NSString *)typedefNameForType:(CDType *)type; |
+ |
+ //NSLog(@"< %s", _cmd); |
+} |
+ |
+- (BOOL)shouldShowName:(NSString *)name; |
+{ |
+ return ([nonretained_classDump shouldMatchRegex] == NO) || [nonretained_classDump regexMatchesString:name]; |
+} |
+ |
+- (BOOL)shouldShowIvarOffsets; |
+{ |
+ return nonretained_classDump.shouldShowIvarOffsets; |
+} |
+ |
+- (BOOL)shouldShowMethodAddresses; |
+{ |
+ return nonretained_classDump.shouldShowMethodAddresses; |
+} |
+ |
+- (BOOL)targetArchUses64BitABI; |
+{ |
+ return CDArchUses64BitABI(nonretained_classDump.targetArch); |
+} |
+ |
+- (CDType *)phase2ReplacementForType:(CDType *)type; |
+{ |
+ if ([type type] == '{') |
+ return [structureTable phase2ReplacementForType:type]; |
+ |
+ if ([type type] == '(') |
+ return [unionTable phase2ReplacementForType:type]; |
+ |
+ return nil; |
+} |
+ |
+- (void)phase3RegisterStructure:(CDType *)aStructure; |
+{ |
+ //NSLog(@"%s, type= %@", _cmd, [aStructure typeString]); |
+ if ([aStructure type] == '{') |
+ [structureTable phase3RegisterStructure:aStructure count:1 usedInMethod:NO typeController:self]; |
+ |
+ if ([aStructure type] == '(') |
+ [unionTable phase3RegisterStructure:aStructure count:1 usedInMethod:NO typeController:self]; |
+} |
+ |
+- (CDType *)phase3ReplacementForType:(CDType *)type; |
+{ |
+ if ([type type] == '{') |
+ return [structureTable phase3ReplacementForType:type]; |
+ |
+ if ([type type] == '(') |
+ return [unionTable phase3ReplacementForType:type]; |
+ |
+ return nil; |
+} |
+ |
+- (BOOL)shouldExpandType:(CDType *)type; |
+{ |
+ if ([type type] == '{') |
+ return [structureTable shouldExpandType:type]; |
+ |
+ if ([type type] == '(') |
+ return [unionTable shouldExpandType:type]; |
+ |
+ return NO; |
+} |
+ |
+- (NSString *)typedefNameForType:(CDType *)type; |
+{ |
+ if ([type type] == '{') |
+ return [structureTable typedefNameForType:type]; |
+ |
+ if ([type type] == '(') |
+ return [unionTable typedefNameForType:type]; |
+ |
+ return nil; |
+} |
+ |
+@end |
Property changes on: class-dump/src/CDTypeController.m |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |