Oolite 1.91.0.7671-250514-dc597d5
All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
OOOXPVerifier.m
Go to the documentation of this file.
1/*
2
3OOOXPVerifier.m
4
5
6Copyright (C) 2007-2013 Jens Ayton and contributors
7
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in all
16copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24SOFTWARE.
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
42#import "OOLoggingExtended.h"
43#import "ResourceManager.h"
45#import "GameController.h"
46#import "OOCacheManager.h"
47#import "OODebugStandards.h"
48
49static void SwitchLogFile(NSString *name);
50static void NoteVerificationStage(NSString *displayName, NSString *stage);
51static void OpenLogFile(NSString *name);
52
53@interface OOOXPVerifier (OOPrivate)
54
55- (id)initWithPath:(NSString *)path;
56- (void)run;
57
58- (void)setUpLogOverrides;
59
60- (void)registerBaseStages;
62- (void)runStages;
63
64- (BOOL)setUpDependencies:(NSSet *)dependencies
65 forStage:(OOOXPVerifierStage *)stage;
66
67- (void)setUpDependents:(NSSet *)dependents
68 forStage:(OOOXPVerifierStage *)stage;
69
70- (void)dumpDebugGraphviz;
71
72@end
73
74
75@implementation OOOXPVerifier
76
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- (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
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
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 */
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];
309 [self runStages];
310
311 NoteVerificationStage(_displayName, @"");
312 OOLog(@"verifyOXP.done", @"%@", @"OXP verification complete.");
313
314 OpenLogFile(_displayName);
315}
316
317
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
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
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
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;
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 }
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
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 {
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
713static void SwitchLogFile(NSString *name)
714{
715//#ifndef OOLITE_LINUX
716 name = [name stringByAppendingPathExtension:@"log"];
717 OOLog(@"verifyOXP.switchingLog", @"Switching log files -- logging to \"%@\".", name);
719//#else
720// OOLog(@"verifyOXP.switchingLog", @"Switching logging to <stdout>.");
721// OOLogOutputHandlerStartLoggingToStdout();
722//#endif
723}
724
725
726static void NoteVerificationStage(NSString *displayName, NSString *stage)
727{
728 [[GameController sharedController] logProgress:[NSString stringWithFormat:@"Verifying %@\n%@", displayName, stage]];
729}
730
731
732static 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
BOOL OOBooleanFromObject(id object, BOOL defaultValue)
void OOSetStandardsForOXPVerifierMode(void)
NSString * OOLogHandlerGetLogPath(void)
void OOLogOutputHandlerChangeLogFile(NSString *newLogName)
void OOLogPushIndent(void)
Definition OOLogging.m:316
void OOLogPopIndent(void)
Definition OOLogging.m:340
void OOLogOutdent(void)
Definition OOLogging.m:376
#define OOLog(class, format,...)
Definition OOLogging.h:88
void OOLogIndent(void)
Definition OOLogging.m:366
void OOLogSetDisplayMessagesInClass(NSString *inClass, BOOL inFlag)
Definition OOLogging.m:182
void OOLogSetShowMessageClassTemporary(BOOL flag)
Definition OOLogging.m:579
static void SwitchLogFile(NSString *name)
static void NoteVerificationStage(NSString *displayName, NSString *stage)
static void OpenLogFile(NSString *name)
unsigned count
return nil
BOOL runVerificationIfRequested()
GameController * sharedController()
void logProgress:(NSString *message)
void setAllowCacheWrites:(BOOL flag)
OOCacheManager * sharedCache()
void setVerifier:(OOOXPVerifier *verifier)
void registerBaseStages()
void setUpDependents:forStage:(NSSet *dependents,[forStage] OOOXPVerifierStage *stage)
BOOL _openForRegistration
NSSet * configurationSetForKey:(NSString *key)
void buildDependencyGraph()
void registerStage:(OOOXPVerifierStage *stage)
NSDictionary * configurationDictionaryForKey:(NSString *key)
NSString * oxpPath()
NSString * oxpDisplayName()
NSString * builtInPath()
BOOL writeDiagnosticString:toFileNamed:(NSString *string,[toFileNamed] NSString *name)
void setUseAddOns:(NSString *useAddOns)