| Index: class-dump/src/CDStructureTable.m
|
| ===================================================================
|
| --- class-dump/src/CDStructureTable.m (revision 0)
|
| +++ class-dump/src/CDStructureTable.m (revision 0)
|
| @@ -0,0 +1,1096 @@
|
| +// -*- 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 "CDStructureTable.h"
|
| +
|
| +#import "NSArray-Extensions.h"
|
| +#import "NSError-CDExtensions.h"
|
| +#import "NSString-Extensions.h"
|
| +#import "CDClassDump.h"
|
| +#import "CDSymbolReferences.h"
|
| +#import "CDType.h"
|
| +#import "CDTypeController.h"
|
| +#import "CDTypeFormatter.h"
|
| +#import "CDTypeName.h"
|
| +#import "CDStructureInfo.h"
|
| +
|
| +// Phase 0 - This is driven by CDClassDump, registering types from all of the classes, categories, and protocols.
|
| +// - This collects all the top level types (or struct/unions?), keeps a reference count, and flags any that were used in a method.
|
| +// - If a top level struct was used in a method, then the type MUST be declared at the top.
|
| +// - At the end of phase 0, these types are recursively visited, renaming structs whose name starts with $ (like $_12345) to ?, so
|
| +// that we'll treat them as anonymous structures.
|
| +// - Those names must be generated by the compiler. It can end up with different numbers for the same type.
|
| +
|
| +// Phase 1 - This goes through all the types collected in phase 0, and recursively registers each structure and union with the type controller.
|
| +// - We are not concerned about reference counts or the isUsedInMethod flags.
|
| +// - Since structures and unions can be nested in each other, we need to process each table before doing the end-of-phase work.
|
| +// - We record the maximum structure depth.
|
| +// - Since the deepest union may be buriend in a structure instead of referenced at the top level, we can't calculate the max depth from phase 0.
|
| +// - On the other hand, since we're only interested in the max combined depth of structures and unions, the end result would be the same.
|
| +// - The result of phase 1 is phase1_groupedByDepth: a dictionary keyed by the structure depth, containing arrays of CDStructureInfo.
|
| +
|
| +// Phase 2 - This is driven by CDTypeController.
|
| +// - The goal of phase 2 is to gather member names and types (@"NSObject" vs just @).
|
| +// - It goes through all of the phase1 groups, shallowest to deepest.
|
| +// - For each level group:
|
| +// - First it merges the results of all previous groups with the types at this depth.
|
| +// - Then we group the CDStructureInfos, named structures by name, anon structures by reallyBareTypeString
|
| +// - If they could be combined, the combined CDStructureInfo is to phase2_namedStructureInfo or phase2_anonStructureInfo.
|
| +// - If they couldn't be combined, the uncombined CDStructureInfos are added to phase2_nameExceptions or phase2_anonExceptions.
|
| +
|
| +// Phase 3 - Using all of the information available from the merged types from phase 2, we merge these types with the types from phase 0
|
| +// to fill in missing member names, and the occasional object type.
|
| +
|
| +// After all the phases are done, typedef names are generated for all anonymous structures, and then field names are added for missing fields.
|
| +// - bitfields don't need to have a name, so they can be blank.
|
| +// - the typedef name is calculated from a hash of the typeString.
|
| +// - Doing it before adding missing fields means we could change the field names without changing the typedef name.
|
| +// - Makes the name independant of the order they were encountered (like the previous indexes were). You can get meaningful diffs between
|
| +// framework changes now.
|
| +
|
| +static BOOL debug = NO;
|
| +static BOOL debugNamedStructures = NO;
|
| +static BOOL debugAnonStructures = NO;
|
| +
|
| +@implementation CDStructureTable
|
| +
|
| +- (id)init;
|
| +{
|
| + if ([super init] == nil)
|
| + return nil;
|
| +
|
| + identifier = nil;
|
| + anonymousBaseName = nil;
|
| +
|
| + phase0_structureInfo = [[NSMutableDictionary alloc] init];
|
| +
|
| + phase1_structureInfo = [[NSMutableDictionary alloc] init];
|
| + phase1_maxDepth = 0;
|
| + phase1_groupedByDepth = [[NSMutableDictionary alloc] init];
|
| +
|
| + phase2_namedStructureInfo = [[NSMutableDictionary alloc] init];
|
| + phase2_anonStructureInfo = [[NSMutableDictionary alloc] init];
|
| + phase2_nameExceptions = [[NSMutableArray alloc] init];
|
| + phase2_anonExceptions = [[NSMutableArray alloc] init];
|
| +
|
| + phase3_namedStructureInfo = [[NSMutableDictionary alloc] init];
|
| + phase3_anonStructureInfo = [[NSMutableDictionary alloc] init];
|
| + phase3_nameExceptions = [[NSMutableDictionary alloc] init];
|
| + phase3_anonExceptions = [[NSMutableDictionary alloc] init];
|
| +
|
| + phase3_exceptionalNames = [[NSMutableSet alloc] init];
|
| + phase3_inMethodNameExceptions = [[NSMutableSet alloc] init];
|
| +
|
| + flags.shouldDebug = NO;
|
| +
|
| + debugNames = [[NSMutableSet alloc] init];
|
| + debugAnon = [[NSMutableSet alloc] init];
|
| +
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc;
|
| +{
|
| + [identifier release];
|
| + [anonymousBaseName release];
|
| +
|
| + [phase0_structureInfo release];
|
| +
|
| + [phase1_structureInfo release];
|
| + [phase1_groupedByDepth release];
|
| +
|
| + [phase2_namedStructureInfo release];
|
| + [phase2_anonStructureInfo release];
|
| + [phase2_nameExceptions release];
|
| + [phase2_anonExceptions release];
|
| +
|
| + [phase3_namedStructureInfo release];
|
| + [phase3_anonStructureInfo release];
|
| + [phase3_nameExceptions release];
|
| + [phase3_anonExceptions release];
|
| +
|
| + [phase3_exceptionalNames release];
|
| + [phase3_inMethodNameExceptions release];
|
| +
|
| + [debugNames release];
|
| + [debugAnon release];
|
| +
|
| + [super dealloc];
|
| +}
|
| +
|
| +- (NSString *)identifier;
|
| +{
|
| + return identifier;
|
| +}
|
| +
|
| +- (void)setIdentifier:(NSString *)newIdentifier;
|
| +{
|
| + if (newIdentifier == identifier)
|
| + return;
|
| +
|
| + [identifier release];
|
| + identifier = [newIdentifier retain];
|
| +}
|
| +
|
| +- (NSString *)anonymousBaseName;
|
| +{
|
| + return anonymousBaseName;
|
| +}
|
| +
|
| +- (void)setAnonymousBaseName:(NSString *)newName;
|
| +{
|
| + if (newName == anonymousBaseName)
|
| + return;
|
| +
|
| + [anonymousBaseName release];
|
| + anonymousBaseName = [newName retain];
|
| +}
|
| +
|
| +- (BOOL)shouldDebug;
|
| +{
|
| + return flags.shouldDebug;
|
| +}
|
| +
|
| +- (void)setShouldDebug:(BOOL)newFlag;
|
| +{
|
| + flags.shouldDebug = newFlag;
|
| +}
|
| +
|
| +//
|
| +// Phase 0
|
| +//
|
| +
|
| +- (void)phase0RegisterStructure:(CDType *)aStructure usedInMethod:(BOOL)isUsedInMethod;
|
| +{
|
| + NSString *key;
|
| + CDStructureInfo *info;
|
| +
|
| + key = [aStructure typeString];
|
| + info = [phase0_structureInfo objectForKey:key];
|
| + if (info == nil) {
|
| + info = [[CDStructureInfo alloc] initWithType:aStructure];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:YES];
|
| + [phase0_structureInfo setObject:info forKey:key];
|
| + [info release];
|
| + } else {
|
| + [info addReferenceCount:1];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:YES];
|
| + }
|
| +}
|
| +
|
| +- (void)finishPhase0;
|
| +{
|
| + if (debug) NSLog(@"[%@] %s, changing struct names that start with $", identifier, _cmd);
|
| + for (CDStructureInfo *info in [phase0_structureInfo allValues]) {
|
| + [[info type] phase0RecursivelyFixStructureNames:debug];
|
| + }
|
| +
|
| + if ([debugNames count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"debug names: %@", [[debugNames allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase0_structureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugNames containsObject:[[[info type] typeName] description]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| + }
|
| +
|
| + if ([debugAnon count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"debug anon: %@", [[debugAnon allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase0_structureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugAnon containsObject:[[info type] reallyBareTypeString]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| + }
|
| +}
|
| +
|
| +- (void)logPhase0Info;
|
| +{
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + for (CDStructureInfo *info in [[phase0_structureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| +}
|
| +
|
| +//
|
| +// Phase 1
|
| +//
|
| +
|
| +- (void)phase1WithTypeController:(CDTypeController *)typeController;
|
| +{
|
| + for (CDStructureInfo *info in [phase0_structureInfo allValues]) {
|
| + [[info type] phase1RegisterStructuresWithObject:typeController];
|
| + }
|
| +}
|
| +
|
| +// Need to gather all of the structures, since some substructures may have member names we'd otherwise miss.
|
| +- (void)phase1RegisterStructure:(CDType *)aStructure;
|
| +{
|
| + NSString *key;
|
| + CDStructureInfo *info;
|
| +
|
| + key = [aStructure typeString];
|
| + info = [phase1_structureInfo objectForKey:key];
|
| + if (info == nil) {
|
| + info = [[CDStructureInfo alloc] initWithType:aStructure];
|
| + [phase1_structureInfo setObject:info forKey:key];
|
| + [info release];
|
| + }
|
| +}
|
| +
|
| +// Need to merge names bottom-up to catch cases like: {?=@@iiffff{_NSRect={_NSPoint=ff}{_NSSize=ff}}{?=b1b1b1b1b1b27}}
|
| +
|
| +- (void)finishPhase1;
|
| +{
|
| + if (debug) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + }
|
| +
|
| + // The deepest union may not be at the top level (buried in a structure instead), so need to get the depth here.
|
| + // But we'll take the max of structure and union depths in the CDTypeController anyway.
|
| +
|
| + for (CDStructureInfo *info in [phase1_structureInfo allValues]) {
|
| + NSUInteger depth;
|
| +
|
| + depth = [[info type] structureDepth];
|
| + if (phase1_maxDepth < depth)
|
| + phase1_maxDepth = depth;
|
| + }
|
| + if (debug) NSLog(@"[%@] Maximum structure depth is: %u", identifier, phase1_maxDepth);
|
| +
|
| + for (CDStructureInfo *info in [phase1_structureInfo allValues]) {
|
| + NSNumber *key;
|
| + NSMutableArray *group;
|
| +
|
| + key = [NSNumber numberWithUnsignedInteger:[[info type] structureDepth]];
|
| + group = [phase1_groupedByDepth objectForKey:key];
|
| + if (group == nil) {
|
| + group = [[NSMutableArray alloc] init];
|
| + [group addObject:info];
|
| + [phase1_groupedByDepth setObject:group forKey:key];
|
| + [group release];
|
| + } else {
|
| + [group addObject:info];
|
| + }
|
| + }
|
| +
|
| + if (debug) NSLog(@"depth groups: %@", [[phase1_groupedByDepth allKeys] sortedArrayUsingSelector:@selector(compare:)]);
|
| +}
|
| +
|
| +- (NSUInteger)phase1_maxDepth;
|
| +{
|
| + return phase1_maxDepth;
|
| +}
|
| +
|
| +//
|
| +// Phase 2
|
| +//
|
| +
|
| +// From lowest to highest depths:
|
| +// - Go through all infos at that level
|
| +// - recursively (bottom up) try to merge substructures into that type, to get names/full types
|
| +// - merge all mergeable infos at that level
|
| +
|
| +- (void)phase2AtDepth:(NSUInteger)depth typeController:(CDTypeController *)typeController;
|
| +{
|
| + NSNumber *depthKey;
|
| + NSArray *infos;
|
| + NSMutableDictionary *nameDict, *anonDict;
|
| +
|
| + //NSLog(@"[%@] %s, depth: %u", identifier, _cmd, depth);
|
| + depthKey = [NSNumber numberWithUnsignedInt:depth];
|
| + infos = [phase1_groupedByDepth objectForKey:depthKey];
|
| +
|
| + for (CDStructureInfo *info in infos) {
|
| + // recursively (bottom up) try to merge substructures into that type, to get names/full types
|
| + //NSLog(@"----------------------------------------");
|
| + //NSLog(@"Trying phase2Merge with on %@", [[info type] typeString]);
|
| + [[info type] phase2MergeWithTypeController:typeController debug:debug];
|
| + }
|
| +
|
| + // merge all mergeable infos at that level
|
| + nameDict = [NSMutableDictionary dictionary];
|
| + anonDict = [NSMutableDictionary dictionary];
|
| +
|
| + // Group named structures by name.
|
| + // Group anon structures by reallyBareTypeString.
|
| + for (CDStructureInfo *info in infos) {
|
| + NSString *name;
|
| + NSMutableArray *group;
|
| +
|
| + name = [[[info type] typeName] description];
|
| +
|
| + if ([@"?" isEqualToString:name]) {
|
| + NSString *key;
|
| +
|
| + key = [[info type] reallyBareTypeString];
|
| + group = [anonDict objectForKey:key];
|
| + if (group == nil) {
|
| + group = [[NSMutableArray alloc] init];
|
| + [group addObject:info];
|
| + [anonDict setObject:group forKey:key];
|
| + [group release];
|
| + } else {
|
| + [group addObject:info];
|
| + }
|
| + } else {
|
| + group = [nameDict objectForKey:name];
|
| + if (group == nil) {
|
| + group = [[NSMutableArray alloc] init];
|
| + [group addObject:info];
|
| + [nameDict setObject:group forKey:name];
|
| + [group release];
|
| + } else {
|
| + [group addObject:info];
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Now... for each group, make sure we can combine them all together.
|
| + // If not, this means that either the types or the member names conflicted, and we save the entire group as an exception.
|
| + for (NSString *key in [nameDict allKeys]) {
|
| + NSMutableArray *group;
|
| + CDStructureInfo *combined = nil;
|
| + BOOL canBeCombined = YES;
|
| +
|
| + //NSLog(@"key... %@", key);
|
| + group = [nameDict objectForKey:key];
|
| + for (CDStructureInfo *info in group) {
|
| + if (combined == nil) {
|
| + combined = [info copy];
|
| + } else {
|
| + //NSLog(@"old: %@", [[combined type] typeString]);
|
| + //NSLog(@"new: %@", [[info type] typeString]);
|
| + if ([[combined type] canMergeWithType:[info type]]) {
|
| + [[combined type] mergeWithType:[info type]];
|
| + [combined addReferenceCount:[info referenceCount]];
|
| +#if 0
|
| + if ([info isUsedInMethod])
|
| + [combined setIsUsedInMethod:YES];
|
| +#endif
|
| + } else {
|
| + canBeCombined = NO;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (canBeCombined) {
|
| + CDStructureInfo *previousInfo;
|
| +
|
| + previousInfo = [phase2_namedStructureInfo objectForKey:key];
|
| + if (previousInfo != nil) {
|
| + // struct _Vector_impl in HALLab.
|
| + [phase2_nameExceptions addObject:previousInfo];
|
| + //[phase2_nameExceptions addObjectsFromArray:group]; // Or just add the combined?
|
| + [phase2_nameExceptions addObject:combined];
|
| + [phase2_namedStructureInfo removeObjectForKey:key];
|
| + if (debugNamedStructures) {
|
| + NSLog(@"[%@] %s, WARNING: depth %u name %@ has conflict(?) at lower level", identifier, _cmd, depth, key);
|
| + NSLog(@"previous: %@", [[phase2_namedStructureInfo objectForKey:key] shortDescription]);
|
| + NSLog(@" current: %@", [combined shortDescription]);
|
| + }
|
| + } else {
|
| + [phase2_namedStructureInfo setObject:combined forKey:key];
|
| + }
|
| + } else {
|
| + if (debugNamedStructures) {
|
| + NSLog(@"----------------------------------------");
|
| + NSLog(@"Can't be combined: %@", key);
|
| + NSLog(@"group: %@", group);
|
| + }
|
| + [phase2_nameExceptions addObjectsFromArray:group];
|
| + }
|
| +
|
| + [combined release];
|
| + }
|
| +
|
| + //NSLog(@"======================================================================");
|
| + for (NSString *key in [anonDict allKeys]) {
|
| + NSMutableArray *group;
|
| + CDStructureInfo *combined = nil;
|
| + BOOL canBeCombined = YES;
|
| +
|
| + //NSLog(@"key... %@", key);
|
| + group = [anonDict objectForKey:key];
|
| + for (CDStructureInfo *info in group) {
|
| + if (combined == nil) {
|
| + combined = [info copy];
|
| + //NSLog(@"info: %@", [info shortDescription]);
|
| + //NSLog(@"combined: %@", [combined shortDescription]);
|
| + } else {
|
| + //NSLog(@"old: %@", [combined shortDescription]);
|
| + //NSLog(@"new: %@", [info shortDescription]);
|
| + if ([[combined type] canMergeWithType:[info type]]) {
|
| + [[combined type] mergeWithType:[info type]];
|
| + [combined addReferenceCount:[info referenceCount]];
|
| +#if 0
|
| + if ([info isUsedInMethod])
|
| + [combined setIsUsedInMethod:YES];
|
| +#endif
|
| + } else {
|
| + if (debugAnonStructures) {
|
| + NSLog(@"previous: %@", [[combined type] typeString]);
|
| + NSLog(@" This: %@", [[info type] typeString]);
|
| + }
|
| + canBeCombined = NO;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (canBeCombined) {
|
| + if ([phase2_anonStructureInfo objectForKey:key] != nil) {
|
| + // This shouldn't happen, but the named case might.
|
| + NSLog(@"[%@] %s, WARNING: depth %u type %@ has conflict(?) at lower level", identifier, _cmd, depth, key);
|
| + NSLog(@"previous: %@", [[phase2_anonStructureInfo objectForKey:key] shortDescription]);
|
| + NSLog(@" current: %@", [combined shortDescription]);
|
| + }
|
| + [phase2_anonStructureInfo setObject:combined forKey:key];
|
| + } else {
|
| + if (debugAnonStructures) {
|
| + NSLog(@"----------------------------------------");
|
| + NSLog(@"Can't be combined: %@", key);
|
| + NSLog(@"group: %@", group);
|
| + }
|
| + [phase2_anonExceptions addObjectsFromArray:group];
|
| + }
|
| +
|
| + [combined release];
|
| + }
|
| +}
|
| +
|
| +- (CDType *)phase2ReplacementForType:(CDType *)type;
|
| +{
|
| + NSString *name;
|
| +
|
| + name = [[type typeName] description];
|
| + if ([@"?" isEqualToString:name]) {
|
| + return [(CDStructureInfo *)[phase2_anonStructureInfo objectForKey:[type reallyBareTypeString]] type];
|
| + } else {
|
| + return [(CDStructureInfo *)[phase2_namedStructureInfo objectForKey:name] type];
|
| + }
|
| +
|
| + return nil;
|
| +}
|
| +
|
| +- (void)finishPhase2;
|
| +{
|
| + if ([debugNames count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"debug names: %@", [[debugNames allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase2_namedStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugNames containsObject:[[[info type] typeName] description]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| + }
|
| +
|
| + if ([debugAnon count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"debug anon: %@", [[debugAnon allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase2_anonStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugAnon containsObject:[[info type] reallyBareTypeString]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| + }
|
| +
|
| + //[self logPhase2Info];
|
| +}
|
| +
|
| +- (void)logPhase2Info;
|
| +{
|
| +#if 0
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s, named:", identifier, _cmd);
|
| + for (CDStructureInfo *info in [[phase2_namedStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +#endif
|
| +#if 0
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s, anon:", identifier, _cmd);
|
| + for (CDStructureInfo *info in [[phase2_anonStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +#endif
|
| +#if 1
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s, named exceptions:", identifier, _cmd);
|
| + for (CDStructureInfo *info in [phase2_nameExceptions sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +#endif
|
| +#if 0
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s, anon exceptions:", identifier, _cmd);
|
| + for (CDStructureInfo *info in [phase2_anonExceptions sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +//
|
| +// Phase 3
|
| +//
|
| +
|
| +- (void)phase2ReplacementOnPhase0WithTypeController:(CDTypeController *)typeController;
|
| +{
|
| + if (debug) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] > %s", identifier, _cmd);
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [phase0_structureInfo allValues]) {
|
| + [[info type] phase2MergeWithTypeController:typeController debug:debug];
|
| + }
|
| +
|
| + if (debug) NSLog(@"[%@] < %s", identifier, _cmd);
|
| +}
|
| +
|
| +// 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
|
| +
|
| +- (void)buildPhase3Exceptions;
|
| +{
|
| + for (CDStructureInfo *info in phase2_nameExceptions) {
|
| + CDStructureInfo *newInfo;
|
| +
|
| + newInfo = [info copy];
|
| + [newInfo setReferenceCount:0];
|
| + [newInfo setIsUsedInMethod:NO];
|
| + [phase3_nameExceptions setObject:newInfo forKey:[[newInfo type] typeString]];
|
| + [phase3_exceptionalNames addObject:[newInfo name]];
|
| + [newInfo release];
|
| + }
|
| +
|
| + for (CDStructureInfo *info in phase2_anonExceptions) {
|
| + CDStructureInfo *newInfo;
|
| +
|
| + newInfo = [info copy];
|
| + [newInfo setReferenceCount:0];
|
| + [newInfo setIsUsedInMethod:NO];
|
| + [phase3_anonExceptions setObject:newInfo forKey:[[newInfo type] typeString]];
|
| + [newInfo release];
|
| + }
|
| +
|
| + //NSLog(@"phase3 name exceptions: %@", [[phase3_nameExceptions allKeys] componentsJoinedByString:@", "]);
|
| + //NSLog(@"phase3 anon exceptions: %@", [[phase3_anonExceptions allKeys] componentsJoinedByString:@"\n"]);
|
| + //exit(99);
|
| +}
|
| +
|
| +- (void)phase3WithTypeController:(CDTypeController *)typeController;
|
| +{
|
| + //NSLog(@"[%@] > %s", identifier, _cmd);
|
| +
|
| + for (CDStructureInfo *info in [[phase0_structureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + [self phase3RegisterStructure:[info type] count:[info referenceCount] usedInMethod:[info isUsedInMethod] typeController:typeController];
|
| + }
|
| +
|
| + //NSLog(@"[%@] < %s", identifier, _cmd);
|
| +}
|
| +
|
| +- (void)phase3RegisterStructure:(CDType *)aStructure
|
| + count:(NSUInteger)referenceCount
|
| + usedInMethod:(BOOL)isUsedInMethod
|
| + typeController:(CDTypeController *)typeController;
|
| +{
|
| + NSString *name;
|
| +
|
| + //NSLog(@"[%@] > %s", identifier, _cmd);
|
| +
|
| + name = [[aStructure typeName] description];
|
| + if ([@"?" isEqualToString:name]) {
|
| + NSString *key;
|
| + CDStructureInfo *info;
|
| +
|
| + key = [aStructure reallyBareTypeString];
|
| + //NSLog(@"key: %@, isUsedInMethod: %u", key, isUsedInMethod);
|
| + info = [phase3_anonExceptions objectForKey:[aStructure typeString]];
|
| + if (info != nil) {
|
| + if (debugAnonStructures) NSLog(@"%s, anon key %@ has exception from phase 2", _cmd, [aStructure typeString]);
|
| + [info addReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:isUsedInMethod];
|
| +
|
| + if ([info referenceCount] == referenceCount) { // i.e. the first time we've encounter this struct
|
| + // And then... add 1 reference for each substructure, stopping recursion when we've encountered a previous structure
|
| + [aStructure phase3RegisterMembersWithTypeController:typeController];
|
| + }
|
| + } else {
|
| + info = [phase3_anonStructureInfo objectForKey:key];
|
| + if (info == nil) {
|
| + info = [[CDStructureInfo alloc] initWithType:aStructure];
|
| + [info setReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:isUsedInMethod];
|
| + [phase3_anonStructureInfo setObject:info forKey:key];
|
| + [info release];
|
| +
|
| + // And then... add 1 reference for each substructure, stopping recursion when we've encountered a previous structure
|
| + [aStructure phase3RegisterMembersWithTypeController:typeController];
|
| + } else {
|
| + [info addReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:isUsedInMethod];
|
| + }
|
| + }
|
| + } else {
|
| + CDStructureInfo *info;
|
| +
|
| + if ([debugNames containsObject:name]) NSLog(@"[%@] %s, type= %@", identifier, _cmd, [aStructure typeString]);
|
| + //NSLog(@"[%@] %s, name: %@", identifier, _cmd, name);
|
| + if ([phase3_exceptionalNames containsObject:name]) {
|
| + if (debugNamedStructures) NSLog(@"%s, name %@ has exception from phase 2", _cmd, name);
|
| + info = [phase3_nameExceptions objectForKey:[aStructure typeString]];
|
| + // Info can be nil. For example, from {_CommandStackEntry}
|
| + if (info != nil) {
|
| + [info addReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [phase3_inMethodNameExceptions addObject:name];
|
| +
|
| + if ([info referenceCount] == referenceCount) { // i.e. the first time we've encounter this struct
|
| + // And then... add 1 reference for each substructure, stopping recursion when we've encountered a previous structure
|
| + [aStructure phase3RegisterMembersWithTypeController:typeController];
|
| + }
|
| + }
|
| + } else {
|
| + info = [phase3_namedStructureInfo objectForKey:name];
|
| + if (info == nil) {
|
| + if ([debugNames containsObject:name]) NSLog(@"[%@] %s, info was nil for %@", identifier, _cmd, name);
|
| + info = [[CDStructureInfo alloc] initWithType:aStructure];
|
| + [info setReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:isUsedInMethod];
|
| + [phase3_namedStructureInfo setObject:info forKey:name];
|
| + [info release];
|
| +
|
| + // And then... add 1 reference for each substructure, stopping recursion when we've encountered a previous structure
|
| + [aStructure phase3RegisterMembersWithTypeController:typeController];
|
| + } else {
|
| + if ([debugNames containsObject:name]) NSLog(@"[%@] %s, info before: %@", identifier, _cmd, [info shortDescription]);
|
| + // Handle the case where {foo} occurs before {foo=iii}
|
| + if ([[[info type] members] count] == 0) {
|
| + [[info type] mergeWithType:aStructure];
|
| +
|
| + // And then... add 1 reference for each substructure, stopping recursion when we've encountered a previous structure
|
| + [aStructure phase3RegisterMembersWithTypeController:typeController];
|
| + }
|
| + [info addReferenceCount:referenceCount];
|
| + if (isUsedInMethod)
|
| + [info setIsUsedInMethod:isUsedInMethod];
|
| + if ([debugNames containsObject:name]) {
|
| + NSLog(@"[%@] %s, added ref count: %u, isUsedInMethod: %u", identifier, _cmd, referenceCount, isUsedInMethod);
|
| + NSLog(@"[%@] %s, info after: %@", identifier, _cmd, [info shortDescription]);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + //NSLog(@"[%@] < %s", identifier, _cmd);
|
| +}
|
| +
|
| +- (void)finishPhase3;
|
| +{
|
| + if ([debugNames count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"names: %@", [[debugNames allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase3_namedStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugNames containsObject:[[[info type] typeName] description]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + for (CDStructureInfo *info in [phase3_nameExceptions allValues]) {
|
| + if ([debugNames containsObject:[info name]])
|
| + NSLog(@"%@ is in the name exceptions", [info name]);
|
| + }
|
| + NSLog(@"======================================================================");
|
| + }
|
| +
|
| + if ([debugAnon count] > 0) {
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s", identifier, _cmd);
|
| + NSLog(@"debug anon: %@", [[debugAnon allObjects] componentsJoinedByString:@", "]);
|
| + for (CDStructureInfo *info in [[phase3_anonStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + if ([debugAnon containsObject:[[info type] reallyBareTypeString]])
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| + for (NSString *str in debugAnon)
|
| + if ([phase3_anonExceptions objectForKey:str] != nil)
|
| + NSLog(@"%@ is in the anon exceptions", str);
|
| + NSLog(@"======================================================================");
|
| + }
|
| +
|
| + //[self logPhase3Info];
|
| +}
|
| +
|
| +- (void)logPhase3Info;
|
| +{
|
| + NSLog(@"[%@] > %s", identifier, _cmd);
|
| +#if 0
|
| + NSLog(@"----------------------------------------------------------------------");
|
| + NSLog(@"named:");
|
| + for (NSString *name in [[phase3_namedStructureInfo allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
| + CDStructureInfo *info;
|
| +
|
| + info = [phase3_namedStructureInfo objectForKey:name];
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +
|
| + NSLog(@"----------------------------------------------------------------------");
|
| + NSLog(@"anon:");
|
| + for (CDStructureInfo *info in [[phase3_anonStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +#endif
|
| + NSLog(@"======================================================================");
|
| + NSLog(@"[%@] %s, anon exceptions:", identifier, _cmd);
|
| + for (CDStructureInfo *info in [[phase3_anonExceptions allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + NSLog(@"%@", [info shortDescription]);
|
| + }
|
| +
|
| + NSLog(@"[%@] < %s", identifier, _cmd);
|
| +}
|
| +
|
| +- (CDType *)phase3ReplacementForType:(CDType *)type;
|
| +{
|
| + NSString *name;
|
| +
|
| + name = [[type typeName] description];
|
| + if ([@"?" isEqualToString:name]) {
|
| + return [(CDStructureInfo *)[phase3_anonStructureInfo objectForKey:[type reallyBareTypeString]] type];
|
| + } else {
|
| + return [(CDStructureInfo *)[phase3_namedStructureInfo objectForKey:name] type];
|
| + }
|
| +
|
| + return nil;
|
| +}
|
| +
|
| +//
|
| +// Other
|
| +//
|
| +
|
| +// TODO (2003-12-23): Add option to show/hide this section
|
| +// TODO (2003-12-23): sort by name or by dependency
|
| +// TODO (2003-12-23): declare in modules where they were first used
|
| +
|
| +- (void)appendNamedStructuresToString:(NSMutableString *)resultString
|
| + formatter:(CDTypeFormatter *)aTypeFormatter
|
| + symbolReferences:(CDSymbolReferences *)symbolReferences
|
| + markName:(NSString *)markName;
|
| +{
|
| + BOOL hasAddedMark = NO;
|
| + BOOL hasShownExceptions = NO;
|
| +
|
| + for (NSString *key in [[phase3_namedStructureInfo allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
| + CDStructureInfo *info;
|
| + BOOL shouldShow;
|
| +
|
| + info = [phase3_namedStructureInfo objectForKey:key];
|
| + shouldShow = ![self shouldExpandStructureInfo:info];
|
| + if (shouldShow || debugNamedStructures) {
|
| + CDType *type;
|
| +
|
| + if (hasAddedMark == NO) {
|
| + [resultString appendFormat:@"#pragma mark %@\n\n", markName];
|
| + hasAddedMark = YES;
|
| + }
|
| +
|
| + type = [info type];
|
| + if ([[aTypeFormatter typeController] shouldShowName:[[type typeName] description]]) {
|
| + NSString *formattedString;
|
| +
|
| + if (debugNamedStructures) {
|
| + [resultString appendFormat:@"// would normally show? %u\n", shouldShow];
|
| + [resultString appendFormat:@"// depth: %u, ref count: %u, used in method? %u\n", [[info type] structureDepth], [info referenceCount], [info isUsedInMethod]];
|
| + }
|
| + formattedString = [aTypeFormatter formatVariable:nil parsedType:type symbolReferences:symbolReferences];
|
| + if (formattedString != nil) {
|
| + [resultString appendString:formattedString];
|
| + [resultString appendString:@";\n\n"];
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [[phase3_nameExceptions allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + BOOL shouldShow;
|
| +
|
| + shouldShow = ![self shouldExpandStructureInfo:info];
|
| + if (shouldShow || debugNamedStructures) {
|
| + CDType *type;
|
| +
|
| + if (hasAddedMark == NO) {
|
| + [resultString appendFormat:@"#pragma mark %@\n\n", markName];
|
| + hasAddedMark = YES;
|
| + }
|
| +
|
| + if (hasShownExceptions == NO) {
|
| + [resultString appendString:@"#if 0\n"];
|
| + [resultString appendString:@"// Names with conflicting types:\n"];
|
| + hasShownExceptions = YES;
|
| + }
|
| +
|
| + type = [info type];
|
| + if ([[aTypeFormatter typeController] shouldShowName:[[type typeName] description]]) {
|
| + NSString *formattedString;
|
| +
|
| + if (debugNamedStructures) {
|
| + [resultString appendFormat:@"// depth: %u, ref count: %u, used in method? %u\n", [[info type] structureDepth], [info referenceCount], [info isUsedInMethod]];
|
| + //[resultString appendFormat:@"// typedefName: %@\n", [info typedefName]];
|
| + }
|
| + formattedString = [aTypeFormatter formatVariable:nil parsedType:type symbolReferences:symbolReferences];
|
| + if (formattedString != nil) {
|
| + [resultString appendFormat:@"typedef %@ %@;\n\n", formattedString, [info typedefName]];
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (hasShownExceptions)
|
| + [resultString appendString:@"#endif\n\n"];
|
| +
|
| + if (debugNamedStructures) {
|
| + [resultString appendString:@"\n// Name exceptions:\n"];
|
| + for (CDStructureInfo *info in [[phase3_nameExceptions allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)])
|
| + [resultString appendFormat:@"// %@\n", [info shortDescription]];
|
| + [resultString appendString:@"\n"];
|
| + }
|
| +}
|
| +
|
| +- (void)appendTypedefsToString:(NSMutableString *)resultString
|
| + formatter:(CDTypeFormatter *)aTypeFormatter
|
| + symbolReferences:(CDSymbolReferences *)symbolReferences
|
| + markName:(NSString *)markName;
|
| +{
|
| + BOOL hasAddedMark = NO;
|
| + BOOL hasShownExceptions = NO;
|
| +
|
| + for (CDStructureInfo *info in [[phase3_anonStructureInfo allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + BOOL shouldShow;
|
| +
|
| + shouldShow = ![self shouldExpandStructureInfo:info];
|
| + if (shouldShow || debugAnonStructures) {
|
| + NSString *formattedString;
|
| +
|
| + if (hasAddedMark == NO) {
|
| + [resultString appendFormat:@"#pragma mark %@\n\n", markName];
|
| + hasAddedMark = YES;
|
| + }
|
| +
|
| + if (debugAnonStructures) {
|
| + [resultString appendFormat:@"// would normally show? %u\n", shouldShow];
|
| + [resultString appendFormat:@"// %@\n", [[info type] reallyBareTypeString]];
|
| + [resultString appendFormat:@"// depth: %u, ref: %u, used in method? %u\n", [[info type] structureDepth], [info referenceCount], [info isUsedInMethod]];
|
| + }
|
| + formattedString = [aTypeFormatter formatVariable:nil parsedType:[info type] symbolReferences:symbolReferences];
|
| + if (formattedString != nil) {
|
| + [resultString appendFormat:@"typedef %@ %@;\n\n", formattedString, [info typedefName]];
|
| + }
|
| + }
|
| + }
|
| +
|
| + // TODO (2009-08-25): Need same ref count rules for anon exceptions.
|
| + for (CDStructureInfo *info in [[phase3_anonExceptions allValues] sortedArrayUsingSelector:@selector(ascendingCompareByStructureDepth:)]) {
|
| + BOOL shouldShow;
|
| +
|
| + shouldShow = ![self shouldExpandStructureInfo:info];
|
| + if (shouldShow || debugAnonStructures) {
|
| + NSString *formattedString;
|
| +
|
| + if (hasAddedMark == NO) {
|
| + [resultString appendFormat:@"#pragma mark %@\n\n", markName];
|
| + hasAddedMark = YES;
|
| + }
|
| +
|
| + if (hasShownExceptions == NO) {
|
| + [resultString appendString:@"// Ambiguous groups\n"];
|
| + hasShownExceptions = YES;
|
| + }
|
| +
|
| + if (debugAnonStructures) {
|
| + [resultString appendFormat:@"// %@\n", [[info type] reallyBareTypeString]];
|
| + [resultString appendFormat:@"// depth: %u, ref: %u, used in method? %u\n", [[info type] structureDepth], [info referenceCount], [info isUsedInMethod]];
|
| + }
|
| + formattedString = [aTypeFormatter formatVariable:nil parsedType:[info type] symbolReferences:symbolReferences];
|
| + if (formattedString != nil) {
|
| + //[resultString appendFormat:@"%@;\n\n", formattedString];
|
| + [resultString appendFormat:@"typedef %@ %@;\n\n", formattedString, [info typedefName]];
|
| + }
|
| + }
|
| + }
|
| +
|
| + for (NSString *key in [[phase3_namedStructureInfo allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
| + CDStructureInfo *info;
|
| + BOOL shouldShow;
|
| +
|
| + info = [phase3_namedStructureInfo objectForKey:key];
|
| + shouldShow = [[info type] isTemplateType] && [info isUsedInMethod];
|
| + if (shouldShow || debugAnonStructures) {
|
| + NSString *formattedString;
|
| +
|
| + if (hasAddedMark == NO) {
|
| + [resultString appendFormat:@"#pragma mark %@\n\n", markName];
|
| + hasAddedMark = YES;
|
| + }
|
| +
|
| + if (hasShownExceptions == NO) {
|
| + [resultString appendString:@"// Template types\n"];
|
| + hasShownExceptions = YES;
|
| + }
|
| +
|
| + if (debugAnonStructures) {
|
| + [resultString appendFormat:@"// %@\n", [[info type] reallyBareTypeString]];
|
| + [resultString appendFormat:@"// depth: %u, ref: %u, used in method? %u\n", [[info type] structureDepth], [info referenceCount], [info isUsedInMethod]];
|
| + }
|
| + formattedString = [aTypeFormatter formatVariable:nil parsedType:[info type] symbolReferences:symbolReferences];
|
| + if (formattedString != nil) {
|
| + //[resultString appendFormat:@"%@;\n\n", formattedString];
|
| + [resultString appendFormat:@"typedef %@ %@;\n\n", formattedString, [info typedefName]];
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +- (void)generateTypedefNames;
|
| +{
|
| + for (CDStructureInfo *info in [phase3_anonStructureInfo allValues]) {
|
| + [info generateTypedefName:anonymousBaseName];
|
| + }
|
| +
|
| + // And do the same for each of the anon exceptions
|
| + for (CDStructureInfo *info in [phase3_anonExceptions allValues]) {
|
| + [info generateTypedefName:anonymousBaseName];
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [phase3_nameExceptions allValues]) {
|
| + [info generateTypedefName:[NSString stringWithFormat:@"%@_", [[[info type] typeName] name]]];
|
| + [[[info type] typeName] setName:@"?"];
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [phase3_namedStructureInfo allValues]) {
|
| + if ([[info type] isTemplateType] && [info isUsedInMethod]) {
|
| + [info generateTypedefName:[NSString stringWithFormat:@"%@_", [[[info type] typeName] name]]];
|
| + }
|
| + }
|
| +}
|
| +
|
| +- (void)generateMemberNames;
|
| +{
|
| + for (CDStructureInfo *info in [phase3_namedStructureInfo allValues]) {
|
| + [[info type] generateMemberNames];
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [phase3_anonStructureInfo allValues]) {
|
| + [[info type] generateMemberNames];
|
| + }
|
| +
|
| + for (CDStructureInfo *info in [phase3_nameExceptions allValues]) {
|
| + [[info type] generateMemberNames];
|
| + }
|
| +
|
| + // And do the same for each of the anon exceptions
|
| + for (CDStructureInfo *info in [phase3_anonExceptions allValues]) {
|
| + [[info type] generateMemberNames];
|
| + }
|
| +}
|
| +
|
| +- (BOOL)shouldExpandStructureInfo:(CDStructureInfo *)info;
|
| +{
|
| + return (info == nil)
|
| + || ([info isUsedInMethod] == NO
|
| + && ([[info type] isTemplateType] == NO || [info isUsedInMethod] == NO)
|
| + && [info referenceCount] < 2
|
| + && (([[info name] hasPrefix:@"_"] && [[info name] hasUnderscoreCapitalPrefix] == NO) // TODO: Don't need the first hasPrefix check now.
|
| + || [@"?" isEqualToString:[info name]]));
|
| +}
|
| +
|
| +// For automatic expansion?
|
| +- (BOOL)shouldExpandType:(CDType *)type;
|
| +{
|
| + NSString *name;
|
| + CDStructureInfo *info;
|
| +
|
| + name = [[type typeName] description];
|
| + if ([@"?" isEqualToString:name]) {
|
| + NSString *key;
|
| +
|
| + key = [type reallyBareTypeString];
|
| + info = [phase3_anonStructureInfo objectForKey:key];
|
| + if (info == nil) {
|
| + // Look for an exception
|
| + info = [phase3_anonExceptions objectForKey:[type typeString]];
|
| + }
|
| + } else {
|
| + info = [phase3_namedStructureInfo objectForKey:name];
|
| + if (info == nil) {
|
| + info = [phase3_nameExceptions objectForKey:[type typeString]];
|
| + if (info != nil) {
|
| + //NSLog(@"[%@] %s, found phase3 name exception... %@", identifier, _cmd, [info shortDescription]);
|
| + //return NO;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return [self shouldExpandStructureInfo:info];
|
| +}
|
| +
|
| +- (NSString *)typedefNameForType:(CDType *)type;
|
| +{
|
| + CDStructureInfo *info;
|
| +
|
| + info = [phase3_anonStructureInfo objectForKey:[type reallyBareTypeString]];
|
| + if (info == nil) {
|
| + info = [phase3_anonExceptions objectForKey:[type typeString]];
|
| + //NSLog(@"fallback typedef info? %@ -- %@", [info shortDescription], [info typedefName]);
|
| + }
|
| +
|
| + if (info == nil) {
|
| + // Check name exceptions
|
| + info = [phase3_nameExceptions objectForKey:[type typeString]];
|
| +#if 0
|
| + if (info != nil)
|
| + NSLog(@"Got typedef name for phase3 name exception: %@", [info typedefName]);
|
| +#endif
|
| + }
|
| +
|
| + if (info == nil) {
|
| + info = [phase3_namedStructureInfo objectForKey:[[type typeName] description]];
|
| + }
|
| +#if 0
|
| + if ([type isTemplateType] && [info typedefName] == nil) {
|
| + NSLog(@"Warning: no typedef name for type: %@", [type typeString]);
|
| + }
|
| +#endif
|
| +
|
| + return [info typedefName];
|
| +}
|
| +
|
| +- (void)debugName:(NSString *)name;
|
| +{
|
| + [debugNames addObject:name];
|
| +}
|
| +
|
| +- (void)debugAnon:(NSString *)str;
|
| +{
|
| + [debugAnon addObject:str];
|
| +}
|
| +
|
| +@end
|
|
|
| Property changes on: class-dump/src/CDStructureTable.m
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|