//  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-2006  Steve Nygard

#import "CDObjCSegmentProcessor.h"

#include <mach-o/arch.h>

#import <Foundation/Foundation.h>
#import "CDClassDump.h"
#import "CDDylibCommand.h"
#import "CDMachOFile.h"
#import "CDOCCategory.h"
#import "CDOCClass.h"
#import "CDOCIvar.h"
#import "CDOCMethod.h"
#import "CDOCModule.h"
#import "CDOCProtocol.h"
#import "CDOCSymtab.h"
#import "CDSection.h"
#import "CDSegmentCommand.h"
#import "NSArray-Extensions.h"
#import "CDObjCSegmentProcessor-Private.h"

@implementation CDObjCSegmentProcessor

- (id)initWithMachOFile:(CDMachOFile *)aMachOFile;
{
    if ([super init] == nil)
        return nil;

    machOFile = [aMachOFile retain];
    modules = [[NSMutableArray alloc] init];
    protocolsByName = [[NSMutableDictionary alloc] init];

    return self;
}

- (void)dealloc;
{
    [machOFile release];
    [modules release];
    [protocolsByName release];

    [super dealloc];
}

- (BOOL)hasModules;
{
    return [modules count] > 0;
}

- (void)process;
{
    [self processProtocolSection];
    [self processModules];
}

- (void)appendFormattedString:(NSMutableString *)resultString classDump:(CDClassDump *)aClassDump;
{
    int count, index;
    NSMutableArray *allClasses;
    NSArray *protocolNames;

    allClasses = [[NSMutableArray alloc] init];

    count = [modules count];
    for (index = 0; index < count; index++) {
        NSArray *moduleClasses, *moduleCategories;

        moduleClasses = [[[modules objectAtIndex:index] symtab] classes];
        if (moduleClasses != nil)
            [allClasses addObjectsFromArray:moduleClasses];

        moduleCategories = [[[modules objectAtIndex:index] symtab] categories];
        if (moduleCategories != nil)
            [allClasses addObjectsFromArray:moduleCategories];
    }

    // TODO: Sort protocols by dependency
    // TODO (2004-01-30): It looks like protocols might be defined in more than one file.  i.e. NSObject.
    // TODO (2004-02-02): Looks like we need to record the order the protocols were encountered, or just always sort protocols
    protocolNames = [[protocolsByName allKeys] sortedArrayUsingSelector:@selector(compare:)];

    if ([protocolNames count] > 0 || [allClasses count] > 0) {
        const NXArchInfo *archInfo;

        [resultString appendString:@"/*\n"];
        [resultString appendFormat:@" * File: %@\n", [machOFile filename]];

        archInfo = NXGetArchInfoFromCpuType([machOFile cpuType], [machOFile cpuSubtype]);
        if (archInfo != NULL)
            [resultString appendFormat:@" * Arch: %s (%s)\n", archInfo->description, archInfo->name];

        if ([machOFile filetype] == MH_DYLIB) {
            CDDylibCommand *identifier;

            identifier = [machOFile dylibIdentifier];
            if (identifier != nil)
                [resultString appendFormat:@" *       Current version: %@, Compatibility version: %@\n",
                              [identifier formattedCurrentVersion], [identifier formattedCompatibilityVersion]];
        }
        [resultString appendString:@" */\n\n"];
    }

    count = [protocolNames count];
    for (index = 0; index < count; index++) {
        CDOCProtocol *aProtocol;

        aProtocol = [protocolsByName objectForKey:[protocolNames objectAtIndex:index]];
        [aProtocol appendToString:resultString classDump:aClassDump symbolReferences:nil];
    }

    if ([aClassDump shouldSortClassesByInheritance] == YES) {
        [allClasses sortTopologically];
    } else if ([aClassDump shouldSortClasses] == YES)
        [allClasses sortUsingSelector:@selector(ascendingCompareByName:)];

    count = [allClasses count];
    for (index = 0; index < count; index++)
        [[allClasses objectAtIndex:index] appendToString:resultString classDump:aClassDump symbolReferences:nil];

    [allClasses release];
}

- (void)registerStructuresWithObject:(id <CDStructureRegistration>)anObject phase:(int)phase;
{
    int count, index;
    NSArray *protocolNames;

    count = [modules count];
    for (index = 0; index < count; index++)
        [[[modules objectAtIndex:index] symtab] registerStructuresWithObject:anObject phase:phase];

    protocolNames = [[protocolsByName allKeys] sortedArrayUsingSelector:@selector(compare:)];
    count = [protocolNames count];
    for (index = 0; index < count; index++) {
        CDOCProtocol *aProtocol;

        aProtocol = [protocolsByName objectForKey:[protocolNames objectAtIndex:index]];
        [aProtocol registerStructuresWithObject:anObject phase:phase];
    }
}

- (NSString *)description;
{
    return [NSString stringWithFormat:@"[%@] machOFile: %@", NSStringFromClass([self class]), [machOFile filename]];
}

- (void)registerClassesWithObject:(NSMutableDictionary *)aDictionary;
{
    NSString *importBaseName;

    importBaseName = [machOFile importBaseName];
    if (importBaseName != nil) {
        int count, index;

        count = [modules count];
        for (index = 0; index < count; index++) {
            [[modules objectAtIndex:index] registerClassesWithObject:aDictionary frameworkName:importBaseName];
        }
    }
}

- (void)generateSeparateHeadersClassDump:(CDClassDump *)aClassDump;
{
    int count, index;

    count = [modules count];
    for (index = 0; index < count; index++)
        [[modules objectAtIndex:index] generateSeparateHeadersClassDump:aClassDump];
}

@end
