Line data Source code
1 0 : /*
2 :
3 : OOStringExpander.h
4 :
5 : Functions for expanding escape codes and key references in strings.
6 :
7 :
8 : Oolite
9 : Copyright (C) 2004-2013 Giles C Williams and contributors
10 :
11 : This program is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU General Public License
13 : as published by the Free Software Foundation; either version 2
14 : of the License, or (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the impllied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program; if not, write to the Free Software
23 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 : MA 02110-1301, USA.
25 :
26 : */
27 :
28 :
29 : #import "OOCocoa.h"
30 : #import "OOMaths.h"
31 :
32 :
33 : // Option flags for OOExpandDescriptionString().
34 0 : enum
35 : {
36 : kOOExpandForJavaScript = 0x00000001, ///< Report warnings through JavaScript runtime system instead of normal logging.
37 : kOOExpandBackslashN = 0x00000002, ///< Convert literal "\\n"s to line breaks (used for missiontext.plist for historical reasons).
38 : kOOExpandGoodRNG = 0x00000004, ///< Use RANDROT for selecting from description arrays and for %N expansion.
39 : kOOExpandReseedRNG = 0x00000008, ///< Set "really random" seeds while expanding.
40 : kOOExpandKey = 0x00000010, ///< Treat string as a key. Expand(@"foo", kOOExpandKey) == Expand(@"[foo]", kOOExpandNoOptions).
41 : kOOExpandDisallowPercentI = 0x00000020, ///< Disallow %I expansion (used when expanding %I itself).
42 :
43 : kOOExpandNoOptions = 0
44 : };
45 0 : typedef NSUInteger OOExpandOptions;
46 :
47 :
48 : /*
49 : OOExpandDescriptionString(string, seed, overrides, locals, systemName, recurse, options)
50 :
51 : Apply the following transformations to a string:
52 : * [commander_name] is replaced with the player character's name.
53 : * [commander_shipname] is replaced with the player ship's name.
54 : * [commander_shipdisplayname] is replaced with the player ship's display
55 : name.
56 : * [commander_rank] is replaced with the descriptive name of the player's
57 : kill rank.
58 : * [commander_legal_status] is replaced with the descriptive name for the
59 : player's bounty ("Clean" etc)
60 : * [commander_bounty] is replaced with the player's numerical bounty.
61 : * [credits_number] is replaced with the player's formatted credit balance.
62 : * [_oo_legacy_credits_number] is replaced with the player's credit balance
63 : in simple #.0 format (this is substituted for [credits_number] by the
64 : legacy script engine).
65 : * [N], where N is an integer, is looked up in system_description in
66 : descriptions.plist. This is an array of arrays of five strings each.
67 : Each [N] lookup selects entry N of the outer array, then selects a
68 : string from the Nth inner array at pseudo-random. The result is then
69 : expanded recursively.
70 : * [key], where key is any string not specified above, is handled as
71 : follows:
72 : - If it is found in <overrides>, use the corresponding value.
73 : - Otherwise, look it up in descriptions.plist. If a string or number
74 : is found, use that; if an array is found, select an item from it
75 : at random.
76 : - Otherwise, if it is a mission variable name (prefixed with
77 : mission_), use the value of the mission variable.
78 : - Otherwise, if it is found in <legacyLocals>, use the corresponding
79 : value.
80 : - Otherwise, if it is a whitelisted legacy script property, look it
81 : up and insert the value.
82 : The resulting string is then recursively expanded.
83 : * %H is replaced with <planetName>. If systemName is nil, a planet name
84 : is retrieved through -[Universe getSystemName:], treating <seed> as a
85 : system seed.
86 : * %I is equivalent to "%H[planetname-derivative-suffix]".
87 : * %N is replaced with a random "alien" name using the planet name
88 : digraphs. If used more than once in the same string, it will produce
89 : the same name on each occurence.
90 : * %R is like %N but, due to a bug, misses some possibilities. Deprecated.
91 : * %JNNN, where NNN is a three-digit integer, is replaced with the name
92 : of system ID NNN in the current galaxy.
93 : * %GNNNNNN, where NNNNNN is a six-digit integer, is replaced with the
94 : name of system ID NNN (first triplet) in the specified galaxy
95 : (second triplet).
96 : * %% is replaced with %.
97 : * %[ is replaced with [.
98 : * %] is replaced with ].
99 :
100 : Syntax errors and, in non-Deployment builds, warnings may be generated. If
101 : <options & kOOExpandForJavaScript>, warnings are sent through
102 : OOJSReportWarning, otherwise they are logged.
103 :
104 : If <options & kOOExpandBackslashN>, literal \n in strings (i.e., "\\n") are
105 : converted to line breaks. This is used for expanding missiontext.plist
106 : entries, which may have literal \n especially in XML format.
107 : */
108 0 : NSString *OOExpandDescriptionString(Random_Seed seed, NSString *string, NSDictionary *overrides, NSDictionary *legacyLocals, NSString *systemName, OOExpandOptions options);
109 :
110 :
111 : /*
112 : OOGenerateSystemDescription(seed, name)
113 :
114 : Generates the default system description for the specified system seed.
115 : Equivalent to OOExpand(@"[system-description-string]"), except that it
116 : uses a special PRNG setting to tie the description to the seed.
117 :
118 : NOTE: this does not apply planetinfo overrides. To get the actual system
119 : description, use [UNIVERSE generateSystemData:].
120 : */
121 0 : NSString *OOGenerateSystemDescription(Random_Seed seed, NSString *name);
122 :
123 :
124 : /**
125 : Expand a string with default options.
126 : */
127 1 : #define OOExpand(string, ...) OOExpandWithSeed(OOStringExpanderDefaultRandomSeed(), string, __VA_ARGS__)
128 :
129 : /**
130 : Expand a string as though it were surrounded by brackets;
131 : OOExpandKey(@"foo", ...) is equivalent to OOExpand(@"[foo]", ...).
132 : */
133 1 : #define OOExpandKey(key, ...) OOExpandKeyWithSeed(OOStringExpanderDefaultRandomSeed(), key, __VA_ARGS__)
134 :
135 : /**
136 : Like OOExpandKey(), but uses a random-er random seed to avoid repeatability.
137 : */
138 1 : #define OOExpandKeyRandomized(key, ...) OOExpandWithOptions(OOStringExpanderDefaultRandomSeed(), kOOExpandKey | kOOExpandGoodRNG | kOOExpandReseedRNG, key, __VA_ARGS__)
139 :
140 0 : #define OOExpandWithSeed(seed, string, ...) OOExpandWithOptions(seed, kOOExpandNoOptions, string, __VA_ARGS__)
141 :
142 0 : #define OOExpandKeyWithSeed(seed, key, ...) OOExpandWithOptions(seed, kOOExpandKey, key, __VA_ARGS__)
143 :
144 :
145 0 : #define OOExpandWithOptions(seed, options, string, ...) \
146 : OOExpandDescriptionString(seed, string, OOEXPAND_ARG_DICTIONARY(__VA_ARGS__), nil, nil, options)
147 :
148 :
149 : // Equivalent to [[UNIVERSE systemManager] getRandomSeedForCurrentSystem], without pulling in Universe.h.
150 0 : Random_Seed OOStringExpanderDefaultRandomSeed(void);
151 :
152 :
153 : // MARK: Danger zone! Everything beyond this point is scary.
154 :
155 : /* Given an argument list, return a dictionary whose keys are the literal
156 : arguments and whose values are objects representing the arguments' values
157 : (as per OO_CAST_PARAMETER() below).
158 :
159 : Note that the argument list will be preprocessor-expanded at this point.
160 : */
161 0 : #define OOEXPAND_ARG_DICTIONARY(...) ( \
162 : (OOEXPAND_ARGUMENT_COUNT(__VA_ARGS__) == 0) ? \
163 : nil : \
164 : [NSDictionary dictionaryWithObjects:OOEXPAND_OBJECTS_FROM_ARGS(__VA_ARGS__) \
165 : forKeys:OOEXPAND_NAMES_FROM_ARGS(__VA_ARGS__) \
166 : count:OOEXPAND_ARGUMENT_COUNT(__VA_ARGS__)] )
167 :
168 0 : #define OOEXPAND_NAME_FROM_ARG(ITEM) @#ITEM
169 0 : #define OOEXPAND_NAMES_FROM_ARGS(...) (NSString *[]){ OOEXPAND_MAP(OOEXPAND_NAME_FROM_ARG, __VA_ARGS__) }
170 :
171 0 : #define OOEXPAND_OBJECTS_FROM_ARGS(...) (id[]){ OOEXPAND_MAP(OO_CAST_PARAMETER, __VA_ARGS__) }
172 :
173 : /* Limited boxing mechanism. ITEM may be an NSString *, NSNumber *, any
174 : integer type or any floating point type; the result is an NSNumber *,
175 : except if the parameter is an NSString * in which case it is returned
176 : unmodified.
177 : */
178 0 : #define OO_CAST_PARAMETER(ITEM) \
179 : __builtin_choose_expr( \
180 : OOEXPAND_IS_OBJECT(ITEM), \
181 : OOCastParamObject, \
182 : __builtin_choose_expr( \
183 : OOEXPAND_IS_SIGNED_INTEGER(ITEM), \
184 : OOCastParamSignedInteger, \
185 : __builtin_choose_expr( \
186 : OOEXPAND_IS_UNSIGNED_INTEGER(ITEM), \
187 : OOCastParamUnsignedInteger, \
188 : __builtin_choose_expr( \
189 : OOEXPAND_IS_FLOAT(ITEM), \
190 : OOCastParamFloat, \
191 : __builtin_choose_expr( \
192 : OOEXPAND_IS_UNSIGNED_INTEGER(ITEM), \
193 : OOCastParamUnsignedInteger, \
194 : __builtin_choose_expr( \
195 : OOEXPAND_IS_DOUBLE(ITEM), \
196 : OOCastParamDouble, \
197 : (void)0 \
198 : ) \
199 : ) \
200 : ) \
201 : ) \
202 : ) \
203 : )(ITEM)
204 :
205 : // Test whether ITEM is a known object type.
206 : // NOTE: id works here in clang, but not gcc.
207 0 : #define OOEXPAND_IS_OBJECT(ITEM) ( \
208 : __builtin_types_compatible_p(typeof(ITEM), NSString *) || \
209 : __builtin_types_compatible_p(typeof(ITEM), NSNumber *))
210 :
211 : // Test whether ITEM is a signed integer type.
212 : // Some redundancy to avoid silliness across platforms; probably not necessary.
213 0 : #define OOEXPAND_IS_SIGNED_INTEGER(ITEM) ( \
214 : __builtin_types_compatible_p(typeof(ITEM), char) || \
215 : __builtin_types_compatible_p(typeof(ITEM), short) || \
216 : __builtin_types_compatible_p(typeof(ITEM), int) || \
217 : __builtin_types_compatible_p(typeof(ITEM), long) || \
218 : __builtin_types_compatible_p(typeof(ITEM), long long) || \
219 : __builtin_types_compatible_p(typeof(ITEM), NSInteger) || \
220 : __builtin_types_compatible_p(typeof(ITEM), intptr_t) || \
221 : __builtin_types_compatible_p(typeof(ITEM), ssize_t) || \
222 : __builtin_types_compatible_p(typeof(ITEM), off_t))
223 :
224 : // Test whether ITEM is an unsigned integer type.
225 : // Some redundancy to avoid silliness across platforms; probably not necessary.
226 0 : #define OOEXPAND_IS_UNSIGNED_INTEGER(ITEM) ( \
227 : __builtin_types_compatible_p(typeof(ITEM), unsigned char) || \
228 : __builtin_types_compatible_p(typeof(ITEM), unsigned short) || \
229 : __builtin_types_compatible_p(typeof(ITEM), unsigned int) || \
230 : __builtin_types_compatible_p(typeof(ITEM), unsigned long) || \
231 : __builtin_types_compatible_p(typeof(ITEM), unsigned long long) || \
232 : __builtin_types_compatible_p(typeof(ITEM), NSUInteger) || \
233 : __builtin_types_compatible_p(typeof(ITEM), uintptr_t) || \
234 : __builtin_types_compatible_p(typeof(ITEM), size_t))
235 :
236 : // Test whether ITEM is a float.
237 : // This is distinguished from double to expose optimization opportunities.
238 0 : #define OOEXPAND_IS_FLOAT(ITEM) ( \
239 : __builtin_types_compatible_p(typeof(ITEM), float))
240 :
241 : // Test whether ITEM is any other floating-point type.
242 0 : #define OOEXPAND_IS_DOUBLE(ITEM) ( \
243 : __builtin_types_compatible_p(typeof(ITEM), double) || \
244 : __builtin_types_compatible_p(typeof(ITEM), long double))
245 :
246 : // OO_CAST_PARAMETER() boils down to one of these.
247 0 : static inline id OOCastParamObject(id object) { return object; }
248 0 : static inline id OOCastParamSignedInteger(long long value) { return [NSNumber numberWithLongLong:value]; }
249 0 : static inline id OOCastParamUnsignedInteger(unsigned long long value) { return [NSNumber numberWithUnsignedLongLong:value]; }
250 0 : static inline id OOCastParamFloat(float value) { return [NSNumber numberWithFloat:value]; }
251 0 : static inline id OOCastParamDouble(double value) { return [NSNumber numberWithDouble:value]; }
252 :
253 :
254 : /*
255 : Evil macro magic.
256 :
257 : OOEXPAND_ARGUMENT_COUNT returns the number of elements in a __VA_ARGS__
258 : list. Trivially modified from code by Laurent Deniau and
259 : "arpad.goret...@gmail.com" (full name not available). Source:
260 : https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/d-6Mj5Lko_s
261 :
262 : This version relies on the GCC/Clang ##__VA_ARGS__ extension to handle
263 : zero-length lists. It supports up to 62 arguments.
264 :
265 : OOEXPAND_MAP applies a unary macro or function to each element of a
266 : parameter or initializer list. For example, "OOEXPAND_MAP(foo, 1, 2, 3)"
267 : is equivalent to "foo(1), foo(2), foo(3)".
268 : */
269 :
270 0 : #define OOEXPAND_ARGUMENT_COUNT(...) \
271 : OOEXPAND_ARGUMENT_COUNT_INNER(_0, ##__VA_ARGS__, OOEXPAND_ARGUMENT_COUNT_63_VALUES())
272 0 : #define OOEXPAND_ARGUMENT_COUNT_INNER(...) \
273 : OOEXPAND_ARGUMENT_COUNT_EXTRACT_64TH_ARG(__VA_ARGS__)
274 : #define OOEXPAND_ARGUMENT_COUNT_EXTRACT_64TH_ARG( \
275 : _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
276 : _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
277 : _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
278 : _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
279 : _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
280 : _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
281 0 : _61,_62,_63,N,...) N
282 0 : #define OOEXPAND_ARGUMENT_COUNT_63_VALUES() \
283 : 62,61,60, \
284 : 59,58,57,56,55,54,53,52,51,50, \
285 : 49,48,47,46,45,44,43,42,41,40, \
286 : 39,38,37,36,35,34,33,32,31,30, \
287 : 29,28,27,26,25,24,23,22,21,20, \
288 : 19,18,17,16,15,14,13,12,11,10, \
289 : 9,8,7,6,5,4,3,2,1,0
290 :
291 :
292 0 : #define OOEXPAND_MAP(F, ...) \
293 : OOEXPAND_MAP_INNER(F, OOEXPAND_ARGUMENT_COUNT(__VA_ARGS__), __VA_ARGS__)
294 0 : #define OOEXPAND_MAP_INNER(F, COUNTEXPR, ...) \
295 : OOEXPAND_MAP_INNER2(F, COUNTEXPR, __VA_ARGS__)
296 0 : #define OOEXPAND_MAP_INNER2(F, COUNT, ...) \
297 : OOEXPAND_MAP_INNER3(F, OOEXPAND_MAP_IMPL_ ## COUNT, __VA_ARGS__)
298 0 : #define OOEXPAND_MAP_INNER3(F, IMPL, ...) \
299 : IMPL(F, __VA_ARGS__)
300 :
301 0 : #define OOEXPAND_MAP_IMPL_0(F, HEAD)
302 0 : #define OOEXPAND_MAP_IMPL_1(F, HEAD) F(HEAD)
303 0 : #define OOEXPAND_MAP_IMPL_2(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_1(F, __VA_ARGS__)
304 0 : #define OOEXPAND_MAP_IMPL_3(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_2(F, __VA_ARGS__)
305 0 : #define OOEXPAND_MAP_IMPL_4(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_3(F, __VA_ARGS__)
306 0 : #define OOEXPAND_MAP_IMPL_5(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_4(F, __VA_ARGS__)
307 0 : #define OOEXPAND_MAP_IMPL_6(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_5(F, __VA_ARGS__)
308 0 : #define OOEXPAND_MAP_IMPL_7(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_6(F, __VA_ARGS__)
309 0 : #define OOEXPAND_MAP_IMPL_8(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_7(F, __VA_ARGS__)
310 0 : #define OOEXPAND_MAP_IMPL_9(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_8(F, __VA_ARGS__)
311 0 : #define OOEXPAND_MAP_IMPL_10(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_9(F, __VA_ARGS__)
312 0 : #define OOEXPAND_MAP_IMPL_11(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_10(F, __VA_ARGS__)
313 0 : #define OOEXPAND_MAP_IMPL_12(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_11(F, __VA_ARGS__)
314 0 : #define OOEXPAND_MAP_IMPL_13(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_12(F, __VA_ARGS__)
315 0 : #define OOEXPAND_MAP_IMPL_14(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_13(F, __VA_ARGS__)
316 0 : #define OOEXPAND_MAP_IMPL_15(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_14(F, __VA_ARGS__)
317 0 : #define OOEXPAND_MAP_IMPL_16(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_15(F, __VA_ARGS__)
318 0 : #define OOEXPAND_MAP_IMPL_17(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_16(F, __VA_ARGS__)
319 0 : #define OOEXPAND_MAP_IMPL_18(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_17(F, __VA_ARGS__)
320 0 : #define OOEXPAND_MAP_IMPL_19(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_18(F, __VA_ARGS__)
321 0 : #define OOEXPAND_MAP_IMPL_20(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_19(F, __VA_ARGS__)
322 0 : #define OOEXPAND_MAP_IMPL_21(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_20(F, __VA_ARGS__)
323 0 : #define OOEXPAND_MAP_IMPL_22(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_21(F, __VA_ARGS__)
324 0 : #define OOEXPAND_MAP_IMPL_23(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_22(F, __VA_ARGS__)
325 0 : #define OOEXPAND_MAP_IMPL_24(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_23(F, __VA_ARGS__)
326 0 : #define OOEXPAND_MAP_IMPL_25(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_24(F, __VA_ARGS__)
327 0 : #define OOEXPAND_MAP_IMPL_26(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_25(F, __VA_ARGS__)
328 0 : #define OOEXPAND_MAP_IMPL_27(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_26(F, __VA_ARGS__)
329 0 : #define OOEXPAND_MAP_IMPL_28(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_27(F, __VA_ARGS__)
330 0 : #define OOEXPAND_MAP_IMPL_29(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_28(F, __VA_ARGS__)
331 0 : #define OOEXPAND_MAP_IMPL_30(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_29(F, __VA_ARGS__)
332 0 : #define OOEXPAND_MAP_IMPL_31(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_30(F, __VA_ARGS__)
333 0 : #define OOEXPAND_MAP_IMPL_32(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_31(F, __VA_ARGS__)
334 0 : #define OOEXPAND_MAP_IMPL_33(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_32(F, __VA_ARGS__)
335 0 : #define OOEXPAND_MAP_IMPL_34(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_33(F, __VA_ARGS__)
336 0 : #define OOEXPAND_MAP_IMPL_35(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_34(F, __VA_ARGS__)
337 0 : #define OOEXPAND_MAP_IMPL_36(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_35(F, __VA_ARGS__)
338 0 : #define OOEXPAND_MAP_IMPL_37(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_36(F, __VA_ARGS__)
339 0 : #define OOEXPAND_MAP_IMPL_38(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_37(F, __VA_ARGS__)
340 0 : #define OOEXPAND_MAP_IMPL_39(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_38(F, __VA_ARGS__)
341 0 : #define OOEXPAND_MAP_IMPL_40(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_39(F, __VA_ARGS__)
342 0 : #define OOEXPAND_MAP_IMPL_41(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_40(F, __VA_ARGS__)
343 0 : #define OOEXPAND_MAP_IMPL_42(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_41(F, __VA_ARGS__)
344 0 : #define OOEXPAND_MAP_IMPL_43(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_42(F, __VA_ARGS__)
345 0 : #define OOEXPAND_MAP_IMPL_44(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_43(F, __VA_ARGS__)
346 0 : #define OOEXPAND_MAP_IMPL_45(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_44(F, __VA_ARGS__)
347 0 : #define OOEXPAND_MAP_IMPL_46(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_45(F, __VA_ARGS__)
348 0 : #define OOEXPAND_MAP_IMPL_47(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_46(F, __VA_ARGS__)
349 0 : #define OOEXPAND_MAP_IMPL_48(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_47(F, __VA_ARGS__)
350 0 : #define OOEXPAND_MAP_IMPL_49(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_48(F, __VA_ARGS__)
351 0 : #define OOEXPAND_MAP_IMPL_50(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_49(F, __VA_ARGS__)
352 0 : #define OOEXPAND_MAP_IMPL_51(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_50(F, __VA_ARGS__)
353 0 : #define OOEXPAND_MAP_IMPL_52(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_51(F, __VA_ARGS__)
354 0 : #define OOEXPAND_MAP_IMPL_53(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_52(F, __VA_ARGS__)
355 0 : #define OOEXPAND_MAP_IMPL_54(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_53(F, __VA_ARGS__)
356 0 : #define OOEXPAND_MAP_IMPL_55(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_54(F, __VA_ARGS__)
357 0 : #define OOEXPAND_MAP_IMPL_56(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_55(F, __VA_ARGS__)
358 0 : #define OOEXPAND_MAP_IMPL_57(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_56(F, __VA_ARGS__)
359 0 : #define OOEXPAND_MAP_IMPL_58(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_57(F, __VA_ARGS__)
360 0 : #define OOEXPAND_MAP_IMPL_59(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_58(F, __VA_ARGS__)
361 0 : #define OOEXPAND_MAP_IMPL_60(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_59(F, __VA_ARGS__)
362 0 : #define OOEXPAND_MAP_IMPL_61(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_60(F, __VA_ARGS__)
363 0 : #define OOEXPAND_MAP_IMPL_62(F, HEAD, ...) F(HEAD), OOEXPAND_MAP_IMPL_61(F, __VA_ARGS__)
|