Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
Classes | Macros | Enumerations | Functions
OOStringExpander.m File Reference
import "OOCocoa.h"
import "OOStringExpander.h"
import "Universe.h"
import "OOJavaScriptEngine.h"
import "OOCollectionExtractors.h"
import "OOStringParsing.h"
import "ResourceManager.h"
import "PlayerEntityScriptMethods.h"
import "PlayerEntity.h"
+ Include dependency graph for OOStringExpander.m:

Go to the source code of this file.

Classes

struct  OOStringExpansionContext
 

Macros

#define WARNINGS   OOLITE_DEBUG
 
#define OO_EXPANDER_RANDOM   (context->useGoodRNG ? (Ranrot()&0xFF) : gen_rnd_number())
 
#define SyntaxError(CONTEXT, CLASS, FORMAT, ...)   SyntaxIssue(CONTEXT, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, CLASS, OOLOG_WARNING_PREFIX, FORMAT, ## __VA_ARGS__)
 
#define SyntaxWarning(CONTEXT, CLASS, FORMAT, ...)   SyntaxIssue(CONTEXT, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, CLASS, OOLOG_WARNING_PREFIX, FORMAT, ## __VA_ARGS__)
 
#define OPERATOR(name)   [NSValue valueWithPointer:Operator_##name], @#name
 
#define kInvalidGEscapeMessage   @"String escape code %G must be followed by six integers."
 
#define kInvalidJEscapeMessage   @"String escape code %J must be followed by three integers."
 

Enumerations

enum  { kStackAllocationLimit = UINT16_MAX , kRecursionLimit = 100 }
 

Functions

static NSString * GetSystemName (OOStringExpansionContext *context)
 
static NSString * GetSystemNameIan (OOStringExpansionContext *context)
 
static NSString * GetRandomNameN (OOStringExpansionContext *context)
 
static NSString * GetRandomNameR (OOStringExpansionContext *context)
 
static NSArray * GetSystemDescriptions (OOStringExpansionContext *context)
 
static void AppendCharacters (NSMutableString **result, const unichar *characters, NSUInteger start, NSUInteger end)
 
static NSString * NewRandomDigrams (OOStringExpansionContext *context)
 
static NSString * OldRandomDigrams (void)
 
static NSString * Expand (OOStringExpansionContext *context, NSString *string, NSUInteger sizeLimit, NSUInteger recursionLimit)
 
static NSString * ExpandKey (OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength, NSUInteger sizeLimit, NSUInteger recursionLimit)
 
static NSString * ExpandDigitKey (OOStringExpansionContext *context, const unichar *characters, NSUInteger keyStart, NSUInteger keyLength, NSUInteger sizeLimit, NSUInteger recursionLimit)
 
static NSString * ExpandStringKey (OOStringExpansionContext *context, NSString *key, NSUInteger sizeLimit, NSUInteger recursionLimit)
 
static NSString * ExpandStringKeyOverride (OOStringExpansionContext *context, NSString *key)
 
static NSString * ExpandStringKeySpecial (OOStringExpansionContext *context, NSString *key)
 
static NSString * ExpandStringKeyKeyboardBinding (OOStringExpansionContext *context, NSString *key)
 
static NSMapTable * SpecialSubstitutionSelectors (void)
 
static NSString * ExpandStringKeyFromDescriptions (OOStringExpansionContext *context, NSString *key, NSUInteger sizeLimit, NSUInteger recursionLimit)
 
static NSString * ExpandStringKeyMissionVariable (OOStringExpansionContext *context, NSString *key)
 
static NSString * ExpandStringKeyLegacyLocalVariable (OOStringExpansionContext *context, NSString *key)
 
static NSString * ExpandLegacyScriptSelectorKey (OOStringExpansionContext *context, NSString *key)
 
static SEL LookUpLegacySelector (NSString *key)
 
static NSString * ExpandPercentEscape (OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
 
static NSString * ExpandSystemNameForGalaxyEscape (OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
 
static NSString * ExpandSystemNameEscape (OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
 
static NSString * ExpandPercentR (OOStringExpansionContext *context, NSString *input)
 
static void ReportWarningForUnknownKey (OOStringExpansionContext *context, NSString *key)
 
static NSString * ApplyOperators (NSString *string, NSString *operatorsString)
 
static NSString * ApplyOneOperator (NSString *string, NSString *op, NSString *param)
 
static void SyntaxIssue (OOStringExpansionContext *context, const char *function, const char *fileName, NSUInteger line, NSString *logMessageClass, NSString *prefix, NSString *format,...) OO_TAKES_FORMAT_STRING(7
 
NSString * OOExpandDescriptionString (Random_Seed seed, NSString *string, NSDictionary *overrides, NSDictionary *legacyLocals, NSString *systemName, OOExpandOptions options)
 
NSString * OOGenerateSystemDescription (Random_Seed seed, NSString *name)
 
Random_Seed OOStringExpanderDefaultRandomSeed (void)
 
static NSString * Operator_cr (NSString *string, NSString *param)
 
static NSString * Operator_dcr (NSString *string, NSString *param)
 
static NSString * Operator_icr (NSString *string, NSString *param)
 
static NSString * Operator_idcr (NSString *string, NSString *param)
 
static NSString * Operator_precision (NSString *string, NSString *param)
 
static NSString * Operator_multiply (NSString *string, NSString *param)
 
static NSString * Operator_add (NSString *string, NSString *param)
 

Macro Definition Documentation

◆ kInvalidGEscapeMessage

#define kInvalidGEscapeMessage   @"String escape code %G must be followed by six integers."

◆ kInvalidJEscapeMessage

#define kInvalidJEscapeMessage   @"String escape code %J must be followed by three integers."

◆ OO_EXPANDER_RANDOM

#define OO_EXPANDER_RANDOM   (context->useGoodRNG ? (Ranrot()&0xFF) : gen_rnd_number())

◆ OPERATOR

#define OPERATOR ( name)    [NSValue valueWithPointer:Operator_##name], @#name

◆ SyntaxError

#define SyntaxError ( CONTEXT,
CLASS,
FORMAT,
... )   SyntaxIssue(CONTEXT, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, CLASS, OOLOG_WARNING_PREFIX, FORMAT, ## __VA_ARGS__)

◆ SyntaxWarning

#define SyntaxWarning ( CONTEXT,
CLASS,
FORMAT,
... )   SyntaxIssue(CONTEXT, OOLOG_FUNCTION_NAME, OOLOG_FILE_NAME, __LINE__, CLASS, OOLOG_WARNING_PREFIX, FORMAT, ## __VA_ARGS__)

◆ WARNINGS

#define WARNINGS   OOLITE_DEBUG

Definition at line 37 of file OOStringExpander.m.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
kStackAllocationLimit 
kRecursionLimit 

Definition at line 41 of file OOStringExpander.m.

42{
43 /*
44 Total stack limit for strings being parsed (in UTF-16 code elements,
45 i.e. units of 2 bytes), used recursively - for instance, if the root
46 string takes 10,000 characters, any string it recurses into gets
47 kStackAllocationLimit - 10,000. If the limit would be exceeded,
48 the unexpanded string is returned instead.
49
50 The limit is expected to be much higher than necessary for any practical
51 string, and exists only to catch pathological behaviour without crashing.
52 */
53 kStackAllocationLimit = UINT16_MAX,
54
55 /*
56 Recursion limit, for much the same purpose. Without it, we crash about
57 22,000 stack frames deep when trying to expand a = "[a]" on a Mac.
58 */
59 kRecursionLimit = 100
60};
@ kRecursionLimit
@ kStackAllocationLimit

Function Documentation

◆ AppendCharacters()

static void AppendCharacters ( NSMutableString ** result,
const unichar * characters,
NSUInteger start,
NSUInteger end )
static

Definition at line 1133 of file OOStringExpander.m.

1134{
1135 NSCParameterAssert(result != NULL && characters != NULL && start <= end);
1136
1137 if (*result == nil)
1138 {
1139 // Ensure there is a string. We want this even if the range is empty.
1140 *result = [NSMutableString string];
1141 }
1142
1143 if (start == end) return;
1144
1145 /* What we want here is a method like -[NSMutableString
1146 appendCharacters:(unichar)characters length:(NSUInteger)length], which
1147 unfortunately doesn't exist. On Mac OS X, CoreFoundation provides an
1148 equivalent. For GNUstep, we have to use a temporary string.
1149
1150 TODO: build the output string in a fixed-size stack buffer instead.
1151 */
1152#if OOLITE_MAC_OS_X
1153 CFStringAppendCharacters((CFMutableStringRef)*result, characters + start, end - start);
1154#else
1155 NSString *temp = [[NSString alloc] initWithCharacters:characters + start length:end - start];
1156 [*result appendString:temp];
1157 [temp release];
1158#endif
1159}
return nil

References nil.

Referenced by Expand().

+ Here is the caller graph for this function:

◆ ApplyOneOperator()

static NSString * ApplyOneOperator ( NSString * string,
NSString * op,
NSString * param )
static

Definition at line 516 of file OOStringExpander.m.

517{
518 static NSDictionary *operators = nil;
519
520 if (operators == nil)
521 {
522 #define OPERATOR(name) [NSValue valueWithPointer:Operator_##name], @#name
523 operators = [[NSDictionary alloc] initWithObjectsAndKeys:
524 OPERATOR(dcr),
525 OPERATOR(cr),
526 OPERATOR(icr),
527 OPERATOR(idcr),
528 OPERATOR(precision),
529 OPERATOR(multiply),
530 OPERATOR(add),
531 nil];
532 }
533
534 NSString *(*operator)(NSString *string, NSString *param) = [[operators objectForKey:op] pointerValue];
535 if (operator != NULL)
536 {
537 return operator(string, param);
538 }
539
540 OOLogERR(@"strings.expand.invalidOperator", @"Unknown string expansion operator %@", op);
541 return string;
542}
#define OOLogERR(class, format,...)
Definition OOLogging.h:112

References nil, and OOLogERR.

Referenced by ApplyOperators().

+ Here is the caller graph for this function:

◆ ApplyOperators()

static NSString * ApplyOperators ( NSString * string,
NSString * operatorsString )
static

Definition at line 444 of file OOStringExpander.m.

445{
446 NSArray *operators = [operatorsString componentsSeparatedByString:@"|"];
447 NSString *op = nil;
448
449 foreach(op, operators)
450 {
451 NSString *param = nil;
452 NSRange colon = [op rangeOfString:@":"];
453 if (colon.location != NSNotFound)
454 {
455 param = [op substringFromIndex:colon.location + colon.length];
456 op = [op substringToIndex:colon.location];
457 }
458 string = ApplyOneOperator(string, op, param);
459 }
460
461 return string;
462}
static NSString * ApplyOneOperator(NSString *string, NSString *op, NSString *param)

References ApplyOneOperator(), and nil.

Referenced by ExpandKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Expand()

static NSString * Expand ( OOStringExpansionContext * context,
NSString * string,
NSUInteger sizeLimit,
NSUInteger recursionLimit )
static

Definition at line 257 of file OOStringExpander.m.

258{
259 NSCParameterAssert(string != nil && context != NULL && sizeLimit <= kStackAllocationLimit);
260
261 const NSUInteger size = [string length];
262
263 // Avoid stack overflow.
264 if (EXPECT_NOT(size > sizeLimit || recursionLimit == 0)) return string;
265 sizeLimit -= size;
266 recursionLimit--;
267
268 // Nothing to expand in an empty string, and the size-1 thing below would be trouble.
269 if (size == 0) return string;
270
271 unichar characters[size];
272 [string getCharacters:characters range:(NSRange){ 0, size }];
273
274 /* Beginning of current range of non-special characters. If we encounter
275 a substitution, we'll be copying from here forward.
276 */
277 NSUInteger copyRangeStart = 0;
278
279 // Mutable string for result if we perform any substitutions.
280 NSMutableString *result = nil;
281
282 /* The iteration limit is size - 1 because every valid substitution is at
283 least 2 characters long. This way, characters[idx + 1] is always valid.
284 */
285 for (NSUInteger idx = 0; idx < size - 1; idx++)
286 {
287 /* Main parsing loop. If, at the end of the loop, replacement != nil,
288 we copy the characters from copyRangeStart to idx into the result,
289 the insert replacement, and skip replaceLength characters forward
290 (minus one, because idx is incremented by the loop.)
291 */
292 NSString *replacement = nil;
293 NSUInteger replaceLength = 0;
294 unichar thisChar = characters[idx];
295
296 if (thisChar == '[')
297 {
298 replacement = ExpandKey(context, characters, size, idx, &replaceLength, sizeLimit, recursionLimit);
299 }
300 else if (thisChar == '%')
301 {
302 replacement = ExpandPercentEscape(context, characters, size, idx, &replaceLength);
303 }
304 else if (thisChar == ']')
305 {
306 SyntaxWarning(context, @"strings.expand.warning.unbalancedClosingBracket", @"%@", @"Unbalanced ] in string.");
307 }
308 else if (thisChar == '\\' && context->convertBackslashN)
309 {
310 if (characters[idx + 1] == 'n')
311 {
312 replaceLength = 2;
313 replacement = @"\n";
314 }
315 }
316 else
317 {
318 // No token start character, so we definitely have no replacement.
319 continue;
320 }
321
322 if (replacement != nil)
323 {
324 /* If replacement string is "\x7F", eat the following character.
325 This is used in system_description for the one empty string
326 in [22].
327 */
328 if ([replacement isEqualToString:@"\x7F"] && replaceLength < size)
329 {
330 replaceLength++;
331 replacement = @"";
332 }
333
334 // Avoid copying if we're replacing the entire input string.
335 if (copyRangeStart == 0 && replaceLength == size)
336 {
337 return replacement;
338 }
339
340 // Write the pending literal segment to result. This also allocates result if needed.
341 AppendCharacters(&result, characters, copyRangeStart, idx);
342
343 [result appendString:replacement];
344
345 // Skip over replaced part and start a new literal segment.
346 idx += replaceLength - 1;
347 copyRangeStart = idx + 1;
348 }
349 }
350
351 if (result != nil)
352 {
353 // Append any trailing literal segment.
354 AppendCharacters(&result, characters, copyRangeStart, size);
355
356 // Don't turn result immutable; doing it once at top level is sufficient.
357 return result;
358 }
359 else
360 {
361 // No substitutions, return original string.
362 return string;
363 }
364}
#define EXPECT_NOT(x)
#define SyntaxWarning(CONTEXT, CLASS, FORMAT,...)
static NSString * ExpandPercentEscape(OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
static void AppendCharacters(NSMutableString **result, const unichar *characters, NSUInteger start, NSUInteger end)
static NSString * ExpandKey(OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength, NSUInteger sizeLimit, NSUInteger recursionLimit)
voidpf void uLong size
Definition ioapi.h:134

References AppendCharacters(), OOStringExpansionContext::convertBackslashN, ExpandKey(), ExpandPercentEscape(), EXPECT_NOT, kStackAllocationLimit, nil, and SyntaxWarning.

Referenced by ExpandDigitKey(), ExpandStringKeyFromDescriptions(), and OOExpandDescriptionString().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandDigitKey()

static NSString * ExpandDigitKey ( OOStringExpansionContext * context,
const unichar * characters,
NSUInteger keyStart,
NSUInteger keyLength,
NSUInteger sizeLimit,
NSUInteger recursionLimit )
static

Definition at line 555 of file OOStringExpander.m.

556{
557 NSCParameterAssert(context != NULL && characters != NULL);
558
559 NSUInteger keyValue = 0, idx;
560 for (idx = keyStart; idx < (keyStart + keyLength); idx++)
561 {
562 NSCAssert2(isdigit(characters[idx]), @"%s called with non-numeric key [%@].", __FUNCTION__, [NSString stringWithCharacters:characters + keyStart length:keyLength]);
563
564 keyValue = keyValue * 10 + characters[idx] - '0';
565 }
566
567 // Retrieve selected system_description entry.
568 NSArray *sysDescs = GetSystemDescriptions(context);
569 NSArray *entry = [sysDescs oo_arrayAtIndex:keyValue];
570
571 if (EXPECT_NOT(entry == nil))
572 {
573 if (keyValue >= context->sysDescCount)
574 {
575 SyntaxWarning(context, @"strings.expand.warning.outOfRangeKey", @"Out-of-range system description expansion key [%@] in string.", [NSString stringWithCharacters:characters + keyStart length:keyLength]);
576 }
577 else
578 {
579 // This is out of the scope of whatever triggered it, so shouldn't be a JS warning.
580 OOLogERR(@"strings.expand.invalidData", @"%@", @"descriptions.plist entry system_description must be an array of arrays of strings.");
581 }
582 return nil;
583 }
584
585 // Select a random sub-entry.
586 NSUInteger selection, count = [entry count];
587 NSUInteger rnd = OO_EXPANDER_RANDOM;
588 if (count == 5 && !context->useGoodRNG)
589 {
590 // Time-honoured Elite-compatible way for five items.
591 if (rnd >= 0xCC) selection = 4;
592 else if (rnd >= 0x99) selection = 3;
593 else if (rnd >= 0x66) selection = 2;
594 else if (rnd >= 0x33) selection = 1;
595 else selection = 0;
596 }
597 else
598 {
599 // General way.
600 selection = (rnd * count) / 256;
601 }
602
603 // Look up and recursively expand string.
604 NSString *string = [entry oo_stringAtIndex:selection];
605 return Expand(context, string, sizeLimit, recursionLimit);
606}
unsigned count
static NSArray * GetSystemDescriptions(OOStringExpansionContext *context)
#define OO_EXPANDER_RANDOM
static NSString * Expand(OOStringExpansionContext *context, NSString *string, NSUInteger sizeLimit, NSUInteger recursionLimit)

References count, Expand(), EXPECT_NOT, GetSystemDescriptions(), nil, OO_EXPANDER_RANDOM, OOLogERR, SyntaxWarning, OOStringExpansionContext::sysDescCount, and OOStringExpansionContext::useGoodRNG.

Referenced by ExpandKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandKey()

static NSString * ExpandKey ( OOStringExpansionContext * context,
const unichar * characters,
NSUInteger size,
NSUInteger idx,
NSUInteger * replaceLength,
NSUInteger sizeLimit,
NSUInteger recursionLimit )
static

Definition at line 379 of file OOStringExpander.m.

380{
381 NSCParameterAssert(context != NULL && characters != NULL && replaceLength != NULL);
382 NSCParameterAssert(characters[idx] == '[');
383
384 // Find the balancing close bracket.
385 NSUInteger end, balanceCount = 1, firstBar = 0;
386 bool allDigits = true;
387
388 for (end = idx + 1; end < size && balanceCount > 0; end++)
389 {
390 if (characters[end] == ']') balanceCount--;
391 else
392 {
393 if (characters[end] == '[') balanceCount++;
394 else if (characters[end] == '|' && firstBar == 0) firstBar = end;
395 if (!isdigit(characters[end]) && firstBar == 0) allDigits = false;
396 }
397 }
398
399 // Fail if no balancing bracket.
400 if (EXPECT_NOT(balanceCount != 0))
401 {
402 SyntaxWarning(context, @"strings.expand.warning.unbalancedOpeningBracket", @"%@", @"Unbalanced [ in string.");
403 return nil;
404 }
405
406 NSUInteger totalLength = end - idx;
407 *replaceLength = totalLength;
408 NSUInteger keyStart = idx + 1, keyLength = totalLength - 2;
409 if (firstBar != 0) keyLength = firstBar - idx - 1;
410
411 if (EXPECT_NOT(keyLength == 0))
412 {
413 SyntaxWarning(context, @"strings.expand.warning.emptyKey", @"%@", @"Invalid expansion code [] string. (To avoid this message, use %%[%%].)");
414 return nil;
415 }
416
417 NSString *expanded = nil;
418 if (allDigits)
419 {
420 expanded = ExpandDigitKey(context, characters, keyStart, keyLength, sizeLimit, recursionLimit);
421 }
422 else
423 {
424 NSString *key = [NSString stringWithCharacters:characters + keyStart length:keyLength];
425 expanded = ExpandStringKey(context, key, sizeLimit, recursionLimit);
426 }
427
428 if (firstBar != 0)
429 {
430 NSString *operators = [NSString stringWithCharacters:characters + firstBar + 1 length:end - firstBar - 2];
431 expanded = ApplyOperators(expanded, operators);
432 }
433
434 return expanded;
435}
static NSString * ExpandDigitKey(OOStringExpansionContext *context, const unichar *characters, NSUInteger keyStart, NSUInteger keyLength, NSUInteger sizeLimit, NSUInteger recursionLimit)
static NSString * ApplyOperators(NSString *string, NSString *operatorsString)
static NSString * ExpandStringKey(OOStringExpansionContext *context, NSString *key, NSUInteger sizeLimit, NSUInteger recursionLimit)

References ApplyOperators(), ExpandDigitKey(), ExpandStringKey(), EXPECT_NOT, nil, and SyntaxWarning.

Referenced by Expand().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandLegacyScriptSelectorKey()

static NSString * ExpandLegacyScriptSelectorKey ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 823 of file OOStringExpander.m.

824{
825 NSCParameterAssert(context != NULL && key != nil);
826
827 SEL selector = LookUpLegacySelector(key);
828
829 if (selector != NULL)
830 {
831 return [[PLAYER performSelector:selector] description];
832 }
833 else
834 {
835 return nil;
836 }
837}
static SEL LookUpLegacySelector(NSString *key)

References LookUpLegacySelector(), and nil.

Referenced by ExpandStringKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandPercentEscape()

static NSString * ExpandPercentEscape ( OOStringExpansionContext * context,
const unichar * characters,
NSUInteger size,
NSUInteger idx,
NSUInteger * replaceLength )
static

Definition at line 937 of file OOStringExpander.m.

938{
939 NSCParameterAssert(context != NULL && characters != NULL && replaceLength != NULL);
940 NSCParameterAssert(characters[idx] == '%');
941
942 // All %-escapes except %J and %G are 2 characters.
943 *replaceLength = 2;
944 unichar selector = characters[idx + 1];
945
946 switch (selector)
947 {
948 case 'H':
949 return GetSystemName(context);
950
951 case 'I':
952 return GetSystemNameIan(context);
953
954 case 'N':
955 return GetRandomNameN(context);
956
957 case 'R':
958 // to keep planet description generation consistent with earlier versions
959 // this must be done after all other substitutions in a second pass.
960 context->hasPercentR = true;
961 return @"%R";
962
963 case 'G':
964 return ExpandSystemNameForGalaxyEscape(context, characters, size, idx, replaceLength);
965
966 case 'J':
967 return ExpandSystemNameEscape(context, characters, size, idx, replaceLength);
968
969 case '%':
970 return @"%";
971
972 case '[':
973 return @"[";
974
975 case ']':
976 return @"]";
977
978 /* These are NSString formatting specifiers that occur in
979 descriptions.plist. The '.' is for floating-point (g and f)
980 specifiers that have field widths specified. No unadorned
981 %f or %g is found in vanilla Oolite descriptions.plist.
982
983 Ideally, these would be replaced with the caller formatting
984 the value and passing it as an override - it would be safer
985 and make descriptions.plist clearer - but it would be a big
986 job and uglify the callers without newfangled Objective-C
987 dictionary literals.
988 -- Ahruman 2012-10-05
989 */
990 case '@':
991 case 'd':
992 case '.':
993 return nil;
994
995 default:
996 // Yay, percent signs!
997 SyntaxWarning(context, @"strings.expand.warning.unknownPercentEscape", @"Unknown escape code in string: %%%lc. (To encode a %% sign without this warning, use %%%% - but prefer \"percent\" in prose writing.)", selector);
998
999 return nil;
1000 }
1001}
static NSString * GetSystemName(OOStringExpansionContext *context)
static NSString * ExpandSystemNameEscape(OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
static NSString * GetSystemNameIan(OOStringExpansionContext *context)
static NSString * ExpandSystemNameForGalaxyEscape(OOStringExpansionContext *context, const unichar *characters, NSUInteger size, NSUInteger idx, NSUInteger *replaceLength)
static NSString * GetRandomNameN(OOStringExpansionContext *context)

References ExpandSystemNameEscape(), ExpandSystemNameForGalaxyEscape(), GetRandomNameN(), GetSystemName(), GetSystemNameIan(), OOStringExpansionContext::hasPercentR, nil, and SyntaxWarning.

Referenced by Expand().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandPercentR()

static NSString * ExpandPercentR ( OOStringExpansionContext * context,
NSString * input )
static

Definition at line 1009 of file OOStringExpander.m.

1010{
1011 NSRange containsR = [input rangeOfString:@"%R"];
1012 if (containsR.location == NSNotFound)
1013 {
1014 return input; // no %Rs to replace
1015 }
1016 NSString *percentR = GetRandomNameR(context);
1017 NSMutableString *output = [NSMutableString stringWithString:input];
1018
1019 /* This loop should be completely unnecessary, but for some reason
1020 * replaceOccurrencesOfString sometimes only replaces the first
1021 * instance of %R if percentR contains the non-ASCII
1022 * digrams-apostrophe character. (I guess
1023 * http://lists.gnu.org/archive/html/gnustep-dev/2011-10/msg00048.html
1024 * this bug in GNUstep's implementation here, which is in 1.22) So
1025 * to cover that case, if there are still %R in the string after
1026 * replacement, try again. Affects things like thargoid curses, and
1027 * particularly %Rful expansions of [nom]. Probably this can be
1028 * tidied up once GNUstep 1.22 is ancient history, but that'll be a
1029 * few years yet. - CIM 15/1/2013 */
1030
1031 do {
1032 [output replaceOccurrencesOfString:@"%R" withString:percentR options:NSLiteralSearch range:NSMakeRange(0, [output length])];
1033 } while([output rangeOfString:@"%R"].location != NSNotFound);
1034
1035 return [NSString stringWithString:output];
1036}
static NSString * GetRandomNameR(OOStringExpansionContext *context)

References GetRandomNameR().

Referenced by OOExpandDescriptionString().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandStringKey()

static NSString * ExpandStringKey ( OOStringExpansionContext * context,
NSString * key,
NSUInteger sizeLimit,
NSUInteger recursionLimit )
static

Definition at line 614 of file OOStringExpander.m.

615{
616 NSCParameterAssert(context != NULL && key != nil);
617
618 // Overrides have top priority.
619 NSString *result = ExpandStringKeyOverride(context, key);
620
621 // Specials override descriptions.plist.
622 if (result == nil) result = ExpandStringKeySpecial(context, key);
623
624 // Now try descriptions.plist.
625 if (result == nil) result = ExpandStringKeyFromDescriptions(context, key, sizeLimit, recursionLimit);
626
627 // For efficiency, descriptions.plist overrides keybindings.
628 // OXPers should therefore avoid oolite_key_ description keys
629 if (result == nil) result = ExpandStringKeyKeyboardBinding(context, key);
630
631 // Try mission variables.
632 if (result == nil) result = ExpandStringKeyMissionVariable(context, key);
633
634 // Try legacy local variables.
635 if (result == nil) result = ExpandStringKeyLegacyLocalVariable(context, key);
636
637 // Try legacy script methods.
638 if (result == nil) ExpandLegacyScriptSelectorKey(context, key);
639
640#if WARNINGS
641 // None of that worked, so moan a bit.
642 if (result == nil) ReportWarningForUnknownKey(context, key);
643#endif
644
645 return result;
646}
static NSString * ExpandStringKeyLegacyLocalVariable(OOStringExpansionContext *context, NSString *key)
static NSString * ExpandStringKeyFromDescriptions(OOStringExpansionContext *context, NSString *key, NSUInteger sizeLimit, NSUInteger recursionLimit)
static NSString * ExpandLegacyScriptSelectorKey(OOStringExpansionContext *context, NSString *key)
static NSString * ExpandStringKeyMissionVariable(OOStringExpansionContext *context, NSString *key)
static NSString * ExpandStringKeyOverride(OOStringExpansionContext *context, NSString *key)
static void ReportWarningForUnknownKey(OOStringExpansionContext *context, NSString *key)
static NSString * ExpandStringKeyKeyboardBinding(OOStringExpansionContext *context, NSString *key)
static NSString * ExpandStringKeySpecial(OOStringExpansionContext *context, NSString *key)

References ExpandLegacyScriptSelectorKey(), ExpandStringKeyFromDescriptions(), ExpandStringKeyKeyboardBinding(), ExpandStringKeyLegacyLocalVariable(), ExpandStringKeyMissionVariable(), ExpandStringKeyOverride(), ExpandStringKeySpecial(), nil, and ReportWarningForUnknownKey().

Referenced by ExpandKey(), and OOExpandDescriptionString().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandStringKeyFromDescriptions()

static NSString * ExpandStringKeyFromDescriptions ( OOStringExpansionContext * context,
NSString * key,
NSUInteger sizeLimit,
NSUInteger recursionLimit )
static

Definition at line 764 of file OOStringExpander.m.

765{
766 id value = [[UNIVERSE descriptions] objectForKey:key];
767 if (value != nil)
768 {
769 if ([value isKindOfClass:[NSArray class]] && [value count] > 0)
770 {
771 NSUInteger rnd = OO_EXPANDER_RANDOM % [value count];
772 value = [value oo_objectAtIndex:rnd];
773 }
774
775 if (![value isKindOfClass:[NSString class]])
776 {
777 // This is out of the scope of whatever triggered it, so shouldn't be a JS warning.
778 OOLogERR(@"strings.expand.invalidData", @"String expansion value %@ for [%@] from descriptions.plist is not a string or number.", [value shortDescription], key);
779 return nil;
780 }
781
782 // Expand recursively.
783 return Expand(context, value, sizeLimit, recursionLimit);
784 }
785
786 return nil;
787}

References Expand(), nil, OO_EXPANDER_RANDOM, and OOLogERR.

Referenced by ExpandStringKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandStringKeyKeyboardBinding()

static NSString * ExpandStringKeyKeyboardBinding ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 710 of file OOStringExpander.m.

711{
712 NSCParameterAssert(context != NULL && key != nil);
713 if ([key hasPrefix:@"oolite_key_"])
714 {
715 NSString *binding = [key substringFromIndex:7];
716 return [PLAYER keyBindingDescription2:binding];
717 }
718 return nil;
719}

References nil.

Referenced by ExpandStringKey().

+ Here is the caller graph for this function:

◆ ExpandStringKeyLegacyLocalVariable()

static NSString * ExpandStringKeyLegacyLocalVariable ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 811 of file OOStringExpander.m.

812{
813 return [[context->legacyLocals objectForKey:key] description];
814}

Referenced by ExpandStringKey().

+ Here is the caller graph for this function:

◆ ExpandStringKeyMissionVariable()

static NSString * ExpandStringKeyMissionVariable ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 794 of file OOStringExpander.m.

795{
796 if ([key hasPrefix:@"mission_"])
797 {
798 return [PLAYER missionVariableForKey:key];
799 }
800
801 return nil;
802}

References nil.

Referenced by ExpandStringKey().

+ Here is the caller graph for this function:

◆ ExpandStringKeyOverride()

static NSString * ExpandStringKeyOverride ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 658 of file OOStringExpander.m.

659{
660 NSCParameterAssert(context != NULL && key != nil);
661
662 id value = [context->overrides objectForKey:key];
663 if (value != nil)
664 {
665#if WARNINGS
666 if (![value isKindOfClass:[NSString class]] && ![value isKindOfClass:[NSNumber class]])
667 {
668 SyntaxWarning(context, @"strings.expand.warning.invalidOverride", @"String expansion override value %@ for [%@] is not a string or number.", [value shortDescription], key);
669 }
670#endif
671 return [value description];
672 }
673
674 return nil;
675}

References nil, and SyntaxWarning.

Referenced by ExpandStringKey().

+ Here is the caller graph for this function:

◆ ExpandStringKeySpecial()

static NSString * ExpandStringKeySpecial ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 684 of file OOStringExpander.m.

685{
686 NSCParameterAssert(context != NULL && key != nil);
687
688 NSMapTable *specials = SpecialSubstitutionSelectors();
689 SEL selector = NSMapGet(specials, key);
690 if (selector != NULL)
691 {
692 NSCAssert2([PLAYER respondsToSelector:selector], @"Special string expansion selector %@ for [%@] is not implemented.", NSStringFromSelector(selector), key);
693
694 NSString *result = [PLAYER performSelector:selector];
695 if (result != nil)
696 {
697 NSCAssert2([result isKindOfClass:[NSString class]], @"Special string expansion [%@] expanded to %@, but expected a string.", key, [result shortDescription]);
698 return result;
699 }
700 }
701
702 return nil;
703}
static NSMapTable * SpecialSubstitutionSelectors(void)
#define PLAYER

References nil, PLAYER, and SpecialSubstitutionSelectors().

Referenced by ExpandStringKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ExpandSystemNameEscape()

static NSString * ExpandSystemNameEscape ( OOStringExpansionContext * context,
const unichar * characters,
NSUInteger size,
NSUInteger idx,
NSUInteger * replaceLength )
static

Definition at line 1096 of file OOStringExpander.m.

1097{
1098 NSCParameterAssert(context != NULL && characters != NULL && replaceLength != NULL);
1099 NSCParameterAssert(characters[idx + 1] == 'J');
1100
1101 // A valid %J escape is always five characters including the three digits.
1102 *replaceLength = 5;
1103
1104 #define kInvalidJEscapeMessage @"String escape code %J must be followed by three integers."
1105 if (EXPECT_NOT(size - idx < 5))
1106 {
1107 // Too close to end of string to actually have three characters, let alone three digits.
1108 SyntaxError(context, @"strings.expand.invalidJEscape", @"%@", kInvalidJEscapeMessage);
1109 return nil;
1110 }
1111
1112 char hundreds = characters[idx + 2];
1113 char tens = characters[idx + 3];
1114 char units = characters[idx + 4];
1115
1116 if (!(isdigit(hundreds) && isdigit(tens) && isdigit(units)))
1117 {
1118 SyntaxError(context, @"strings.expand.invalidJEscape", @"%@", kInvalidJEscapeMessage);
1119 return nil;
1120 }
1121
1122 OOSystemID sysID = (hundreds - '0') * 100 + (tens - '0') * 10 + (units - '0');
1123 if (sysID > kOOMaximumSystemID)
1124 {
1125 SyntaxError(context, @"strings.expand.invalidJEscape.range", @"String escape code %%J%3u is out of range (must be less than %u).", sysID, kOOMaximumSystemID + 1);
1126 return nil;
1127 }
1128
1129 return [UNIVERSE getSystemName:sysID];
1130}
#define SyntaxError(CONTEXT, CLASS, FORMAT,...)
#define kInvalidJEscapeMessage
int16_t OOSystemID
Definition OOTypes.h:211
@ kOOMaximumSystemID
Definition OOTypes.h:217

References EXPECT_NOT, kInvalidJEscapeMessage, kOOMaximumSystemID, nil, and SyntaxError.

Referenced by ExpandPercentEscape().

+ Here is the caller graph for this function:

◆ ExpandSystemNameForGalaxyEscape()

static NSString * ExpandSystemNameForGalaxyEscape ( OOStringExpansionContext * context,
const unichar * characters,
NSUInteger size,
NSUInteger idx,
NSUInteger * replaceLength )
static

Definition at line 1044 of file OOStringExpander.m.

1045{
1046 NSCParameterAssert(context != NULL && characters != NULL && replaceLength != NULL);
1047 NSCParameterAssert(characters[idx + 1] == 'G');
1048
1049 // A valid %G escape is always eight characters including the six digits.
1050 *replaceLength = 8;
1051
1052 #define kInvalidGEscapeMessage @"String escape code %G must be followed by six integers."
1053 if (EXPECT_NOT(size - idx < 8))
1054 {
1055 // Too close to end of string to actually have six characters, let alone six digits.
1056 SyntaxError(context, @"strings.expand.invalidJEscape", @"%@", kInvalidGEscapeMessage);
1057 return nil;
1058 }
1059
1060 char hundreds = characters[idx + 2];
1061 char tens = characters[idx + 3];
1062 char units = characters[idx + 4];
1063 char galHundreds = characters[idx + 5];
1064 char galTens = characters[idx + 6];
1065 char galUnits = characters[idx + 7];
1066
1067 if (!(isdigit(hundreds) && isdigit(tens) && isdigit(units) && isdigit(galHundreds) && isdigit(galTens) && isdigit(galUnits)))
1068 {
1069 SyntaxError(context, @"strings.expand.invalidJEscape", @"%@", kInvalidGEscapeMessage);
1070 return nil;
1071 }
1072
1073 OOSystemID sysID = (hundreds - '0') * 100 + (tens - '0') * 10 + (units - '0');
1074 if (sysID > kOOMaximumSystemID)
1075 {
1076 SyntaxError(context, @"strings.expand.invalidJEscape.range", @"String escape code %%G%3u for system is out of range (must be less than %u).", sysID, kOOMaximumSystemID + 1);
1077 return nil;
1078 }
1079
1080 OOGalaxyID galID = (galHundreds - '0') * 100 + (galTens - '0') * 10 + (galUnits - '0');
1081 if (galID > kOOMaximumGalaxyID)
1082 {
1083 SyntaxError(context, @"strings.expand.invalidJEscape.range", @"String escape code %%G%3u for galaxy is out of range (must be less than %u).", galID, kOOMaximumGalaxyID + 1);
1084 return nil;
1085 }
1086
1087 return [UNIVERSE getSystemName:sysID forGalaxy:galID];
1088}
#define kInvalidGEscapeMessage
uint8_t OOGalaxyID
Definition OOTypes.h:210
@ kOOMaximumGalaxyID
Definition OOTypes.h:216

References EXPECT_NOT, kInvalidGEscapeMessage, kOOMaximumGalaxyID, kOOMaximumSystemID, nil, and SyntaxError.

Referenced by ExpandPercentEscape().

+ Here is the caller graph for this function:

◆ GetRandomNameN()

static NSString * GetRandomNameN ( OOStringExpansionContext * context)
static

Definition at line 1186 of file OOStringExpander.m.

1187{
1188 NSCParameterAssert(context != NULL);
1189
1190 if (context->randomNameN == nil)
1191 {
1192 context->randomNameN = [NewRandomDigrams(context) retain];
1193 }
1194
1195 return context->randomNameN;
1196}

References nil, and OOStringExpansionContext::randomNameN.

Referenced by ExpandPercentEscape().

+ Here is the caller graph for this function:

◆ GetRandomNameR()

static NSString * GetRandomNameR ( OOStringExpansionContext * context)
static

Definition at line 1199 of file OOStringExpander.m.

1200{
1201 NSCParameterAssert(context != NULL);
1202
1203 if (context->randomNameR == nil)
1204 {
1205 context->randomNameR = [OldRandomDigrams() retain];
1206 }
1207
1208 return context->randomNameR;
1209}

References nil, and OOStringExpansionContext::randomNameR.

Referenced by ExpandPercentR().

+ Here is the caller graph for this function:

◆ GetSystemDescriptions()

static NSArray * GetSystemDescriptions ( OOStringExpansionContext * context)
static

Definition at line 1212 of file OOStringExpander.m.

1213{
1214 NSCParameterAssert(context != NULL);
1215
1216 if (context->systemDescriptions == nil)
1217 {
1218 context->systemDescriptions = [[[UNIVERSE descriptions] oo_arrayForKey:@"system_description"] retain];
1219 context->sysDescCount = [context->systemDescriptions count];
1220 }
1221
1222 return context->systemDescriptions;
1223}

References nil, OOStringExpansionContext::sysDescCount, and OOStringExpansionContext::systemDescriptions.

Referenced by ExpandDigitKey().

+ Here is the caller graph for this function:

◆ GetSystemName()

static NSString * GetSystemName ( OOStringExpansionContext * context)
static

Definition at line 1162 of file OOStringExpander.m.

1163{
1164 NSCParameterAssert(context != NULL);
1165 if (context->systemName == nil) {
1166 context->systemName = [[UNIVERSE getSystemName:[PLAYER systemID]] retain];
1167 }
1168
1169 return context->systemName;
1170}

References nil, and OOStringExpansionContext::systemName.

Referenced by ExpandPercentEscape().

+ Here is the caller graph for this function:

◆ GetSystemNameIan()

static NSString * GetSystemNameIan ( OOStringExpansionContext * context)
static

Definition at line 1173 of file OOStringExpander.m.

1174{
1175 NSCParameterAssert(context != NULL);
1176
1177 if (context->systemNameWithIan == nil)
1178 {
1179 context->systemNameWithIan = [OOExpandWithOptions(context->seed, kOOExpandDisallowPercentI | kOOExpandGoodRNG | kOOExpandKey, @"planetname-possessive") retain];
1180 }
1181
1182 return context->systemNameWithIan;
1183}

References nil, and OOStringExpansionContext::systemNameWithIan.

Referenced by ExpandPercentEscape().

+ Here is the caller graph for this function:

◆ LookUpLegacySelector()

static SEL LookUpLegacySelector ( NSString * key)
static

Definition at line 845 of file OOStringExpander.m.

846{
847 SEL selector = NULL;
848 static NSMapTable *selectorCache = NULL;
849
850 // Try cache lookup.
851 if (selectorCache != NULL)
852 {
853 selector = NSMapGet(selectorCache, key);
854 }
855
856 if (selector == NULL)
857 {
858 static NSDictionary *aliases = nil;
859 static NSSet *whitelist = nil;
860 if (whitelist == nil)
861 {
862 NSDictionary *whitelistDict = [ResourceManager whitelistDictionary];
863 whitelist = [[NSSet alloc] initWithArray:[whitelistDict oo_arrayForKey:@"query_methods"]];
864 aliases = [[whitelistDict oo_dictionaryForKey:@"query_method_aliases"] copy];
865 }
866
867 NSString *selectorName = [aliases oo_stringForKey:key];
868 if (selectorName == nil) selectorName = key;
869
870 if ([whitelist containsObject:selectorName])
871 {
872 selector = NSSelectorFromString(selectorName);
873
874 /* This is an assertion, not a warning, because whitelist.plist is
875 part of the game and cannot be overriden by OXPs. If there is an
876 invalid selector in the whitelist, it's a game bug.
877 */
878 NSCAssert1([PLAYER respondsToSelector:selector], @"Player does not respond to whitelisted query selector %@.", key);
879 }
880
881 if (selector != NULL)
882 {
883 // Add it to cache.
884 if (selectorCache == NULL)
885 {
886 selectorCache = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, [whitelist count]);
887 }
888 NSMapInsertKnownAbsent(selectorCache, key, selector);
889 }
890 }
891
892 return selector;
893}
NSDictionary * whitelistDictionary()

References count, nil, PLAYER, and ResourceManager::whitelistDictionary.

Referenced by ExpandLegacyScriptSelectorKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ NewRandomDigrams()

static NSString * NewRandomDigrams ( OOStringExpansionContext * context)
static

Definition at line 1250 of file OOStringExpander.m.

1251{
1252 unsigned length = (OO_EXPANDER_RANDOM % 4) + 1;
1253 if ((OO_EXPANDER_RANDOM % 5) < ((length == 1) ? 3 : 1)) ++length; // Make two-letter names rarer and 10-letter names happen sometimes
1254 NSString *digrams = [[UNIVERSE descriptions] objectForKey:@"digrams"];
1255 NSUInteger count = [digrams length] / 2;
1256 NSMutableString *name = [NSMutableString stringWithCapacity:length * 2];
1257
1258 for (unsigned i = 0; i != length; ++i)
1259 {
1260 [name appendString:[digrams substringWithRange:NSMakeRange((OO_EXPANDER_RANDOM % count) * 2, 2)]];
1261 }
1262
1263 return [name capitalizedString];
1264}

References count, and OO_EXPANDER_RANDOM.

◆ OldRandomDigrams()

static NSString * OldRandomDigrams ( void )
static

Definition at line 1230 of file OOStringExpander.m.

1231{
1232 /* The only point of using %R is for world generation, so there's
1233 * no point in checking the context */
1234 unsigned len = gen_rnd_number() & 3;
1235 NSString *digrams = [[UNIVERSE descriptions] objectForKey:@"digrams"];
1236 NSMutableString *name = [NSMutableString stringWithCapacity:256];
1237
1238 for (unsigned i = 0; i <=len; i++)
1239 {
1240 unsigned x = gen_rnd_number() & 0x3e;
1241 [name appendString:[digrams substringWithRange:NSMakeRange(x, 2)]];
1242 }
1243
1244 return [name capitalizedString];
1245}
float x
int gen_rnd_number(void)

References gen_rnd_number(), and x.

+ Here is the call graph for this function:

◆ OOExpandDescriptionString()

NSString * OOExpandDescriptionString ( Random_Seed seed,
NSString * string,
NSDictionary * overrides,
NSDictionary * legacyLocals,
NSString * systemName,
OOExpandOptions options )

Definition at line 160 of file OOStringExpander.m.

161{
162 if (string == nil) return nil;
163
165 {
166 .seed = seed,
167 .systemName = [systemName retain],
168 .overrides = [overrides retain],
169 .legacyLocals = [legacyLocals retain],
170 .isJavaScript = options & kOOExpandForJavaScript,
171 .convertBackslashN = options & kOOExpandBackslashN,
172 .useGoodRNG = options & kOOExpandGoodRNG
173 };
174
175 // Avoid recursive %I expansion by pre-seeding cache with literal %I.
176 if (options & kOOExpandDisallowPercentI) {
177 context.systemNameWithIan = @"%I";
178 }
179
180 OORandomState savedRandomState;
181 if (options & kOOExpandReseedRNG)
182 {
183 savedRandomState = OOSaveRandomState();
185 }
186
187 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
188 NSString *result = nil, *intermediate = nil;
189 @try
190 {
191 // TODO: profile caching the results. Would need to keep track of whether we've done something nondeterministic (array selection, %R etc).
192 if (options & kOOExpandKey)
193 {
194 intermediate = ExpandStringKey(&context, string, kStackAllocationLimit, kRecursionLimit);
195 }
196 else
197 {
198 intermediate = Expand(&context, string, kStackAllocationLimit, kRecursionLimit);
199 }
200 if (!context.hasPercentR)
201 {
202 result = intermediate;
203 }
204 else
205 {
206 result = ExpandPercentR(&context, intermediate);
207 }
208 }
209 @finally
210 {
211 [context.systemName release];
212 [context.overrides release];
213 [context.legacyLocals release];
214 [context.systemNameWithIan release];
215 [context.randomNameN release];
216 [context.randomNameR release];
217 [context.systemDescriptions release];
218 }
219
220 if (options & kOOExpandReseedRNG)
221 {
222 OORestoreRandomState(savedRandomState);
223 }
224
225 result = [result copy];
226 [pool release];
227 return [result autorelease];
228}
@ kOOExpandForJavaScript
Report warnings through JavaScript runtime system instead of normal logging.
@ kOOExpandDisallowPercentI
Disallow I expansion (used when expanding I itself).
@ kOOExpandKey
Treat string as a key. Expand("foo", kOOExpandKey) == Expand(@"[foo]", kOOExpandNoOptions).
@ kOOExpandBackslashN
Convert literal "\\n"s to line breaks (used for missiontext.plist for historical reasons).
@ kOOExpandGoodRNG
Use RANDROT for selecting from description arrays and for N expansion.
@ kOOExpandReseedRNG
Set "really random" seeds while expanding.
static NSString * ExpandPercentR(OOStringExpansionContext *context, NSString *input)
void OORestoreRandomState(OORandomState state)
OORandomState OOSaveRandomState(void)
void OOSetReallyRandomRANROTAndRndSeeds(void)

References Expand(), ExpandPercentR(), ExpandStringKey(), OOStringExpansionContext::hasPercentR, kOOExpandBackslashN, kOOExpandDisallowPercentI, kOOExpandForJavaScript, kOOExpandGoodRNG, kOOExpandKey, kOOExpandReseedRNG, kRecursionLimit, kStackAllocationLimit, nil, OORestoreRandomState(), OOSaveRandomState(), OOSetReallyRandomRANROTAndRndSeeds(), OOStringExpansionContext::seed, and OOStringExpansionContext::systemNameWithIan.

Referenced by GlobalExpandDescription(), GlobalExpandMissionText(), OOGenerateSystemDescription(), and PlayerEntity(Scripting)::PerformActionStatment.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ OOGenerateSystemDescription()

NSString * OOGenerateSystemDescription ( Random_Seed seed,
NSString * name )

Definition at line 231 of file OOStringExpander.m.

232{
234 return OOExpandDescriptionString(seed, @"system-description-string", nil, nil, name, kOOExpandKey);
235}
NSString * OOExpandDescriptionString(Random_Seed seed, NSString *string, NSDictionary *overrides, NSDictionary *legacyLocals, NSString *systemName, OOExpandOptions options)
void seed_RNG_only_for_planet_description(Random_Seed s_seed)

References kOOExpandKey, nil, OOExpandDescriptionString(), and seed_RNG_only_for_planet_description().

+ Here is the call graph for this function:

◆ OOStringExpanderDefaultRandomSeed()

Random_Seed OOStringExpanderDefaultRandomSeed ( void )

Definition at line 238 of file OOStringExpander.m.

239{
240 return [[UNIVERSE systemManager] getRandomSeedForCurrentSystem];
241}

Referenced by PlayerEntity(Scripting)::PerformActionStatment.

+ Here is the caller graph for this function:

◆ Operator_add()

static NSString * Operator_add ( NSString * string,
NSString * param )
static

Definition at line 501 of file OOStringExpander.m.

502{
503 return [NSString stringWithFormat:@"%g", [string doubleValue] + [param doubleValue]];
504}

◆ Operator_cr()

static NSString * Operator_cr ( NSString * string,
NSString * param )
static

Definition at line 465 of file OOStringExpander.m.

466{
467 return OOCredits([string doubleValue] * 10);
468}
OOINLINE NSString * OOCredits(OOCreditsQuantity tenthsOfCredits)

References OOCredits().

+ Here is the call graph for this function:

◆ Operator_dcr()

static NSString * Operator_dcr ( NSString * string,
NSString * param )
static

Definition at line 471 of file OOStringExpander.m.

472{
473 return OOCredits([string longLongValue]);
474}

References OOCredits().

+ Here is the call graph for this function:

◆ Operator_icr()

static NSString * Operator_icr ( NSString * string,
NSString * param )
static

Definition at line 477 of file OOStringExpander.m.

478{
479 return OOIntCredits([string longLongValue]);
480}
OOINLINE NSString * OOIntCredits(OOCreditsQuantity integerCredits)

References OOIntCredits().

+ Here is the call graph for this function:

◆ Operator_idcr()

static NSString * Operator_idcr ( NSString * string,
NSString * param )
static

Definition at line 483 of file OOStringExpander.m.

484{
485 return OOIntCredits(round([string doubleValue] / 10.0));
486}

References OOIntCredits().

+ Here is the call graph for this function:

◆ Operator_multiply()

static NSString * Operator_multiply ( NSString * string,
NSString * param )
static

Definition at line 495 of file OOStringExpander.m.

496{
497 return [NSString stringWithFormat:@"%g", [string doubleValue] * [param doubleValue]];
498}

◆ Operator_precision()

static NSString * Operator_precision ( NSString * string,
NSString * param )
static

Definition at line 489 of file OOStringExpander.m.

490{
491 return [NSString stringWithFormat:@"%.*f", [param intValue], [string doubleValue]];
492}

◆ ReportWarningForUnknownKey()

static void ReportWarningForUnknownKey ( OOStringExpansionContext * context,
NSString * key )
static

Definition at line 903 of file OOStringExpander.m.

904{
905 if ([key hasSuffix:@"_string"] || [key hasSuffix:@"_number"] || [key hasSuffix:@"_bool"])
906 {
907 SyntaxError(context, @"strings.expand.invalidSelector", @"Unpermitted legacy script method [%@] in string.", key);
908 }
909 else
910 {
911 SyntaxWarning(context, @"strings.expand.warning.unknownExpansion", @"Unknown expansion key [%@] in string.", key);
912 }
913}

References SyntaxError, and SyntaxWarning.

Referenced by ExpandStringKey().

+ Here is the caller graph for this function:

◆ SpecialSubstitutionSelectors()

static NSMapTable * SpecialSubstitutionSelectors ( void )
static

Definition at line 727 of file OOStringExpander.m.

728{
729 static NSMapTable *specials = NULL;
730 if (specials != NULL) return specials;
731
732 struct { NSString *key; SEL selector; } selectors[] =
733 {
734 { @"commander_name", @selector(commanderName_string) },
735 { @"commander_shipname", @selector(commanderShip_string) },
736 { @"commander_shipdisplayname", @selector(commanderShipDisplayName_string) },
737 { @"commander_rank", @selector(commanderRank_string) },
738 { @"commander_kills", @selector(commanderKillsAsString) },
739 { @"commander_legal_status", @selector(commanderLegalStatus_string) },
740 { @"commander_bounty", @selector(commanderBountyAsString) },
741 { @"credits_number", @selector(creditsFormattedForSubstitution) },
742 { @"_oo_legacy_credits_number", @selector(creditsFormattedForLegacySubstitution) }
743 };
744 unsigned i, count = sizeof selectors / sizeof *selectors;
745
746 specials = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, count);
747 for (i = 0; i < count; i++)
748 {
749 NSMapInsertKnownAbsent(specials, selectors[i].key, selectors[i].selector);
750 }
751
752 return specials;
753}

References count.

Referenced by ExpandStringKeySpecial().

+ Here is the caller graph for this function:

◆ SyntaxIssue()

static void SyntaxIssue ( OOStringExpansionContext * context,
const char * function,
const char * fileName,
NSUInteger line,
NSString * logMessageClass,
NSString * prefix,
NSString * format,
... )
static

Definition at line 1267 of file OOStringExpander.m.

1268{
1269 NSCParameterAssert(context != NULL);
1270
1271 va_list args;
1272 va_start(args, format);
1273
1274 if (OOLogWillDisplayMessagesInClass(logMessageClass))
1275 {
1276 if (context->isJavaScript)
1277 {
1278 /* NOTE: syntax errors are reported as warnings when called from JS
1279 because we don't want to start throwing exceptions when the old
1280 expander didn't.
1281 */
1282 JSContext *jsc = OOJSAcquireContext();
1283 OOJSReportWarningWithArguments(jsc, format, args);
1285 }
1286 else
1287 {
1288 format = [prefix stringByAppendingString:format];
1289 OOLogWithFunctionFileAndLineAndArguments(logMessageClass, function, fileName, line, format, args);
1290 }
1291 }
1292
1293 va_end(args);
1294}
void OOJSReportWarningWithArguments(JSContext *context, NSString *format, va_list args)
OOINLINE JSContext * OOJSAcquireContext(void)
OOINLINE void OOJSRelinquishContext(JSContext *context)
void void void OOLogWithFunctionFileAndLineAndArguments(NSString *inMessageClass, const char *inFunction, const char *inFile, unsigned long inLine, NSString *inFormat, va_list inArguments) OO_TAKES_FORMAT_STRING(5
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
Definition OOLogging.m:144

References OOStringExpansionContext::isJavaScript, OOJSAcquireContext(), OOJSRelinquishContext(), OOJSReportWarningWithArguments(), OOLogWillDisplayMessagesInClass(), and OOLogWithFunctionFileAndLineAndArguments().

+ Here is the call graph for this function: