LCOV - code coverage report
Current view: top level - Core/OXPVerifier - OOOXPVerifier.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 14 0.0 %
Date: 2025-12-19 09:33:35 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOOXPVerifier.m
       4             : 
       5             : 
       6             : Copyright (C) 2007-2013 Jens Ayton and contributors
       7             : 
       8             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9             : of this software and associated documentation files (the "Software"), to deal
      10             : in the Software without restriction, including without limitation the rights
      11             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             : copies of the Software, and to permit persons to whom the Software is
      13             : furnished to do so, subject to the following conditions:
      14             : 
      15             : The above copyright notice and this permission notice shall be included in all
      16             : copies or substantial portions of the Software.
      17             : 
      18             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             : SOFTWARE.
      25             : 
      26             : */
      27             : 
      28             : /*      Design notes:
      29             :         see "verifier design.txt".
      30             : */
      31             : 
      32             : #import "OOOXPVerifier.h"
      33             : 
      34             : #if OO_OXP_VERIFIER_ENABLED
      35             : 
      36             : #if OOLITE_WINDOWS
      37             : 
      38             : #ifdef __OBJC__
      39             : #pragma push_macro("interface")
      40             : #undef interface
      41             : #define interface struct
      42             : #endif
      43             : 
      44             : #include <shlwapi.h>
      45             : 
      46             : #ifdef __OBJC__
      47             : #pragma pop_macro("interface")
      48             : #endif
      49             : 
      50             : #include <tchar.h>
      51             : #endif
      52             : 
      53             : #import "OOOXPVerifierStageInternal.h"
      54             : #import "OOLoggingExtended.h"
      55             : #import "ResourceManager.h"
      56             : #import "OOCollectionExtractors.h"
      57             : #import "GameController.h"
      58             : #import "OOCacheManager.h"
      59             : #import "OODebugStandards.h"
      60             : 
      61             : static void SwitchLogFile(NSString *name);
      62             : static void NoteVerificationStage(NSString *displayName, NSString *stage);
      63             : static void OpenLogFile(NSString *name);
      64             : 
      65             : @interface OOOXPVerifier (OOPrivate)
      66             : 
      67           0 : - (id)initWithPath:(NSString *)path;
      68           0 : - (void)run;
      69             : 
      70           0 : - (void)setUpLogOverrides;
      71             : 
      72           0 : - (void)registerBaseStages;
      73           0 : - (void)buildDependencyGraph;
      74           0 : - (void)runStages;
      75             : 
      76           0 : - (BOOL)setUpDependencies:(NSSet *)dependencies
      77             :                                  forStage:(OOOXPVerifierStage *)stage;
      78             : 
      79           0 : - (void)setUpDependents:(NSSet *)dependents
      80             :                            forStage:(OOOXPVerifierStage *)stage;
      81             : 
      82           0 : - (void)dumpDebugGraphviz;
      83             : 
      84             : @end
      85             : 
      86             : 
      87             : @implementation OOOXPVerifier
      88             : 
      89             : /**
      90             :  * \ingroup cli
      91             :  * Scans the command line for -verify-oxp or --verify-oxp, followed by a
      92             :  * path to the oxp to verify.
      93             :  *
      94             :  * @return YES or NO
      95             :  */
      96             : + (BOOL)runVerificationIfRequested
      97             : {
      98             :         NSArray                         *arguments = nil;
      99             :         NSEnumerator            *argEnum = nil;
     100             :         NSString                        *arg = nil;
     101             :         NSString                        *foundPath = nil;
     102             :         BOOL                            exists, isDirectory;
     103             :         OOOXPVerifier           *verifier = nil;
     104             :         NSAutoreleasePool       *pool = nil;
     105             :         
     106             :         pool = [[NSAutoreleasePool alloc] init];
     107             :         
     108             :         arguments = [[NSProcessInfo processInfo] arguments];
     109             :         
     110             :         // Scan for -verify-oxp or --verify-oxp followed by relative path
     111             :         for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
     112             :         {
     113             :                 if ([arg isEqual:@"-verify-oxp"] || [arg isEqual:@"--verify-oxp"])
     114             :                 {
     115             :                         foundPath = [argEnum nextObject];
     116             :                         if (foundPath == nil)
     117             :                         {
     118             :                                 OOLog(@"verifyOXP.noPath", @"***** ERROR: %@ passed without path argument; nothing to verify.", arg);
     119             :                                 [pool release];
     120             :                                 return YES;
     121             :                         }
     122             :                         foundPath = [foundPath stringByExpandingTildeInPath];
     123             :                         break;
     124             :                 }
     125             :         }
     126             :         
     127             :         if (foundPath == nil)
     128             :         {
     129             :                 [pool release];
     130             :                 return NO;
     131             :         }
     132             :         
     133             :         // We got a path; does it point to a directory?
     134             :         exists = [[NSFileManager defaultManager] fileExistsAtPath:foundPath isDirectory:&isDirectory];
     135             :         if (!exists)
     136             :         {
     137             :                 OOLog(@"verifyOXP.badPath", @"***** ERROR: no OXP exists at path \"%@\"; nothing to verify.", foundPath);
     138             :         }
     139             :         else if (!isDirectory)
     140             :         {
     141             :                 OOLog(@"verifyOXP.badPath", @"***** ERROR: \"%@\" is a file, not an OXP directory; nothing to verify.", foundPath);
     142             :         }
     143             :         else
     144             :         {
     145             :                 verifier = [[OOOXPVerifier alloc] initWithPath:foundPath];
     146             :                 [pool release];
     147             :                 pool = [[NSAutoreleasePool alloc] init];
     148             :                 [verifier run];
     149             :                 [verifier release];
     150             :         }
     151             :         [pool release];
     152             :         
     153             :         // Whether or not we got a valid path, -verify-oxp was passed.
     154             :         return YES;
     155             : }
     156             : 
     157             : 
     158           0 : - (void)dealloc
     159             : {
     160             :         [_verifierPList release];
     161             :         [_basePath release];
     162             :         [_displayName release];
     163             :         [_stagesByName release];
     164             :         [_waitingStages release];
     165             :         
     166             :         [super dealloc];
     167             : }
     168             : 
     169             : 
     170             : - (void)registerStage:(OOOXPVerifierStage *)stage
     171             : {
     172             :         NSString                                *name = nil;
     173             :         OOOXPVerifierStage              *existing = nil;
     174             :         
     175             :         // Sanity checking
     176             :         if (stage == nil)  return;
     177             :         
     178             :         if (![stage isKindOfClass:[OOOXPVerifierStage class]])
     179             :         {
     180             :                 OOLog(@"verifyOXP.registration.failed", @"Attempt to register class %@ as a verifier stage, but it is not a subclass of OOOXPVerifierStage; ignoring.", [stage class]);
     181             :                 return;
     182             :         }
     183             :         
     184             :         if (!_openForRegistration)
     185             :         {
     186             :                 OOLog(@"verifyOXP.registration.failed", @"Attempt to register verifier stage %@ after registration closed, ignoring.", stage);
     187             :                 return;
     188             :         }
     189             :         
     190             :         name = [stage name];
     191             :         if (name == nil)
     192             :         {
     193             :                 OOLog(@"verifyOXP.registration.failed", @"Attempt to register verifier stage %@ with nil name, ignoring.", stage);
     194             :                 return;
     195             :         }
     196             :                 
     197             :         // We can only have one stage with a given name. Registering the same stage twice is OK, though.
     198             :         existing = [_stagesByName objectForKey:name];
     199             :         if (existing == stage)  return;
     200             :         if (existing != nil)
     201             :         {
     202             :                 OOLog(@"verifyOXP.registration.failed", @"Attempt to register verifier stage %@ with same name as stage %@, ignoring.", stage, existing);
     203             :                 return;
     204             :         }
     205             :         
     206             :         // Checks passed, store state.
     207             :         [stage setVerifier:self];
     208             :         [_stagesByName setObject:stage forKey:name];
     209             :         [_waitingStages addObject:stage];
     210             : }
     211             : 
     212             : 
     213             : - (NSString *)oxpPath
     214             : {
     215             :         return [[_basePath retain] autorelease];
     216             : }
     217             : 
     218             : 
     219             : - (NSString *)oxpDisplayName
     220             : {
     221             :         return [[_displayName retain] autorelease];
     222             : }
     223             : 
     224             : 
     225             : - (id)stageWithName:(NSString *)name
     226             : {
     227             :         if (name == nil)  return nil;
     228             :         
     229             :         return [_stagesByName objectForKey:name];
     230             : }
     231             : 
     232             : 
     233             : - (id)configurationValueForKey:(NSString *)key
     234             : {
     235             :         return [_verifierPList objectForKey:key];
     236             : }
     237             : 
     238             : 
     239             : - (NSArray *)configurationArrayForKey:(NSString *)key
     240             : {
     241             :         return [_verifierPList oo_arrayForKey:key];
     242             : }
     243             : 
     244             : 
     245             : - (NSDictionary *)configurationDictionaryForKey:(NSString *)key
     246             : {
     247             :         return [_verifierPList oo_dictionaryForKey:key];
     248             : }
     249             : 
     250             : 
     251             : - (NSString *)configurationStringForKey:(NSString *)key
     252             : {
     253             :         return [_verifierPList oo_stringForKey:key];
     254             : }
     255             : 
     256             : 
     257             : - (NSSet *)configurationSetForKey:(NSString *)key
     258             : {
     259             :         NSArray *array = [_verifierPList oo_arrayForKey:key];
     260             :         return array != nil ? [NSSet setWithArray:array] : nil;
     261             : }
     262             : 
     263             : @end
     264             : 
     265             : 
     266             : @implementation OOOXPVerifier (OOPrivate)
     267             : 
     268             : - (id)initWithPath:(NSString *)path
     269             : {
     270             :         self = [super init];
     271             : 
     272             :         OOSetStandardsForOXPVerifierMode();
     273             : 
     274             :         NSString *verifierPListPath = [[[ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"verifyOXP.plist"];
     275             :         _verifierPList = [[NSDictionary dictionaryWithContentsOfFile:verifierPListPath] retain];
     276             :         
     277             :         _basePath = [path copy];
     278             :         _displayName = [[NSFileManager defaultManager] displayNameAtPath:_basePath];
     279             :         if (_displayName == nil)  _displayName = [_basePath lastPathComponent];
     280             :         [_displayName retain];
     281             :         
     282             :         _stagesByName = [[NSMutableDictionary alloc] init];
     283             :         _waitingStages = [[NSMutableSet alloc] init];
     284             :         
     285             :         if (_verifierPList == nil ||
     286             :                 _basePath == nil)
     287             :         {
     288             :                 OOLog(@"verifyOXP.setup.failed", @"%@", @"***** ERROR: failed to set up OXP verifier.");
     289             :                 [self release];
     290             :                 return nil;
     291             :         }
     292             :         
     293             :         _openForRegistration = YES;
     294             :         
     295             :         return self;
     296             : }
     297             : 
     298             : 
     299             : - (void)run
     300             : {
     301             :         NoteVerificationStage(_displayName, @"");
     302             :         
     303             :         [self setUpLogOverrides];
     304             :         
     305             :         /*      We need to be able to look up internal files, but not other OXP files.
     306             :                 To do this without clobbering the disk cache, we disable cache writes.
     307             :         */
     308             :         [[OOCacheManager sharedCache] flush];
     309             :         [[OOCacheManager sharedCache] setAllowCacheWrites:NO];
     310             :         /* FIXME: the OXP verifier should load files from OXPs which have
     311             :          * been explicitly listed as required_oxps in the
     312             :          * manifest. Reading the manifest from the OXP being verified and
     313             :          * setting 'id:<its identifier>' below will do this. */
     314             :         [ResourceManager setUseAddOns:SCENARIO_OXP_DEFINITION_NONE];
     315             :         
     316             :         SwitchLogFile(_displayName);
     317             :         OOLog(@"verifyOXP.start", @"Running OXP verifier for %@", _basePath);//_displayName);
     318             :         
     319             :         [self registerBaseStages];
     320             :         [self buildDependencyGraph];
     321             :         [self runStages];
     322             :         
     323             :         NoteVerificationStage(_displayName, @"");
     324             :         OOLog(@"verifyOXP.done", @"%@", @"OXP verification complete.");
     325             :         
     326             :         OpenLogFile(_displayName);
     327             : }
     328             : 
     329             : 
     330             : - (void)setUpLogOverrides
     331             : {
     332             :         NSDictionary                    *overrides = nil;
     333             :         NSEnumerator                    *messageClassEnum = nil;
     334             :         NSString                                *messageClass = nil;
     335             :         id                                              verbose = nil;
     336             :         
     337             :         OOLogSetShowMessageClassTemporary([_verifierPList oo_boolForKey:@"logShowMessageClassOverride" defaultValue:NO]);
     338             :         
     339             :         overrides = [_verifierPList oo_dictionaryForKey:@"logControlOverride"];
     340             :         for (messageClassEnum = [overrides keyEnumerator]; (messageClass = [messageClassEnum nextObject]); )
     341             :         {
     342             :                 OOLogSetDisplayMessagesInClass(messageClass, [overrides oo_boolForKey:messageClass defaultValue:NO]);
     343             :         }
     344             :         
     345             :         /*      Since actually editing logControlOverride is a pain, we also allow
     346             :                 overriding verifyOXP.verbose through user defaults. This is at least
     347             :                 as much a pain under GNUstep, but very convenient under OS X.
     348             :         */
     349             :         verbose = [[NSUserDefaults standardUserDefaults] objectForKey:@"oxp-verifier-verbose-logging"];
     350             :         if (verbose != nil)  OOLogSetDisplayMessagesInClass(@"verifyOXP.verbose", OOBooleanFromObject(verbose, NO));
     351             : }
     352             : 
     353             : 
     354             : - (void)registerBaseStages
     355             : {
     356             :         NSAutoreleasePool               *pool = nil;
     357             :         NSSet                                   *stages = nil;
     358             :         NSSet                                   *excludeStages = nil;
     359             :         NSEnumerator                    *stageEnum = nil;
     360             :         NSString                                *stageName = nil;
     361             :         Class                                   stageClass = Nil;
     362             :         OOOXPVerifierStage              *stage = nil;
     363             :         
     364             :         pool = [[NSAutoreleasePool alloc] init];
     365             :         
     366             :         // Load stages specified as array of class names in verifyOXP.plist
     367             :         stages = [self configurationSetForKey:@"stages"];
     368             :         excludeStages = [self configurationSetForKey:@"excludeStages"];
     369             :         if ([excludeStages count] != 0)
     370             :         {
     371             :                 stages = [[stages mutableCopy] autorelease];
     372             :                 [(NSMutableSet *)stages minusSet:excludeStages];
     373             :         }
     374             :         for (stageEnum = [stages objectEnumerator]; (stageName = [stageEnum nextObject]); )
     375             :         {
     376             :                 if ([stageName isKindOfClass:[NSString class]])
     377             :                 {
     378             :                         stageClass = NSClassFromString(stageName);
     379             :                         if (stageClass == Nil)
     380             :                         {
     381             :                                 OOLog(@"verifyOXP.registration.failed", @"Attempt to register unknown class %@ as a verifier stage, ignoring.", stageName);
     382             :                                 continue;
     383             :                         }
     384             :                         stage = [[stageClass alloc] init];
     385             :                         [self registerStage:stage];
     386             :                         [stage release];
     387             :                 }
     388             :         }
     389             :         
     390             :         [pool release];
     391             : }
     392             : 
     393             : 
     394             : - (void)buildDependencyGraph
     395             : {
     396             :         NSAutoreleasePool               *pool = nil;
     397             :         NSArray                                 *stageKeys = nil;
     398             :         NSEnumerator                    *stageEnum = nil;
     399             :         NSString                                *stageKey = nil;
     400             :         OOOXPVerifierStage              *stage = nil;
     401             :         NSString                                *name = nil;
     402             :         NSMutableDictionary             *dependenciesByStage = nil,
     403             :                                                         *dependentsByStage = nil;
     404             :         NSSet                                   *dependencies = nil,
     405             :                                                         *dependents = nil;
     406             :         NSValue                                 *key = nil;
     407             :         
     408             :         pool = [[NSAutoreleasePool alloc] init];
     409             :         
     410             :         /*      Iterate over all stages, getting dependency and dependent sets.
     411             :                 This is done in advance so that -dependencies and -dependents may
     412             :                 register stages.
     413             :         */
     414             :         dependenciesByStage = [NSMutableDictionary dictionary];
     415             :         dependentsByStage = [NSMutableDictionary dictionary];
     416             :         
     417             :         for (;;)
     418             :         {
     419             :                 /*      Loop while there are stages whose dependency lists haven't been
     420             :                         checked. This is an indeterminate loop since new ones can be
     421             :                         added.
     422             :                 */
     423             :                 stage = [_waitingStages anyObject];
     424             :                 if (stage == nil)  break;
     425             :                 [_waitingStages removeObject:stage];
     426             :                 
     427             :                 key = [NSValue valueWithNonretainedObject:stage];
     428             :                 
     429             :                 dependencies = [stage dependencies];
     430             :                 if (dependencies != nil)
     431             :                 {
     432             :                         [dependenciesByStage setObject:dependencies
     433             :                                                                         forKey:key];
     434             :                 }
     435             :                 
     436             :                 dependents = [stage dependents];
     437             :                 if (dependents != nil)
     438             :                 {
     439             :                         [dependentsByStage setObject:dependents
     440             :                                                                   forKey:key];
     441             :                 }
     442             :         }
     443             :         [_waitingStages release];
     444             :         _waitingStages = nil;
     445             :         _openForRegistration = NO;
     446             :         
     447             :         // Iterate over all stages, resolving dependencies.
     448             :         stageKeys = [_stagesByName allKeys];    // Get the keys up front because we may need to remove entries from dictionary.
     449             :         
     450             :         for (stageEnum = [stageKeys objectEnumerator]; (stageKey = [stageEnum nextObject]); )
     451             :         {
     452             :                 stage = [_stagesByName objectForKey:stageKey];
     453             :                 if (stage == nil)  continue;
     454             :                 
     455             :                 // Sanity check
     456             :                 name = [stage name];
     457             :                 if (![stageKey isEqualToString:name])
     458             :                 {
     459             :                         OOLog(@"verifyOXP.buildDependencyGraph.badName", @"***** Stage name appears to have changed from \"%@\" to \"%@\" for verifier stage %@, removing.", stageKey, name, stage);
     460             :                         [_stagesByName removeObjectForKey:stageKey];
     461             :                         continue;
     462             :                 }
     463             :                 
     464             :                 // Get dependency set
     465             :                 key = [NSValue valueWithNonretainedObject:stage];
     466             :                 dependencies = [dependenciesByStage objectForKey:key];
     467             :                 
     468             :                 if (dependencies != nil && ![self setUpDependencies:dependencies forStage:stage])
     469             :                 {
     470             :                         [_stagesByName removeObjectForKey:stageKey];
     471             :                 }
     472             :         }
     473             :         
     474             :         /*      Iterate over all stages again, resolving reverse dependencies.
     475             :                 This is done in a separate pass because reverse dependencies are "weak"
     476             :                 while forward dependencies are "strong". 
     477             :         */
     478             :         stageKeys = [_stagesByName allKeys];
     479             :         
     480             :         for (stageEnum = [stageKeys objectEnumerator]; (stageKey = [stageEnum nextObject]); )
     481             :         {
     482             :                 stage = [_stagesByName objectForKey:stageKey];
     483             :                 if (stage == nil)  continue;
     484             :                 
     485             :                 // Get dependent set
     486             :                 key = [NSValue valueWithNonretainedObject:stage];
     487             :                 dependents = [dependentsByStage objectForKey:key];
     488             :                 
     489             :                 if (dependents != nil)
     490             :                 {
     491             :                         [self setUpDependents:dependents forStage:stage];
     492             :                 }
     493             :         }
     494             :         
     495             :         _waitingStages = [[NSMutableSet alloc] initWithArray:[_stagesByName allValues]];
     496             :         [_waitingStages makeObjectsPerformSelector:@selector(dependencyRegistrationComplete)];
     497             :         
     498             :         if ([[NSUserDefaults standardUserDefaults] boolForKey:@"oxp-verifier-dump-debug-graphviz"])
     499             :         {
     500             :                 [self dumpDebugGraphviz];
     501             :         }
     502             :         
     503             :         [pool release];
     504             : }
     505             : 
     506             : 
     507             : - (void)runStages
     508             : {
     509             :         NSAutoreleasePool               *pool = nil;
     510             :         NSEnumerator                    *stageEnum = nil;
     511             :         OOOXPVerifierStage              *candidateStage = nil,
     512             :                                                         *stageToRun = nil;
     513             :         NSString                                *stageName = nil;
     514             :         
     515             :         // Loop while there are still stages to run.
     516             :         for (;;)
     517             :         {
     518             :                 pool = [[NSAutoreleasePool alloc] init];
     519             :                 
     520             :                 // Look through queue for a stage that's ready
     521             :                 stageToRun = nil;
     522             :                 for (stageEnum = [_waitingStages objectEnumerator]; (candidateStage = [stageEnum nextObject]); )
     523             :                 {
     524             :                         if ([candidateStage canRun])
     525             :                         {
     526             :                                 stageToRun = candidateStage;
     527             :                                 break;
     528             :                         }
     529             :                 }
     530             :                 if (stageToRun == nil)
     531             :                 {
     532             :                         // No more runnable stages
     533             :                         [pool release];
     534             :                         break;
     535             :                 }
     536             :                 
     537             :                 stageName = nil;
     538             :                 OOLogPushIndent();
     539             :                 @try
     540             :                 {
     541             :                         stageName = [stageToRun name];
     542             :                         if ([stageToRun shouldRun])
     543             :                         {
     544             :                                 NoteVerificationStage(_displayName, stageName);
     545             :                                 OOLog(@"verifyOXP.runStage", @"%@", stageName);
     546             :                                 OOLogIndent();
     547             :                                 [stageToRun performRun];
     548             :                         }
     549             :                         else
     550             :                         {
     551             :                                 OOLog(@"verifyOXP.verbose.skipStage", @"- Skipping stage: %@ (nothing to do).", stageName);
     552             :                                 [stageToRun noteSkipped];
     553             :                         }
     554             :                 }
     555             :                 @catch (NSException *exception)
     556             :                 {
     557             :                         if (stageName == nil)  stageName = [[stageToRun class] description];
     558             :                         OOLog(@"verifyOXP.exception", @"***** Exception occurred when running OXP verifier stage \"%@\": %@: %@", stageName, [exception name], [exception reason]);
     559             :                 }
     560             :                 OOLogPopIndent();
     561             :                 
     562             :                 [_waitingStages removeObject:stageToRun];
     563             :                 [pool release];
     564             :         }
     565             :         
     566             :         pool = [[NSAutoreleasePool alloc] init];
     567             :         
     568             :         if ([_waitingStages count] != 0)
     569             :         {
     570             :                 OOLog(@"verifyOXP.incomplete", @"%@", @"Some verifier stages could not be run:");
     571             :                 OOLogIndent();
     572             :                 for (stageEnum = [_waitingStages objectEnumerator]; (candidateStage = [stageEnum nextObject]); )
     573             :                 {
     574             :                         OOLog(@"verifyOXP.incomplete.item", @"%@", candidateStage);
     575             :                 }
     576             :                 OOLogOutdent();
     577             :         }
     578             :         [_waitingStages release];
     579             :         _waitingStages = nil;
     580             :         
     581             :         [pool release];
     582             : }
     583             : 
     584             : 
     585             : - (BOOL)setUpDependencies:(NSSet *)dependencies
     586             :                                  forStage:(OOOXPVerifierStage *)stage
     587             : {
     588             :         NSString                                *depName = nil;
     589             :         NSEnumerator                    *depEnum = nil;
     590             :         OOOXPVerifierStage              *depStage = nil;
     591             :         
     592             :         // Iterate over dependencies, connecting them up.
     593             :         for (depEnum = [dependencies objectEnumerator]; (depName = [depEnum nextObject]); )
     594             :         {
     595             :                 depStage = [_stagesByName objectForKey:depName];
     596             :                 if (depStage == nil)
     597             :                 {
     598             :                         OOLog(@"verifyOXP.buildDependencyGraph.unresolved", @"Verifier stage %@ has unresolved dependency \"%@\", skipping.", stage, depName);
     599             :                         return NO;
     600             :                 }
     601             :                 
     602             :                 if ([depStage isDependentOf:stage])
     603             :                 {
     604             :                         OOLog(@"verifyOXP.buildDependencyGraph.circularReference", @"Verifier stages %@ and %@ have a dependency loop, skipping.", stage, depStage);
     605             :                         [_stagesByName removeObjectForKey:depName];
     606             :                         return NO;
     607             :                 }
     608             :                 
     609             :                 [stage registerDependency:depStage];
     610             :         }
     611             :         
     612             :         return YES;
     613             : }
     614             : 
     615             : 
     616             : - (void)setUpDependents:(NSSet *)dependents
     617             :                            forStage:(OOOXPVerifierStage *)stage
     618             : {
     619             :         NSString                                *depName = nil;
     620             :         NSEnumerator                    *depEnum = nil;
     621             :         OOOXPVerifierStage              *depStage = nil;
     622             :         
     623             :         // Iterate over dependents, connecting them up.
     624             :         for (depEnum = [dependents objectEnumerator]; (depName = [depEnum nextObject]); )
     625             :         {
     626             :                 depStage = [_stagesByName objectForKey:depName];
     627             :                 if (depStage == nil)
     628             :                 {
     629             :                         OOLog(@"verifyOXP.buildDependencyGraph.unresolved", @"Verifier stage %@ has unresolved dependent \"%@\".", stage, depName);
     630             :                         continue;       // Unresolved/conflicting dependents are non-fatal
     631             :                 }
     632             :                 
     633             :                 if ([stage isDependentOf:depStage])
     634             :                 {
     635             :                         OOLog(@"verifyOXP.buildDependencyGraph.circularReference", @"Verifier stage %@ lists %@ as both dependent and dependency (possibly indirectly); will execute %@ after %@.", stage, depStage, stage, depStage);
     636             :                         continue;
     637             :                 }
     638             :                 
     639             :                 [depStage registerDependency:stage];
     640             :         }
     641             : }
     642             : 
     643             : 
     644             : - (void)dumpDebugGraphviz
     645             : {
     646             :         NSMutableString                         *graphViz = nil;
     647             :         NSDictionary                            *graphVizTemplate = nil;
     648             :         NSString                                        *template = nil,
     649             :                                                                 *startTemplate = nil,
     650             :                                                                 *endTemplate = nil;
     651             :         NSEnumerator                            *stageEnum = nil;
     652             :         OOOXPVerifierStage                      *stage = nil;
     653             :         NSSet                                           *deps = nil;
     654             :         NSEnumerator                            *depEnum = nil;
     655             :         OOOXPVerifierStage                      *dep = nil;
     656             :         
     657             :         graphVizTemplate = [self configurationDictionaryForKey:@"debugGraphvizTempate"];
     658             :         graphViz = [NSMutableString stringWithFormat:[graphVizTemplate oo_stringForKey:@"preamble"], [NSDate date]];
     659             :         
     660             :         /*      Pass 1: enumerate over graph setting node attributes for each stage.
     661             :                 We use pointers as node names for simplicity of generation.
     662             :         */
     663             :         template = [graphVizTemplate oo_stringForKey:@"node"];
     664             :         for (stageEnum = [_stagesByName objectEnumerator]; (stage = [stageEnum nextObject]); )
     665             :         {
     666             :                 [graphViz appendFormat:template, stage, [stage class], [stage name]];
     667             :         }
     668             :         
     669             :         [graphViz appendString:[graphVizTemplate oo_stringForKey:@"forwardPreamble"]];
     670             :         
     671             :         /*      Pass 2: enumerate over graph setting forward arcs for each dependency.
     672             :         */
     673             :         template = [graphVizTemplate oo_stringForKey:@"forwardArc"];
     674             :         startTemplate = [graphVizTemplate oo_stringForKey:@"startArc"];
     675             :         for (stageEnum = [_stagesByName objectEnumerator]; (stage = [stageEnum nextObject]); )
     676             :         {
     677             :                 deps = [stage resolvedDependencies];
     678             :                 if ([deps count] != 0)
     679             :                 {
     680             :                         for (depEnum = [deps objectEnumerator]; (dep = [depEnum nextObject]); )
     681             :                         {
     682             :                                 [graphViz appendFormat:template, dep, stage];
     683             :                         }
     684             :                 }
     685             :                 else
     686             :                 {
     687             :                         [graphViz appendFormat:startTemplate, stage];
     688             :                 }
     689             :         }
     690             :         
     691             :         [graphViz appendString:[graphVizTemplate oo_stringForKey:@"backwardPreamble"]];
     692             :         
     693             :         /*      Pass 3: enumerate over graph setting backward arcs for each dependent.
     694             :         */
     695             :         template = [graphVizTemplate oo_stringForKey:@"backwardArc"];
     696             :         endTemplate = [graphVizTemplate oo_stringForKey:@"endArc"];
     697             :         for (stageEnum = [_stagesByName objectEnumerator]; (stage = [stageEnum nextObject]); )
     698             :         {
     699             :                 deps = [stage resolvedDependents];
     700             :                 if ([deps count] != 0)
     701             :                 {
     702             :                         for (depEnum = [deps objectEnumerator]; (dep = [depEnum nextObject]); )
     703             :                         {
     704             :                                 [graphViz appendFormat:template, dep, stage];
     705             :                         }
     706             :                 }
     707             :                 else
     708             :                 {
     709             :                         [graphViz appendFormat:endTemplate, stage];
     710             :                 }
     711             :         }
     712             :         
     713             :         [graphViz appendString:[graphVizTemplate oo_stringForKey:@"postamble"]];
     714             :         
     715             :         // Write file
     716             :         [ResourceManager writeDiagnosticString:graphViz toFileNamed:@"OXPVerifierStageDependencies.dot"];
     717             : }
     718             : 
     719             : @end
     720             : 
     721             : 
     722             : #import "OOLogOutputHandler.h"
     723             : 
     724             : 
     725           0 : static void SwitchLogFile(NSString *name)
     726             : {
     727             : //#ifndef OOLITE_LINUX
     728             :         name = [name stringByAppendingPathExtension:@"log"];
     729             :         OOLog(@"verifyOXP.switchingLog", @"Switching log files -- logging to \"%@\".", name);
     730             :         OOLogOutputHandlerChangeLogFile(name);
     731             : //#else
     732             : //      OOLog(@"verifyOXP.switchingLog", @"Switching logging to <stdout>.");
     733             : //      OOLogOutputHandlerStartLoggingToStdout();
     734             : //#endif
     735             : }
     736             : 
     737             : 
     738           0 : static void NoteVerificationStage(NSString *displayName, NSString *stage)
     739             : {
     740             :         [[GameController sharedController] logProgress:[NSString stringWithFormat:@"Verifying %@\n%@", displayName, stage]];
     741             : }
     742             : 
     743             : 
     744           0 : static void OpenLogFile(NSString *name)
     745             : {
     746             :         //      Open log file in appropriate application / provide feedback.
     747             :         
     748             :         if ([[NSUserDefaults standardUserDefaults] oo_boolForKey:@"oxp-verifier-open-log" defaultValue:YES])
     749             :         {
     750             : #if OOLITE_MAC_OS_X
     751             :                 [[NSWorkspace sharedWorkspace] openFile:OOLogHandlerGetLogPath()];
     752             : #elif OOLITE_WINDOWS
     753             :                 // identify the application set by the OS as the default app for opening .log files
     754             :                 // in case anything goes wrong, fall back to opening the log file in Motepad
     755             :                 DWORD dwSize = MAX_PATH;
     756             :                 TCHAR applicationPath[MAX_PATH] = TEXT("notepad");
     757             :                 HRESULT hr = AssocQueryString (0, //ASSOCF_NONE 
     758             :                                                 ASSOCSTR_EXECUTABLE,
     759             :                                                 _T(".log"),
     760             :                                                 _T("open"),
     761             :                                                 applicationPath,
     762             :                                                 &dwSize);
     763             :                                                 
     764             :                 if (FAILED (hr))
     765             :                 {
     766             :                         OOLog(@"OXP Verifier", @"Could not find application for opening .log files - using Notepad by default.");
     767             :                 }
     768             :                 
     769             :                 // open the log file
     770             :                 system([[NSString stringWithFormat:@"start \"\" \"%s\" \"Logs\\%@.log\"", applicationPath, name] UTF8String]);
     771             : #elif  OOLITE_LINUX
     772             :                 // MKW - needed to suppress 'ignoring return value' warning for system() call
     773             :                 //              int ret;
     774             :                 // CIM - and now the compiler complains about that too... casting return
     775             :                 // value to void seems to keep it quiet for now
     776             :                 // Nothing to do here, since we dump to stdout instead of to a file.
     777             :                 //OOLogOutputHandlerStopLoggingToStdout();
     778             :                 (void) system([[NSString stringWithFormat:@"cat \"%@\"", OOLogHandlerGetLogPath()] UTF8String]);
     779             : #else 
     780             :                 do {} while (0);
     781             : #endif
     782             :         }
     783             : }
     784             : 
     785             : 
     786             : #endif  // OO_OXP_VERIFIER_ENABLED

Generated by: LCOV version 1.14