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

Generated by: LCOV version 1.14