diff options
author | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
commit | 6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch) | |
tree | 34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/build-scripts | |
parent | 8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff) |
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/build-scripts')
50 files changed, 16114 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/build-scripts/SDL_migration.cocci b/src/contrib/SDL-3.2.20/build-scripts/SDL_migration.cocci new file mode 100644 index 0000000..38655af --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/SDL_migration.cocci | |||
@@ -0,0 +1,3836 @@ | |||
1 | // | ||
2 | // This is a coccinelle semantic patch to ease migration of your project from SDL2 to SDL3. | ||
3 | // | ||
4 | // It generates a patch that you can apply to your project to build for SDL3. It does not | ||
5 | // handle conceptual API changes, but it automates API name changes and function parameter | ||
6 | // transformations. | ||
7 | // | ||
8 | // To install (native Ubuntu or using WSL on Windows): | ||
9 | // sudo apt install coccinelle | ||
10 | // | ||
11 | // Apply the semantic patch to generate a patch file: | ||
12 | // cd path/to/your/code | ||
13 | // spatch --sp-file path/to/SDL_migration.cocci . >patch.txt | ||
14 | // | ||
15 | // A few options: | ||
16 | // --c++=11 to parse cpp file | ||
17 | // --max-width 200 to increase line width of generated source | ||
18 | // | ||
19 | // Apply the patch to your project: | ||
20 | // patch -p1 <patch.txt | ||
21 | // | ||
22 | // | ||
23 | // ############# | ||
24 | // In very short, a semantic patch is composed of two sub-blocks, like | ||
25 | // | ||
26 | // @@ | ||
27 | // declaration | ||
28 | // @@ | ||
29 | // rule / transformation | ||
30 | // | ||
31 | // So this file is a set of many semantic patches, mostly independent. | ||
32 | |||
33 | @ rule_audio_open @ | ||
34 | expression e1, e2; | ||
35 | @@ | ||
36 | - SDL_OpenAudio(e1, e2) | ||
37 | + (g_audio_id = SDL_OpenAudioDevice(NULL, 0, e1, e2, 0)) > 0 ? 0 : -1 | ||
38 | |||
39 | @ depends on rule_audio_open @ | ||
40 | @@ | ||
41 | { | ||
42 | + /* FIXME MIGRATION: maybe move this to a global scope ? */ | ||
43 | + SDL_AudioDeviceID g_audio_id = -1; | ||
44 | ... | ||
45 | SDL_OpenAudioDevice(...) | ||
46 | ... | ||
47 | } | ||
48 | |||
49 | @@ | ||
50 | @@ | ||
51 | - SDL_LockAudio() | ||
52 | + SDL_LockAudioDevice(g_audio_id) | ||
53 | |||
54 | @@ | ||
55 | @@ | ||
56 | - SDL_UnlockAudio() | ||
57 | + SDL_UnlockAudioDevice(g_audio_id) | ||
58 | |||
59 | @@ | ||
60 | @@ | ||
61 | - SDL_CloseAudio(void) | ||
62 | + SDL_CloseAudioDevice(g_audio_id) | ||
63 | |||
64 | @@ | ||
65 | expression e; | ||
66 | @@ | ||
67 | - SDL_PauseAudio(e) | ||
68 | + e ? SDL_PauseAudioDevice(g_audio_id) : SDL_PlayAudioDevice(g_audio_id) | ||
69 | |||
70 | @@ | ||
71 | @@ | ||
72 | - SDL_GetAudioStatus() | ||
73 | + SDL_GetAudioDeviceStatus(g_audio_id) | ||
74 | |||
75 | @@ | ||
76 | @@ | ||
77 | - SDL_GetQueuedAudioSize(1) | ||
78 | + SDL_GetQueuedAudioSize(g_audio_id) | ||
79 | |||
80 | @@ | ||
81 | expression e1, e2; | ||
82 | @@ | ||
83 | - SDL_QueueAudio(1, e1, e2) | ||
84 | + SDL_QueueAudio(g_audio_id, e1, e2) | ||
85 | |||
86 | |||
87 | |||
88 | |||
89 | // SDL_EventState() - replaced with SDL_SetEventEnabled() | ||
90 | @@ | ||
91 | expression e1; | ||
92 | @@ | ||
93 | ( | ||
94 | - SDL_EventState(e1, SDL_IGNORE) | ||
95 | + SDL_SetEventEnabled(e1, false) | ||
96 | | | ||
97 | - SDL_EventState(e1, SDL_DISABLE) | ||
98 | + SDL_SetEventEnabled(e1, false) | ||
99 | | | ||
100 | - SDL_EventState(e1, SDL_ENABLE) | ||
101 | + SDL_SetEventEnabled(e1, true) | ||
102 | | | ||
103 | - SDL_EventState(e1, SDL_QUERY) | ||
104 | + SDL_EventEnabled(e1) | ||
105 | ) | ||
106 | |||
107 | // SDL_GetEventState() - replaced with SDL_EventEnabled() | ||
108 | @@ | ||
109 | expression e1; | ||
110 | @@ | ||
111 | - SDL_GetEventState(e1) | ||
112 | + SDL_EventEnabled(e1) | ||
113 | |||
114 | @@ | ||
115 | expression e; | ||
116 | @@ | ||
117 | - SDL_JoystickGetDevicePlayerIndex(e) | ||
118 | + /* FIXME MIGRATION: check for valid instance */ | ||
119 | + SDL_GetJoystickInstancePlayerIndex(GetJoystickInstanceFromIndex(e)) | ||
120 | |||
121 | @@ | ||
122 | expression e; | ||
123 | @@ | ||
124 | - SDL_JoystickIsVirtual(e) | ||
125 | + /* FIXME MIGRATION: check for valid instance */ | ||
126 | + SDL_IsJoystickVirtual(GetJoystickInstanceFromIndex(e)) | ||
127 | |||
128 | @@ | ||
129 | expression e; | ||
130 | @@ | ||
131 | - SDL_JoystickPathForIndex(e) | ||
132 | + /* FIXME MIGRATION: check for valid instance */ | ||
133 | + SDL_GetJoystickInstancePath(GetJoystickInstanceFromIndex(e)) | ||
134 | |||
135 | @@ | ||
136 | expression e; | ||
137 | @@ | ||
138 | - SDL_IsGameController(e) | ||
139 | + /* FIXME MIGRATION: check for valid instance */ | ||
140 | + SDL_IsGamepad(GetJoystickInstanceFromIndex(e)) | ||
141 | |||
142 | @@ | ||
143 | expression e; | ||
144 | @@ | ||
145 | - SDL_GameControllerMappingForDeviceIndex(e) | ||
146 | + /* FIXME MIGRATION: check for valid instance */ | ||
147 | + SDL_GetGamepadInstanceMapping(GetJoystickInstanceFromIndex(e)) | ||
148 | |||
149 | @@ | ||
150 | expression e; | ||
151 | @@ | ||
152 | - SDL_GameControllerNameForIndex(e) | ||
153 | + /* FIXME MIGRATION: check for valid instance */ | ||
154 | + SDL_GetGamepadInstanceName(GetJoystickInstanceFromIndex(e)) | ||
155 | |||
156 | @@ | ||
157 | expression e; | ||
158 | @@ | ||
159 | - SDL_GameControllerPathForIndex(e) | ||
160 | + /* FIXME MIGRATION: check for valid instance */ | ||
161 | + SDL_GetGamepadInstancePath(GetJoystickInstanceFromIndex(e)) | ||
162 | |||
163 | @@ | ||
164 | expression e; | ||
165 | @@ | ||
166 | - SDL_GameControllerTypeForIndex(e) | ||
167 | + /* FIXME MIGRATION: check for valid instance */ | ||
168 | + SDL_GetGamepadInstanceType(GetJoystickInstanceFromIndex(e)) | ||
169 | |||
170 | |||
171 | // SDL_Has3DNow() has been removed; there is no replacement. | ||
172 | @@ | ||
173 | @@ | ||
174 | + /* FIXME MIGRATION: SDL_Has3DNow() has been removed; there is no replacement. */ 0 | ||
175 | - SDL_Has3DNow() | ||
176 | |||
177 | // SDL_HasRDTSC() has been removed; there is no replacement. | ||
178 | @@ | ||
179 | @@ | ||
180 | + /* FIXME MIGRATION: SDL_HasRDTSC() has been removed; there is no replacement. */ 0 | ||
181 | - SDL_HasRDTSC() | ||
182 | |||
183 | // SDL_HINT_VIDEO_X11_XINERAMA (Xinerama no longer supported by the X11 backend) | ||
184 | @@ | ||
185 | @@ | ||
186 | + /* FIXME MIGRATION: no longer support by the X11 backend */ NULL | ||
187 | - SDL_HINT_VIDEO_X11_XINERAMA | ||
188 | |||
189 | // SDL_HINT_VIDEO_X11_XVIDMODE (Xvidmode no longer supported by the X11 backend) | ||
190 | @@ | ||
191 | @@ | ||
192 | + /* FIXME MIGRATION: no longer support by the X11 backend */ NULL | ||
193 | - SDL_HINT_VIDEO_X11_XVIDMODE | ||
194 | |||
195 | // SDL_HINT_VIDEO_X11_FORCE_EGL (use SDL_HINT_VIDEO_FORCE_EGL instead) | ||
196 | @@ | ||
197 | @@ | ||
198 | - SDL_HINT_VIDEO_X11_FORCE_EGL | ||
199 | + SDL_HINT_VIDEO_FORCE_EGL | ||
200 | |||
201 | @@ | ||
202 | @@ | ||
203 | - SDL_HINT_AUDIODRIVER | ||
204 | + SDL_HINT_AUDIO_DRIVER | ||
205 | |||
206 | @@ | ||
207 | @@ | ||
208 | - SDL_HINT_VIDEODRIVER | ||
209 | + SDL_HINT_VIDEO_DRIVER | ||
210 | |||
211 | // SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0. | ||
212 | @@ | ||
213 | @@ | ||
214 | + /* FIXME MIGRATION: SDL_GetRevisionNumber() removed */ 0 | ||
215 | - SDL_GetRevisionNumber() | ||
216 | |||
217 | // SDL_RWread | ||
218 | @ rule_rwread @ | ||
219 | expression e1, e2, e3, e4; | ||
220 | identifier i; | ||
221 | @@ | ||
222 | ( | ||
223 | i = SDL_RWread(e1, e2, | ||
224 | - e3, e4); | ||
225 | + e3 * e4); | ||
226 | + i = (i <= 0) ? 0 : i / e3; | ||
227 | | | ||
228 | SDL_RWread(e1, e2, | ||
229 | - e3, e4); | ||
230 | + e3 * e4); | ||
231 | | | ||
232 | + /* FIXME MIGRATION: double-check if you use the returned value of SDL_RWread() */ | ||
233 | SDL_RWread(e1, e2, | ||
234 | - e3, e4) | ||
235 | + e3 * e4) | ||
236 | |||
237 | ) | ||
238 | |||
239 | // SDL_RWwrite | ||
240 | @ rule_rwwrite @ | ||
241 | expression e1, e2, e3, e4; | ||
242 | identifier i; | ||
243 | @@ | ||
244 | ( | ||
245 | i = SDL_RWwrite(e1, e2, | ||
246 | - e3, e4); | ||
247 | + e3 * e4); | ||
248 | + i = (i <= 0) ? 0 : i / e3; | ||
249 | | | ||
250 | SDL_RWwrite(e1, e2, | ||
251 | - e3, e4); | ||
252 | + e3 * e4); | ||
253 | | | ||
254 | + /* FIXME MIGRATION: double-check if you use the returned value of SDL_RWwrite() */ | ||
255 | SDL_RWwrite(e1, e2, | ||
256 | - e3, e4) | ||
257 | + e3 * e4) | ||
258 | ) | ||
259 | |||
260 | @ depends on rule_rwread || rule_rwwrite @ | ||
261 | expression e; | ||
262 | @@ | ||
263 | ( | ||
264 | - e * 1 | ||
265 | + e | ||
266 | | | ||
267 | - e / 1 | ||
268 | + e | ||
269 | ) | ||
270 | |||
271 | // SDL_SIMDAlloc(), SDL_SIMDFree() have been removed. | ||
272 | @@ | ||
273 | expression e1; | ||
274 | @@ | ||
275 | - SDL_SIMDAlloc(e1) | ||
276 | + SDL_aligned_alloc(SDL_SIMDGetAlignment(), e1) | ||
277 | |||
278 | @@ | ||
279 | expression e1; | ||
280 | @@ | ||
281 | - SDL_SIMDFree( | ||
282 | + SDL_aligned_free( | ||
283 | e1) | ||
284 | |||
285 | // SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter. | ||
286 | @@ | ||
287 | expression e1, e2, e3; | ||
288 | @@ | ||
289 | SDL_Vulkan_GetInstanceExtensions( | ||
290 | - e1, | ||
291 | e2, e3) | ||
292 | |||
293 | // SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr. | ||
294 | @@ | ||
295 | typedef PFN_vkGetInstanceProcAddr; | ||
296 | @@ | ||
297 | ( | ||
298 | (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr() | ||
299 | | | ||
300 | + (PFN_vkGetInstanceProcAddr) | ||
301 | SDL_Vulkan_GetVkGetInstanceProcAddr() | ||
302 | ) | ||
303 | |||
304 | // SDL_PauseAudioDevice / SDL_PlayAudioDevice | ||
305 | @@ | ||
306 | expression e; | ||
307 | @@ | ||
308 | ( | ||
309 | - SDL_PauseAudioDevice(e, 1) | ||
310 | + SDL_PauseAudioDevice(e) | ||
311 | | | ||
312 | - SDL_PauseAudioDevice(e, SDL_TRUE) | ||
313 | + SDL_PauseAudioDevice(e) | ||
314 | | | ||
315 | - SDL_PauseAudioDevice(e, 0) | ||
316 | + SDL_ResumeAudioDevice(e) | ||
317 | | | ||
318 | - SDL_PauseAudioDevice(e, SDL_FALSE) | ||
319 | + SDL_ResumeAudioDevice(e) | ||
320 | ) | ||
321 | |||
322 | @@ | ||
323 | expression e, pause_on; | ||
324 | @@ | ||
325 | - SDL_PauseAudioDevice(e, pause_on); | ||
326 | + if (pause_on) { | ||
327 | + SDL_PauseAudioDevice(e); | ||
328 | + } else { | ||
329 | + SDL_ResumeAudioDevice(e); | ||
330 | + } | ||
331 | |||
332 | |||
333 | // Remove SDL_WINDOW_SHOWN | ||
334 | @@ | ||
335 | expression e; | ||
336 | @@ | ||
337 | ( | ||
338 | - SDL_WINDOW_SHOWN | e | ||
339 | + e | ||
340 | | | ||
341 | - SDL_WINDOW_SHOWN | ||
342 | + 0 | ||
343 | ) | ||
344 | |||
345 | |||
346 | @@ | ||
347 | // Remove parameter from SDL_ConvertSurface | ||
348 | expression e1, e2, e3; | ||
349 | @@ | ||
350 | SDL_ConvertSurface(e1, e2 | ||
351 | - ,e3) | ||
352 | + ) | ||
353 | |||
354 | |||
355 | @@ | ||
356 | // Remove parameter from SDL_ConvertSurfaceFormat | ||
357 | expression e1, e2, e3; | ||
358 | @@ | ||
359 | SDL_ConvertSurfaceFormat(e1, e2 | ||
360 | - ,e3) | ||
361 | + ) | ||
362 | |||
363 | |||
364 | @@ | ||
365 | // SDL_CreateRGBSurfaceWithFormat | ||
366 | // remove 'flags' | ||
367 | // remove 'depth' | ||
368 | // rename to SDL_CreateSurface | ||
369 | expression e1, e2, e3, e4, e5; | ||
370 | @@ | ||
371 | - SDL_CreateRGBSurfaceWithFormat(e1, e2, e3, e4, e5) | ||
372 | + SDL_CreateSurface(e2, e3, e5) | ||
373 | |||
374 | |||
375 | @@ | ||
376 | // SDL_CreateRGBSurfaceWithFormat: | ||
377 | // remove 'depth' | ||
378 | // rename to SDL_CreateSurfaceFrom | ||
379 | expression e1, e2, e3, e4, e5, e6; | ||
380 | @@ | ||
381 | - SDL_CreateRGBSurfaceWithFormatFrom(e1, e2, e3, e4, e5, e6) | ||
382 | + SDL_CreateSurfaceFrom(e1, e2, e3, e5, e6) | ||
383 | |||
384 | |||
385 | |||
386 | @@ | ||
387 | // SDL_CreateRGBSurface : convert Masks to format | ||
388 | expression e1, e2, e3, e4, e5, e6, e7, e8, e9; | ||
389 | |||
390 | @@ | ||
391 | |||
392 | ( | ||
393 | |||
394 | // Generated for all formats: | ||
395 | |||
396 | - SDL_CreateRGBSurface(e1, e2, e3, 1, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
397 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_INDEX1LSB) | ||
398 | |||
399 | | | ||
400 | |||
401 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 1, e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
402 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_INDEX1LSB) | ||
403 | |||
404 | | | ||
405 | |||
406 | - SDL_CreateRGBSurface(e1, e2, e3, 1, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
407 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_INDEX1MSB) | ||
408 | |||
409 | | | ||
410 | |||
411 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 1, e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
412 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_INDEX1MSB) | ||
413 | |||
414 | | | ||
415 | |||
416 | - SDL_CreateRGBSurface(e1, e2, e3, 4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
417 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_INDEX4LSB) | ||
418 | |||
419 | | | ||
420 | |||
421 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 4, e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
422 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_INDEX4LSB) | ||
423 | |||
424 | | | ||
425 | |||
426 | - SDL_CreateRGBSurface(e1, e2, e3, 4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
427 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_INDEX4MSB) | ||
428 | |||
429 | | | ||
430 | |||
431 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 4, e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
432 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_INDEX4MSB) | ||
433 | |||
434 | | | ||
435 | |||
436 | - SDL_CreateRGBSurface(e1, e2, e3, 8, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
437 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_INDEX8) | ||
438 | |||
439 | | | ||
440 | |||
441 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 8, e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000) | ||
442 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_INDEX8) | ||
443 | |||
444 | | | ||
445 | |||
446 | - SDL_CreateRGBSurface(e1, e2, e3, 8, 0x000000E0, 0x0000001C, 0x00000003, 0x00000000) | ||
447 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGB332) | ||
448 | |||
449 | | | ||
450 | |||
451 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 8, e4, 0x000000E0, 0x0000001C, 0x00000003, 0x00000000) | ||
452 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGB332) | ||
453 | |||
454 | | | ||
455 | |||
456 | - SDL_CreateRGBSurface(e1, e2, e3, 12, 0x00000F00, 0x000000F0, 0x0000000F, 0x00000000) | ||
457 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGB444) | ||
458 | |||
459 | | | ||
460 | |||
461 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 12, e4, 0x00000F00, 0x000000F0, 0x0000000F, 0x00000000) | ||
462 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGB444) | ||
463 | |||
464 | | | ||
465 | |||
466 | - SDL_CreateRGBSurface(e1, e2, e3, 15, 0x00007C00, 0x000003E0, 0x0000001F, 0x00000000) | ||
467 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGB555) | ||
468 | |||
469 | | | ||
470 | |||
471 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 15, e4, 0x00007C00, 0x000003E0, 0x0000001F, 0x00000000) | ||
472 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGB555) | ||
473 | |||
474 | | | ||
475 | |||
476 | - SDL_CreateRGBSurface(e1, e2, e3, 15, 0x0000001F, 0x000003E0, 0x00007C00, 0x00000000) | ||
477 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGR555) | ||
478 | |||
479 | | | ||
480 | |||
481 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 15, e4, 0x0000001F, 0x000003E0, 0x00007C00, 0x00000000) | ||
482 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGR555) | ||
483 | |||
484 | | | ||
485 | |||
486 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x00000F00, 0x000000F0, 0x0000000F, 0x0000F000) | ||
487 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ARGB4444) | ||
488 | |||
489 | | | ||
490 | |||
491 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x00000F00, 0x000000F0, 0x0000000F, 0x0000F000) | ||
492 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ARGB4444) | ||
493 | |||
494 | | | ||
495 | |||
496 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000F000, 0x00000F00, 0x000000F0, 0x0000000F) | ||
497 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGBA4444) | ||
498 | |||
499 | | | ||
500 | |||
501 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000F000, 0x00000F00, 0x000000F0, 0x0000000F) | ||
502 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGBA4444) | ||
503 | |||
504 | | | ||
505 | |||
506 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000) | ||
507 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ABGR4444) | ||
508 | |||
509 | | | ||
510 | |||
511 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000) | ||
512 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ABGR4444) | ||
513 | |||
514 | | | ||
515 | |||
516 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x000000F0, 0x00000F00, 0x0000F000, 0x0000000F) | ||
517 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGRA4444) | ||
518 | |||
519 | | | ||
520 | |||
521 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x000000F0, 0x00000F00, 0x0000F000, 0x0000000F) | ||
522 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGRA4444) | ||
523 | |||
524 | | | ||
525 | |||
526 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x00007C00, 0x000003E0, 0x0000001F, 0x00008000) | ||
527 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ARGB1555) | ||
528 | |||
529 | | | ||
530 | |||
531 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x00007C00, 0x000003E0, 0x0000001F, 0x00008000) | ||
532 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ARGB1555) | ||
533 | |||
534 | | | ||
535 | |||
536 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000F800, 0x000007C0, 0x0000003E, 0x00000001) | ||
537 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGBA5551) | ||
538 | |||
539 | | | ||
540 | |||
541 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000F800, 0x000007C0, 0x0000003E, 0x00000001) | ||
542 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGBA5551) | ||
543 | |||
544 | | | ||
545 | |||
546 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000001F, 0x000003E0, 0x00007C00, 0x00008000) | ||
547 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ABGR1555) | ||
548 | |||
549 | | | ||
550 | |||
551 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000001F, 0x000003E0, 0x00007C00, 0x00008000) | ||
552 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ABGR1555) | ||
553 | |||
554 | | | ||
555 | |||
556 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000003E, 0x000007C0, 0x0000F800, 0x00000001) | ||
557 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGRA5551) | ||
558 | |||
559 | | | ||
560 | |||
561 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000003E, 0x000007C0, 0x0000F800, 0x00000001) | ||
562 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGRA5551) | ||
563 | |||
564 | | | ||
565 | |||
566 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000) | ||
567 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGB565) | ||
568 | |||
569 | | | ||
570 | |||
571 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000) | ||
572 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGB565) | ||
573 | |||
574 | | | ||
575 | |||
576 | - SDL_CreateRGBSurface(e1, e2, e3, 16, 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000) | ||
577 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGR565) | ||
578 | |||
579 | | | ||
580 | |||
581 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 16, e4, 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000) | ||
582 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGR565) | ||
583 | |||
584 | | | ||
585 | |||
586 | - SDL_CreateRGBSurface(e1, e2, e3, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000) | ||
587 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGB24) | ||
588 | |||
589 | | | ||
590 | |||
591 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 24, e4, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000) | ||
592 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGB24) | ||
593 | |||
594 | | | ||
595 | |||
596 | - SDL_CreateRGBSurface(e1, e2, e3, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000) | ||
597 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGR24) | ||
598 | |||
599 | | | ||
600 | |||
601 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 24, e4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000) | ||
602 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGR24) | ||
603 | |||
604 | | | ||
605 | |||
606 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000) | ||
607 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_XRGB8888) | ||
608 | |||
609 | | | ||
610 | |||
611 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000) | ||
612 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_XRGB8888) | ||
613 | |||
614 | | | ||
615 | |||
616 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000) | ||
617 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGBX8888) | ||
618 | |||
619 | | | ||
620 | |||
621 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000) | ||
622 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGBX8888) | ||
623 | |||
624 | | | ||
625 | |||
626 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000) | ||
627 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_XBGR8888) | ||
628 | |||
629 | | | ||
630 | |||
631 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000) | ||
632 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_XBGR8888) | ||
633 | |||
634 | | | ||
635 | |||
636 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000) | ||
637 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGRX8888) | ||
638 | |||
639 | | | ||
640 | |||
641 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000) | ||
642 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGRX8888) | ||
643 | |||
644 | | | ||
645 | |||
646 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000) | ||
647 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ARGB8888) | ||
648 | |||
649 | | | ||
650 | |||
651 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000) | ||
652 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ARGB8888) | ||
653 | |||
654 | | | ||
655 | |||
656 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF) | ||
657 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_RGBA8888) | ||
658 | |||
659 | | | ||
660 | |||
661 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF) | ||
662 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_RGBA8888) | ||
663 | |||
664 | | | ||
665 | |||
666 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000) | ||
667 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ABGR8888) | ||
668 | |||
669 | | | ||
670 | |||
671 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000) | ||
672 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ABGR8888) | ||
673 | |||
674 | | | ||
675 | |||
676 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF) | ||
677 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_BGRA8888) | ||
678 | |||
679 | | | ||
680 | |||
681 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF) | ||
682 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_BGRA8888) | ||
683 | |||
684 | | | ||
685 | |||
686 | - SDL_CreateRGBSurface(e1, e2, e3, 32, 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000) | ||
687 | + SDL_CreateSurface(e2, e3, SDL_PIXELFORMAT_ARGB2101010) | ||
688 | |||
689 | | | ||
690 | |||
691 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, 32, e4, 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000) | ||
692 | + SDL_CreateSurfaceFrom(e1, e2, e3, e4, SDL_PIXELFORMAT_ARGB2101010) | ||
693 | |||
694 | | | ||
695 | |||
696 | // End Generated | ||
697 | |||
698 | |||
699 | - SDL_CreateRGBSurface(e1, e2, e3, e4->BitsPerPixel, e4->Rmask, e4->Gmask, e4->Bmask, e4->Amask) | ||
700 | + SDL_CreateSurface(e2, e3, e4->format) | ||
701 | |||
702 | | | ||
703 | |||
704 | - SDL_CreateRGBSurfaceFrom(e1, e2, e3, e4->BitsPerPixel, e5, e4->Rmask, e4->Gmask, e4->Bmask, e4->Amask) | ||
705 | + SDL_CreateSurfaceFrom(e1, e2, e3, e5, e4->format) | ||
706 | |||
707 | | | ||
708 | |||
709 | -SDL_CreateRGBSurface(e1, e2, e3, e4, e5, e6, e7, e8) | ||
710 | +SDL_CreateSurface(e2, e3, SDL_MasksToPixelFormatEnum(e4, e5, e6, e7, e8)) | ||
711 | |||
712 | | | ||
713 | |||
714 | -SDL_CreateRGBSurfaceFrom(e1, e2, e3, e4, e5, e6, e7, e8, e9) | ||
715 | +SDL_CreateSurfaceFrom(e1, e2, e3, e5, SDL_MasksToPixelFormatEnum(e4, e6, e7, e8, e9)) | ||
716 | |||
717 | ) | ||
718 | |||
719 | @@ | ||
720 | // SDL_CreateRenderer: | ||
721 | // 2nd argument changed from int (default=-1) to const char* (default=NULL) | ||
722 | expression e1, e3; | ||
723 | int e2; | ||
724 | @@ | ||
725 | |||
726 | ( | ||
727 | |||
728 | -SDL_CreateRenderer(e1, -1, e3) | ||
729 | +SDL_CreateRenderer(e1, NULL, e3) | ||
730 | |||
731 | | | ||
732 | |||
733 | -SDL_CreateRenderer(e1, e2, e3) | ||
734 | +SDL_CreateRenderer(e1, SDL_GetRenderDriver(e2), e3) | ||
735 | |||
736 | ) | ||
737 | |||
738 | // Renaming of SDL_oldnames.h | ||
739 | |||
740 | @@ | ||
741 | @@ | ||
742 | - SDL_AudioStreamAvailable | ||
743 | + SDL_GetAudioStreamAvailable | ||
744 | (...) | ||
745 | @@ | ||
746 | @@ | ||
747 | - SDL_AudioStreamClear | ||
748 | + SDL_ClearAudioStream | ||
749 | (...) | ||
750 | @@ | ||
751 | @@ | ||
752 | - SDL_AudioStreamFlush | ||
753 | + SDL_FlushAudioStream | ||
754 | (...) | ||
755 | @@ | ||
756 | @@ | ||
757 | - SDL_AudioStreamGet | ||
758 | + SDL_GetAudioStreamData | ||
759 | (...) | ||
760 | @@ | ||
761 | @@ | ||
762 | - SDL_AudioStreamPut | ||
763 | + SDL_PutAudioStreamData | ||
764 | (...) | ||
765 | @@ | ||
766 | @@ | ||
767 | - SDL_FreeAudioStream | ||
768 | + SDL_DestroyAudioStream | ||
769 | (...) | ||
770 | @@ | ||
771 | @@ | ||
772 | - SDL_FreeWAV | ||
773 | + SDL_free | ||
774 | (...) | ||
775 | @@ | ||
776 | @@ | ||
777 | - SDL_NewAudioStream | ||
778 | + SDL_CreateAudioStream | ||
779 | (...) | ||
780 | @@ | ||
781 | @@ | ||
782 | - SDL_CONTROLLERAXISMOTION | ||
783 | + SDL_EVENT_GAMEPAD_AXIS_MOTION | ||
784 | @@ | ||
785 | @@ | ||
786 | - SDL_CONTROLLERBUTTONDOWN | ||
787 | + SDL_EVENT_GAMEPAD_BUTTON_DOWN | ||
788 | @@ | ||
789 | @@ | ||
790 | - SDL_CONTROLLERBUTTONUP | ||
791 | + SDL_EVENT_GAMEPAD_BUTTON_UP | ||
792 | @@ | ||
793 | @@ | ||
794 | - SDL_CONTROLLERDEVICEADDED | ||
795 | + SDL_EVENT_GAMEPAD_ADDED | ||
796 | @@ | ||
797 | @@ | ||
798 | - SDL_CONTROLLERDEVICEREMAPPED | ||
799 | + SDL_EVENT_GAMEPAD_REMAPPED | ||
800 | @@ | ||
801 | @@ | ||
802 | - SDL_CONTROLLERDEVICEREMOVED | ||
803 | + SDL_EVENT_GAMEPAD_REMOVED | ||
804 | @@ | ||
805 | @@ | ||
806 | - SDL_CONTROLLERSENSORUPDATE | ||
807 | + SDL_EVENT_GAMEPAD_SENSOR_UPDATE | ||
808 | @@ | ||
809 | @@ | ||
810 | - SDL_CONTROLLERTOUCHPADDOWN | ||
811 | + SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN | ||
812 | @@ | ||
813 | @@ | ||
814 | - SDL_CONTROLLERTOUCHPADMOTION | ||
815 | + SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION | ||
816 | @@ | ||
817 | @@ | ||
818 | - SDL_CONTROLLERTOUCHPADUP | ||
819 | + SDL_EVENT_GAMEPAD_TOUCHPAD_UP | ||
820 | @@ | ||
821 | typedef SDL_ControllerAxisEvent, SDL_GamepadAxisEvent; | ||
822 | @@ | ||
823 | - SDL_ControllerAxisEvent | ||
824 | + SDL_GamepadAxisEvent | ||
825 | @@ | ||
826 | typedef SDL_ControllerButtonEvent, SDL_GamepadButtonEvent; | ||
827 | @@ | ||
828 | - SDL_ControllerButtonEvent | ||
829 | + SDL_GamepadButtonEvent | ||
830 | @@ | ||
831 | typedef SDL_ControllerDeviceEvent, SDL_GamepadDeviceEvent; | ||
832 | @@ | ||
833 | - SDL_ControllerDeviceEvent | ||
834 | + SDL_GamepadDeviceEvent | ||
835 | @@ | ||
836 | typedef SDL_ControllerSensorEvent, SDL_GamepadSensorEvent; | ||
837 | @@ | ||
838 | - SDL_ControllerSensorEvent | ||
839 | + SDL_GamepadSensorEvent | ||
840 | @@ | ||
841 | typedef SDL_ControllerTouchpadEvent, SDL_GamepadTouchpadEvent; | ||
842 | @@ | ||
843 | - SDL_ControllerTouchpadEvent | ||
844 | + SDL_GamepadTouchpadEvent | ||
845 | @@ | ||
846 | @@ | ||
847 | - SDL_CONTROLLER_AXIS_INVALID | ||
848 | + SDL_GAMEPAD_AXIS_INVALID | ||
849 | @@ | ||
850 | @@ | ||
851 | - SDL_CONTROLLER_AXIS_LEFTX | ||
852 | + SDL_GAMEPAD_AXIS_LEFTX | ||
853 | @@ | ||
854 | @@ | ||
855 | - SDL_CONTROLLER_AXIS_LEFTY | ||
856 | + SDL_GAMEPAD_AXIS_LEFTY | ||
857 | @@ | ||
858 | @@ | ||
859 | - SDL_CONTROLLER_AXIS_MAX | ||
860 | + SDL_GAMEPAD_AXIS_COUNT | ||
861 | @@ | ||
862 | @@ | ||
863 | - SDL_CONTROLLER_AXIS_RIGHTX | ||
864 | + SDL_GAMEPAD_AXIS_RIGHTX | ||
865 | @@ | ||
866 | @@ | ||
867 | - SDL_CONTROLLER_AXIS_RIGHTY | ||
868 | + SDL_GAMEPAD_AXIS_RIGHTY | ||
869 | @@ | ||
870 | @@ | ||
871 | - SDL_CONTROLLER_AXIS_TRIGGERLEFT | ||
872 | + SDL_GAMEPAD_AXIS_LEFT_TRIGGER | ||
873 | @@ | ||
874 | @@ | ||
875 | - SDL_CONTROLLER_AXIS_TRIGGERRIGHT | ||
876 | + SDL_GAMEPAD_AXIS_RIGHT_TRIGGER | ||
877 | @@ | ||
878 | @@ | ||
879 | - SDL_CONTROLLER_BINDTYPE_AXIS | ||
880 | + SDL_GAMEPAD_BINDTYPE_AXIS | ||
881 | @@ | ||
882 | @@ | ||
883 | - SDL_CONTROLLER_BINDTYPE_BUTTON | ||
884 | + SDL_GAMEPAD_BINDTYPE_BUTTON | ||
885 | @@ | ||
886 | @@ | ||
887 | - SDL_CONTROLLER_BINDTYPE_HAT | ||
888 | + SDL_GAMEPAD_BINDTYPE_HAT | ||
889 | @@ | ||
890 | @@ | ||
891 | - SDL_CONTROLLER_BINDTYPE_NONE | ||
892 | + SDL_GAMEPAD_BINDTYPE_NONE | ||
893 | @@ | ||
894 | @@ | ||
895 | - SDL_CONTROLLER_BUTTON_A | ||
896 | + SDL_GAMEPAD_BUTTON_SOUTH | ||
897 | @@ | ||
898 | @@ | ||
899 | - SDL_CONTROLLER_BUTTON_B | ||
900 | + SDL_GAMEPAD_BUTTON_EAST | ||
901 | @@ | ||
902 | @@ | ||
903 | - SDL_CONTROLLER_BUTTON_BACK | ||
904 | + SDL_GAMEPAD_BUTTON_BACK | ||
905 | @@ | ||
906 | @@ | ||
907 | - SDL_CONTROLLER_BUTTON_DPAD_DOWN | ||
908 | + SDL_GAMEPAD_BUTTON_DPAD_DOWN | ||
909 | @@ | ||
910 | @@ | ||
911 | - SDL_CONTROLLER_BUTTON_DPAD_LEFT | ||
912 | + SDL_GAMEPAD_BUTTON_DPAD_LEFT | ||
913 | @@ | ||
914 | @@ | ||
915 | - SDL_CONTROLLER_BUTTON_DPAD_RIGHT | ||
916 | + SDL_GAMEPAD_BUTTON_DPAD_RIGHT | ||
917 | @@ | ||
918 | @@ | ||
919 | - SDL_CONTROLLER_BUTTON_DPAD_UP | ||
920 | + SDL_GAMEPAD_BUTTON_DPAD_UP | ||
921 | @@ | ||
922 | @@ | ||
923 | - SDL_CONTROLLER_BUTTON_GUIDE | ||
924 | + SDL_GAMEPAD_BUTTON_GUIDE | ||
925 | @@ | ||
926 | @@ | ||
927 | - SDL_CONTROLLER_BUTTON_INVALID | ||
928 | + SDL_GAMEPAD_BUTTON_INVALID | ||
929 | @@ | ||
930 | @@ | ||
931 | - SDL_CONTROLLER_BUTTON_LEFTSHOULDER | ||
932 | + SDL_GAMEPAD_BUTTON_LEFT_SHOULDER | ||
933 | @@ | ||
934 | @@ | ||
935 | - SDL_CONTROLLER_BUTTON_LEFTSTICK | ||
936 | + SDL_GAMEPAD_BUTTON_LEFT_STICK | ||
937 | @@ | ||
938 | @@ | ||
939 | - SDL_CONTROLLER_BUTTON_MAX | ||
940 | + SDL_GAMEPAD_BUTTON_COUNT | ||
941 | @@ | ||
942 | @@ | ||
943 | - SDL_CONTROLLER_BUTTON_MISC1 | ||
944 | + SDL_GAMEPAD_BUTTON_MISC1 | ||
945 | @@ | ||
946 | @@ | ||
947 | - SDL_CONTROLLER_BUTTON_PADDLE1 | ||
948 | + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 | ||
949 | @@ | ||
950 | @@ | ||
951 | - SDL_CONTROLLER_BUTTON_PADDLE2 | ||
952 | + SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 | ||
953 | @@ | ||
954 | @@ | ||
955 | - SDL_CONTROLLER_BUTTON_PADDLE3 | ||
956 | + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 | ||
957 | @@ | ||
958 | @@ | ||
959 | - SDL_CONTROLLER_BUTTON_PADDLE4 | ||
960 | + SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 | ||
961 | @@ | ||
962 | @@ | ||
963 | - SDL_CONTROLLER_BUTTON_RIGHTSHOULDER | ||
964 | + SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER | ||
965 | @@ | ||
966 | @@ | ||
967 | - SDL_CONTROLLER_BUTTON_RIGHTSTICK | ||
968 | + SDL_GAMEPAD_BUTTON_RIGHT_STICK | ||
969 | @@ | ||
970 | @@ | ||
971 | - SDL_CONTROLLER_BUTTON_START | ||
972 | + SDL_GAMEPAD_BUTTON_START | ||
973 | @@ | ||
974 | @@ | ||
975 | - SDL_CONTROLLER_BUTTON_TOUCHPAD | ||
976 | + SDL_GAMEPAD_BUTTON_TOUCHPAD | ||
977 | @@ | ||
978 | @@ | ||
979 | - SDL_CONTROLLER_BUTTON_X | ||
980 | + SDL_GAMEPAD_BUTTON_WEST | ||
981 | @@ | ||
982 | @@ | ||
983 | - SDL_CONTROLLER_BUTTON_Y | ||
984 | + SDL_GAMEPAD_BUTTON_NORTH | ||
985 | @@ | ||
986 | @@ | ||
987 | - SDL_CONTROLLER_TYPE_AMAZON_LUNA | ||
988 | + SDL_GAMEPAD_TYPE_AMAZON_LUNA | ||
989 | @@ | ||
990 | @@ | ||
991 | - SDL_CONTROLLER_TYPE_GOOGLE_STADIA | ||
992 | + SDL_GAMEPAD_TYPE_GOOGLE_STADIA | ||
993 | @@ | ||
994 | @@ | ||
995 | - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT | ||
996 | + SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT | ||
997 | @@ | ||
998 | @@ | ||
999 | - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR | ||
1000 | + SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR | ||
1001 | @@ | ||
1002 | @@ | ||
1003 | - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT | ||
1004 | + SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT | ||
1005 | @@ | ||
1006 | @@ | ||
1007 | - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO | ||
1008 | + SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO | ||
1009 | @@ | ||
1010 | @@ | ||
1011 | - SDL_CONTROLLER_TYPE_NVIDIA_SHIELD | ||
1012 | + SDL_GAMEPAD_TYPE_NVIDIA_SHIELD | ||
1013 | @@ | ||
1014 | @@ | ||
1015 | - SDL_CONTROLLER_TYPE_PS3 | ||
1016 | + SDL_GAMEPAD_TYPE_PS3 | ||
1017 | @@ | ||
1018 | @@ | ||
1019 | - SDL_CONTROLLER_TYPE_PS4 | ||
1020 | + SDL_GAMEPAD_TYPE_PS4 | ||
1021 | @@ | ||
1022 | @@ | ||
1023 | - SDL_CONTROLLER_TYPE_PS5 | ||
1024 | + SDL_GAMEPAD_TYPE_PS5 | ||
1025 | @@ | ||
1026 | @@ | ||
1027 | - SDL_CONTROLLER_TYPE_UNKNOWN | ||
1028 | + SDL_GAMEPAD_TYPE_UNKNOWN | ||
1029 | @@ | ||
1030 | @@ | ||
1031 | - SDL_CONTROLLER_TYPE_VIRTUAL | ||
1032 | + SDL_GAMEPAD_TYPE_VIRTUAL | ||
1033 | @@ | ||
1034 | @@ | ||
1035 | - SDL_CONTROLLER_TYPE_XBOX360 | ||
1036 | + SDL_GAMEPAD_TYPE_XBOX360 | ||
1037 | @@ | ||
1038 | @@ | ||
1039 | - SDL_CONTROLLER_TYPE_XBOXONE | ||
1040 | + SDL_GAMEPAD_TYPE_XBOXONE | ||
1041 | @@ | ||
1042 | typedef SDL_GameController, SDL_Gamepad; | ||
1043 | @@ | ||
1044 | - SDL_GameController | ||
1045 | + SDL_Gamepad | ||
1046 | @@ | ||
1047 | @@ | ||
1048 | - SDL_GameControllerAddMapping | ||
1049 | + SDL_AddGamepadMapping | ||
1050 | (...) | ||
1051 | @@ | ||
1052 | @@ | ||
1053 | - SDL_GameControllerAddMappingsFromFile | ||
1054 | + SDL_AddGamepadMappingsFromFile | ||
1055 | (...) | ||
1056 | @@ | ||
1057 | @@ | ||
1058 | - SDL_GameControllerAddMappingsFromRW | ||
1059 | + SDL_AddGamepadMappingsFromIO | ||
1060 | (...) | ||
1061 | @@ | ||
1062 | typedef SDL_GameControllerAxis, SDL_GamepadAxis; | ||
1063 | @@ | ||
1064 | - SDL_GameControllerAxis | ||
1065 | + SDL_GamepadAxis | ||
1066 | @@ | ||
1067 | typedef SDL_GameControllerBindType, SDL_GamepadBindingType; | ||
1068 | @@ | ||
1069 | - SDL_GameControllerBindType | ||
1070 | + SDL_GamepadBindingType | ||
1071 | @@ | ||
1072 | typedef SDL_GameControllerButton, SDL_GamepadButton; | ||
1073 | @@ | ||
1074 | - SDL_GameControllerButton | ||
1075 | + SDL_GamepadButton | ||
1076 | @@ | ||
1077 | @@ | ||
1078 | - SDL_GameControllerClose | ||
1079 | + SDL_CloseGamepad | ||
1080 | (...) | ||
1081 | @@ | ||
1082 | @@ | ||
1083 | - SDL_GameControllerFromInstanceID | ||
1084 | + SDL_GetGamepadFromID | ||
1085 | (...) | ||
1086 | @@ | ||
1087 | @@ | ||
1088 | - SDL_GameControllerFromPlayerIndex | ||
1089 | + SDL_GetGamepadFromPlayerIndex | ||
1090 | (...) | ||
1091 | @@ | ||
1092 | @@ | ||
1093 | - SDL_GameControllerGetAppleSFSymbolsNameForAxis | ||
1094 | + SDL_GetGamepadAppleSFSymbolsNameForAxis | ||
1095 | (...) | ||
1096 | @@ | ||
1097 | @@ | ||
1098 | - SDL_GameControllerGetAppleSFSymbolsNameForButton | ||
1099 | + SDL_GetGamepadAppleSFSymbolsNameForButton | ||
1100 | (...) | ||
1101 | @@ | ||
1102 | @@ | ||
1103 | - SDL_GameControllerGetAttached | ||
1104 | + SDL_GamepadConnected | ||
1105 | (...) | ||
1106 | @@ | ||
1107 | @@ | ||
1108 | - SDL_GameControllerGetAxis | ||
1109 | + SDL_GetGamepadAxis | ||
1110 | (...) | ||
1111 | @@ | ||
1112 | @@ | ||
1113 | - SDL_GameControllerGetAxisFromString | ||
1114 | + SDL_GetGamepadAxisFromString | ||
1115 | (...) | ||
1116 | @@ | ||
1117 | @@ | ||
1118 | - SDL_GameControllerGetButton | ||
1119 | + SDL_GetGamepadButton | ||
1120 | (...) | ||
1121 | @@ | ||
1122 | @@ | ||
1123 | - SDL_GameControllerGetButtonFromString | ||
1124 | + SDL_GetGamepadButtonFromString | ||
1125 | (...) | ||
1126 | @@ | ||
1127 | @@ | ||
1128 | - SDL_GameControllerGetFirmwareVersion | ||
1129 | + SDL_GetGamepadFirmwareVersion | ||
1130 | (...) | ||
1131 | @@ | ||
1132 | @@ | ||
1133 | - SDL_GameControllerGetJoystick | ||
1134 | + SDL_GetGamepadJoystick | ||
1135 | (...) | ||
1136 | @@ | ||
1137 | @@ | ||
1138 | - SDL_GameControllerGetNumTouchpadFingers | ||
1139 | + SDL_GetNumGamepadTouchpadFingers | ||
1140 | (...) | ||
1141 | @@ | ||
1142 | @@ | ||
1143 | - SDL_GameControllerGetNumTouchpads | ||
1144 | + SDL_GetNumGamepadTouchpads | ||
1145 | (...) | ||
1146 | @@ | ||
1147 | @@ | ||
1148 | - SDL_GameControllerGetPlayerIndex | ||
1149 | + SDL_GetGamepadPlayerIndex | ||
1150 | (...) | ||
1151 | @@ | ||
1152 | @@ | ||
1153 | - SDL_GameControllerGetProduct | ||
1154 | + SDL_GetGamepadProduct | ||
1155 | (...) | ||
1156 | @@ | ||
1157 | @@ | ||
1158 | - SDL_GameControllerGetProductVersion | ||
1159 | + SDL_GetGamepadProductVersion | ||
1160 | (...) | ||
1161 | @@ | ||
1162 | @@ | ||
1163 | - SDL_GameControllerGetSensorData | ||
1164 | + SDL_GetGamepadSensorData | ||
1165 | (...) | ||
1166 | @@ | ||
1167 | @@ | ||
1168 | - SDL_GameControllerGetSensorDataRate | ||
1169 | + SDL_GetGamepadSensorDataRate | ||
1170 | (...) | ||
1171 | @@ | ||
1172 | @@ | ||
1173 | - SDL_GameControllerGetSerial | ||
1174 | + SDL_GetGamepadSerial | ||
1175 | (...) | ||
1176 | @@ | ||
1177 | @@ | ||
1178 | - SDL_GameControllerGetStringForAxis | ||
1179 | + SDL_GetGamepadStringForAxis | ||
1180 | (...) | ||
1181 | @@ | ||
1182 | @@ | ||
1183 | - SDL_GameControllerGetStringForButton | ||
1184 | + SDL_GetGamepadStringForButton | ||
1185 | (...) | ||
1186 | @@ | ||
1187 | @@ | ||
1188 | - SDL_GameControllerGetTouchpadFinger | ||
1189 | + SDL_GetGamepadTouchpadFinger | ||
1190 | (...) | ||
1191 | @@ | ||
1192 | @@ | ||
1193 | - SDL_GameControllerGetType | ||
1194 | + SDL_GetGamepadType | ||
1195 | (...) | ||
1196 | @@ | ||
1197 | @@ | ||
1198 | - SDL_GameControllerGetVendor | ||
1199 | + SDL_GetGamepadVendor | ||
1200 | (...) | ||
1201 | @@ | ||
1202 | @@ | ||
1203 | - SDL_GameControllerHasAxis | ||
1204 | + SDL_GamepadHasAxis | ||
1205 | (...) | ||
1206 | @@ | ||
1207 | @@ | ||
1208 | - SDL_GameControllerHasButton | ||
1209 | + SDL_GamepadHasButton | ||
1210 | (...) | ||
1211 | @@ | ||
1212 | @@ | ||
1213 | - SDL_GameControllerHasSensor | ||
1214 | + SDL_GamepadHasSensor | ||
1215 | (...) | ||
1216 | @@ | ||
1217 | @@ | ||
1218 | - SDL_GameControllerIsSensorEnabled | ||
1219 | + SDL_GamepadSensorEnabled | ||
1220 | (...) | ||
1221 | @@ | ||
1222 | @@ | ||
1223 | - SDL_GameControllerMapping | ||
1224 | + SDL_GetGamepadMapping | ||
1225 | (...) | ||
1226 | @@ | ||
1227 | @@ | ||
1228 | - SDL_GameControllerMappingForGUID | ||
1229 | + SDL_GetGamepadMappingForGUID | ||
1230 | (...) | ||
1231 | @@ | ||
1232 | @@ | ||
1233 | - SDL_GameControllerName | ||
1234 | + SDL_GetGamepadName | ||
1235 | (...) | ||
1236 | @@ | ||
1237 | @@ | ||
1238 | - SDL_GameControllerOpen | ||
1239 | + SDL_OpenGamepad | ||
1240 | (...) | ||
1241 | @@ | ||
1242 | @@ | ||
1243 | - SDL_GameControllerPath | ||
1244 | + SDL_GetGamepadPath | ||
1245 | (...) | ||
1246 | @@ | ||
1247 | @@ | ||
1248 | - SDL_GameControllerRumble | ||
1249 | + SDL_RumbleGamepad | ||
1250 | (...) | ||
1251 | @@ | ||
1252 | @@ | ||
1253 | - SDL_GameControllerRumbleTriggers | ||
1254 | + SDL_RumbleGamepadTriggers | ||
1255 | (...) | ||
1256 | @@ | ||
1257 | @@ | ||
1258 | - SDL_GameControllerSendEffect | ||
1259 | + SDL_SendGamepadEffect | ||
1260 | (...) | ||
1261 | @@ | ||
1262 | @@ | ||
1263 | - SDL_GameControllerSetLED | ||
1264 | + SDL_SetGamepadLED | ||
1265 | (...) | ||
1266 | @@ | ||
1267 | @@ | ||
1268 | - SDL_GameControllerSetPlayerIndex | ||
1269 | + SDL_SetGamepadPlayerIndex | ||
1270 | (...) | ||
1271 | @@ | ||
1272 | @@ | ||
1273 | - SDL_GameControllerSetSensorEnabled | ||
1274 | + SDL_SetGamepadSensorEnabled | ||
1275 | (...) | ||
1276 | @@ | ||
1277 | @@ | ||
1278 | - SDL_GameControllerType | ||
1279 | + SDL_GamepadType | ||
1280 | (...) | ||
1281 | @@ | ||
1282 | @@ | ||
1283 | - SDL_GameControllerUpdate | ||
1284 | + SDL_UpdateGamepads | ||
1285 | (...) | ||
1286 | @@ | ||
1287 | @@ | ||
1288 | - SDL_INIT_GAMECONTROLLER | ||
1289 | + SDL_INIT_GAMEPAD | ||
1290 | @ rule_init_noparachute @ | ||
1291 | @@ | ||
1292 | - SDL_INIT_NOPARACHUTE | ||
1293 | + 0 | ||
1294 | @@ | ||
1295 | @@ | ||
1296 | - SDL_JOYSTICK_TYPE_GAMECONTROLLER | ||
1297 | + SDL_JOYSTICK_TYPE_GAMEPAD | ||
1298 | @@ | ||
1299 | @@ | ||
1300 | - SDL_JoystickAttachVirtualEx | ||
1301 | + SDL_AttachVirtualJoystick | ||
1302 | (...) | ||
1303 | @@ | ||
1304 | @@ | ||
1305 | - SDL_JoystickClose | ||
1306 | + SDL_CloseJoystick | ||
1307 | (...) | ||
1308 | @@ | ||
1309 | @@ | ||
1310 | - SDL_JoystickCurrentPowerLevel | ||
1311 | + SDL_GetJoystickPowerLevel | ||
1312 | (...) | ||
1313 | @@ | ||
1314 | @@ | ||
1315 | - SDL_JoystickDetachVirtual | ||
1316 | + SDL_DetachVirtualJoystick | ||
1317 | (...) | ||
1318 | @@ | ||
1319 | @@ | ||
1320 | - SDL_JoystickFromInstanceID | ||
1321 | + SDL_GetJoystickFromID | ||
1322 | (...) | ||
1323 | @@ | ||
1324 | @@ | ||
1325 | - SDL_JoystickFromPlayerIndex | ||
1326 | + SDL_GetJoystickFromPlayerIndex | ||
1327 | (...) | ||
1328 | @@ | ||
1329 | @@ | ||
1330 | - SDL_JoystickGetAttached | ||
1331 | + SDL_JoystickConnected | ||
1332 | (...) | ||
1333 | @@ | ||
1334 | @@ | ||
1335 | - SDL_JoystickGetAxis | ||
1336 | + SDL_GetJoystickAxis | ||
1337 | (...) | ||
1338 | @@ | ||
1339 | @@ | ||
1340 | - SDL_JoystickGetAxisInitialState | ||
1341 | + SDL_GetJoystickAxisInitialState | ||
1342 | (...) | ||
1343 | @@ | ||
1344 | @@ | ||
1345 | - SDL_JoystickGetButton | ||
1346 | + SDL_GetJoystickButton | ||
1347 | (...) | ||
1348 | @@ | ||
1349 | @@ | ||
1350 | - SDL_JoystickGetFirmwareVersion | ||
1351 | + SDL_GetJoystickFirmwareVersion | ||
1352 | (...) | ||
1353 | @@ | ||
1354 | @@ | ||
1355 | - SDL_JoystickGetGUID | ||
1356 | + SDL_GetJoystickGUID | ||
1357 | (...) | ||
1358 | @@ | ||
1359 | @@ | ||
1360 | - SDL_JoystickGetGUIDFromString | ||
1361 | + SDL_StringToGUID | ||
1362 | (...) | ||
1363 | @@ | ||
1364 | @@ | ||
1365 | - SDL_JoystickGetHat | ||
1366 | + SDL_GetJoystickHat | ||
1367 | (...) | ||
1368 | @@ | ||
1369 | @@ | ||
1370 | - SDL_JoystickGetPlayerIndex | ||
1371 | + SDL_GetJoystickPlayerIndex | ||
1372 | (...) | ||
1373 | @@ | ||
1374 | @@ | ||
1375 | - SDL_JoystickGetProduct | ||
1376 | + SDL_GetJoystickProduct | ||
1377 | (...) | ||
1378 | @@ | ||
1379 | @@ | ||
1380 | - SDL_JoystickGetProductVersion | ||
1381 | + SDL_GetJoystickProductVersion | ||
1382 | (...) | ||
1383 | @@ | ||
1384 | @@ | ||
1385 | - SDL_JoystickGetSerial | ||
1386 | + SDL_GetJoystickSerial | ||
1387 | (...) | ||
1388 | @@ | ||
1389 | @@ | ||
1390 | - SDL_JoystickGetType | ||
1391 | + SDL_GetJoystickType | ||
1392 | (...) | ||
1393 | @@ | ||
1394 | @@ | ||
1395 | - SDL_JoystickGetVendor | ||
1396 | + SDL_GetJoystickVendor | ||
1397 | (...) | ||
1398 | @@ | ||
1399 | @@ | ||
1400 | - SDL_JoystickInstanceID | ||
1401 | + SDL_GetJoystickID | ||
1402 | (...) | ||
1403 | @@ | ||
1404 | @@ | ||
1405 | - SDL_JoystickName | ||
1406 | + SDL_GetJoystickName | ||
1407 | (...) | ||
1408 | @@ | ||
1409 | @@ | ||
1410 | - SDL_JoystickNumAxes | ||
1411 | + SDL_GetNumJoystickAxes | ||
1412 | (...) | ||
1413 | @@ | ||
1414 | @@ | ||
1415 | - SDL_JoystickNumButtons | ||
1416 | + SDL_GetNumJoystickButtons | ||
1417 | (...) | ||
1418 | @@ | ||
1419 | @@ | ||
1420 | - SDL_JoystickNumHats | ||
1421 | + SDL_GetNumJoystickHats | ||
1422 | (...) | ||
1423 | @@ | ||
1424 | @@ | ||
1425 | - SDL_JoystickOpen | ||
1426 | + SDL_OpenJoystick | ||
1427 | (...) | ||
1428 | @@ | ||
1429 | @@ | ||
1430 | - SDL_JoystickPath | ||
1431 | + SDL_GetJoystickPath | ||
1432 | (...) | ||
1433 | @@ | ||
1434 | @@ | ||
1435 | - SDL_JoystickRumble | ||
1436 | + SDL_RumbleJoystick | ||
1437 | (...) | ||
1438 | @@ | ||
1439 | @@ | ||
1440 | - SDL_JoystickRumbleTriggers | ||
1441 | + SDL_RumbleJoystickTriggers | ||
1442 | (...) | ||
1443 | @@ | ||
1444 | @@ | ||
1445 | - SDL_JoystickSendEffect | ||
1446 | + SDL_SendJoystickEffect | ||
1447 | (...) | ||
1448 | @@ | ||
1449 | @@ | ||
1450 | - SDL_JoystickSetLED | ||
1451 | + SDL_SetJoystickLED | ||
1452 | (...) | ||
1453 | @@ | ||
1454 | @@ | ||
1455 | - SDL_JoystickSetPlayerIndex | ||
1456 | + SDL_SetJoystickPlayerIndex | ||
1457 | (...) | ||
1458 | @@ | ||
1459 | @@ | ||
1460 | - SDL_JoystickSetVirtualAxis | ||
1461 | + SDL_SetJoystickVirtualAxis | ||
1462 | (...) | ||
1463 | @@ | ||
1464 | @@ | ||
1465 | - SDL_JoystickSetVirtualButton | ||
1466 | + SDL_SetJoystickVirtualButton | ||
1467 | (...) | ||
1468 | @@ | ||
1469 | @@ | ||
1470 | - SDL_JoystickSetVirtualHat | ||
1471 | + SDL_SetJoystickVirtualHat | ||
1472 | (...) | ||
1473 | @@ | ||
1474 | @@ | ||
1475 | - SDL_JoystickUpdate | ||
1476 | + SDL_UpdateJoysticks | ||
1477 | (...) | ||
1478 | @@ | ||
1479 | @@ | ||
1480 | - SDL_IsScreenKeyboardShown | ||
1481 | + SDL_ScreenKeyboardShown | ||
1482 | (...) | ||
1483 | @@ | ||
1484 | @@ | ||
1485 | - SDL_IsTextInputActive | ||
1486 | + SDL_TextInputActive | ||
1487 | (...) | ||
1488 | @@ | ||
1489 | @@ | ||
1490 | - SDL_IsTextInputShown | ||
1491 | + SDL_TextInputShown | ||
1492 | (...) | ||
1493 | @@ | ||
1494 | SDL_Event e1; | ||
1495 | @@ | ||
1496 | - e1.key.keysym.mod | ||
1497 | + e1.key.mod | ||
1498 | @@ | ||
1499 | SDL_Event *e1; | ||
1500 | @@ | ||
1501 | - e1->key.keysym.mod | ||
1502 | + e1->key.mod | ||
1503 | @@ | ||
1504 | SDL_KeyboardEvent *e1; | ||
1505 | @@ | ||
1506 | - e1->keysym.mod | ||
1507 | + e1->mod | ||
1508 | @@ | ||
1509 | SDL_Event e1; | ||
1510 | @@ | ||
1511 | - e1.key.keysym.sym | ||
1512 | + e1.key.key | ||
1513 | @@ | ||
1514 | SDL_Event *e1; | ||
1515 | @@ | ||
1516 | - e1->key.keysym.sym | ||
1517 | + e1->key.key | ||
1518 | @@ | ||
1519 | SDL_KeyboardEvent *e1; | ||
1520 | @@ | ||
1521 | - e1->keysym.sym | ||
1522 | + e1->key | ||
1523 | @@ | ||
1524 | SDL_Event e1; | ||
1525 | @@ | ||
1526 | - e1.key.keysym.scancode | ||
1527 | + e1.key.scancode | ||
1528 | @@ | ||
1529 | SDL_Event *e1; | ||
1530 | @@ | ||
1531 | - e1->key.keysym.scancode | ||
1532 | + e1->key.scancode | ||
1533 | @@ | ||
1534 | SDL_KeyboardEvent *e1; | ||
1535 | @@ | ||
1536 | - e1->keysym.scancode | ||
1537 | + e1->scancode | ||
1538 | @@ | ||
1539 | @@ | ||
1540 | - KMOD_ALT | ||
1541 | + SDL_KMOD_ALT | ||
1542 | @@ | ||
1543 | @@ | ||
1544 | - KMOD_CAPS | ||
1545 | + SDL_KMOD_CAPS | ||
1546 | @@ | ||
1547 | @@ | ||
1548 | - KMOD_CTRL | ||
1549 | + SDL_KMOD_CTRL | ||
1550 | @@ | ||
1551 | @@ | ||
1552 | - KMOD_GUI | ||
1553 | + SDL_KMOD_GUI | ||
1554 | @@ | ||
1555 | @@ | ||
1556 | - KMOD_LALT | ||
1557 | + SDL_KMOD_LALT | ||
1558 | @@ | ||
1559 | @@ | ||
1560 | - KMOD_LCTRL | ||
1561 | + SDL_KMOD_LCTRL | ||
1562 | @@ | ||
1563 | @@ | ||
1564 | - KMOD_LGUI | ||
1565 | + SDL_KMOD_LGUI | ||
1566 | @@ | ||
1567 | @@ | ||
1568 | - KMOD_LSHIFT | ||
1569 | + SDL_KMOD_LSHIFT | ||
1570 | @@ | ||
1571 | @@ | ||
1572 | - KMOD_MODE | ||
1573 | + SDL_KMOD_MODE | ||
1574 | @@ | ||
1575 | @@ | ||
1576 | - KMOD_NONE | ||
1577 | + SDL_KMOD_NONE | ||
1578 | @@ | ||
1579 | @@ | ||
1580 | - KMOD_NUM | ||
1581 | + SDL_KMOD_NUM | ||
1582 | @@ | ||
1583 | @@ | ||
1584 | - KMOD_RALT | ||
1585 | + SDL_KMOD_RALT | ||
1586 | @@ | ||
1587 | @@ | ||
1588 | - KMOD_RCTRL | ||
1589 | + SDL_KMOD_RCTRL | ||
1590 | @@ | ||
1591 | @@ | ||
1592 | - KMOD_RGUI | ||
1593 | + SDL_KMOD_RGUI | ||
1594 | @@ | ||
1595 | @@ | ||
1596 | - KMOD_RSHIFT | ||
1597 | + SDL_KMOD_RSHIFT | ||
1598 | @@ | ||
1599 | @@ | ||
1600 | - KMOD_SCROLL | ||
1601 | + SDL_KMOD_SCROLL | ||
1602 | @@ | ||
1603 | @@ | ||
1604 | - KMOD_SHIFT | ||
1605 | + SDL_KMOD_SHIFT | ||
1606 | @@ | ||
1607 | @@ | ||
1608 | - SDL_FreeCursor | ||
1609 | + SDL_DestroyCursor | ||
1610 | (...) | ||
1611 | @@ | ||
1612 | @@ | ||
1613 | - SDL_AllocFormat | ||
1614 | + SDL_GetPixelFormatDetails | ||
1615 | (...) | ||
1616 | @@ | ||
1617 | @@ | ||
1618 | - SDL_AllocPalette | ||
1619 | + SDL_CreatePalette | ||
1620 | (...) | ||
1621 | @@ | ||
1622 | @@ | ||
1623 | - SDL_FreePalette | ||
1624 | + SDL_DestroyPalette | ||
1625 | (...) | ||
1626 | @@ | ||
1627 | @@ | ||
1628 | - SDL_MasksToPixelFormatEnum | ||
1629 | + SDL_GetPixelFormatForMasks | ||
1630 | (...) | ||
1631 | @@ | ||
1632 | @@ | ||
1633 | - SDL_PixelFormatEnumToMasks | ||
1634 | + SDL_GetMasksForPixelFormat | ||
1635 | (...) | ||
1636 | @@ | ||
1637 | @@ | ||
1638 | - SDL_EncloseFPoints | ||
1639 | + SDL_GetRectEnclosingPointsFloat | ||
1640 | (...) | ||
1641 | @@ | ||
1642 | @@ | ||
1643 | - SDL_EnclosePoints | ||
1644 | + SDL_GetRectEnclosingPoints | ||
1645 | (...) | ||
1646 | @@ | ||
1647 | @@ | ||
1648 | - SDL_FRectEmpty | ||
1649 | + SDL_RectEmptyFloat | ||
1650 | (...) | ||
1651 | @@ | ||
1652 | @@ | ||
1653 | - SDL_FRectEquals | ||
1654 | + SDL_RectsEqualFloat | ||
1655 | (...) | ||
1656 | @@ | ||
1657 | @@ | ||
1658 | - SDL_FRectEqualsEpsilon | ||
1659 | + SDL_RectsEqualEpsilon | ||
1660 | (...) | ||
1661 | @@ | ||
1662 | @@ | ||
1663 | - SDL_HasIntersection | ||
1664 | + SDL_HasRectIntersection | ||
1665 | (...) | ||
1666 | @@ | ||
1667 | @@ | ||
1668 | - SDL_HasIntersectionF | ||
1669 | + SDL_HasRectIntersectionFloat | ||
1670 | (...) | ||
1671 | @@ | ||
1672 | @@ | ||
1673 | - SDL_IntersectFRect | ||
1674 | + SDL_GetRectIntersectionFloat | ||
1675 | (...) | ||
1676 | @@ | ||
1677 | @@ | ||
1678 | - SDL_IntersectFRectAndLine | ||
1679 | + SDL_GetRectAndLineIntersectionFloat | ||
1680 | (...) | ||
1681 | @@ | ||
1682 | @@ | ||
1683 | - SDL_IntersectRect | ||
1684 | + SDL_GetRectIntersection | ||
1685 | (...) | ||
1686 | @@ | ||
1687 | @@ | ||
1688 | - SDL_IntersectRectAndLine | ||
1689 | + SDL_GetRectAndLineIntersection | ||
1690 | (...) | ||
1691 | @@ | ||
1692 | @@ | ||
1693 | - SDL_PointInFRect | ||
1694 | + SDL_PointInRectFloat | ||
1695 | (...) | ||
1696 | @@ | ||
1697 | @@ | ||
1698 | - SDL_RectEquals | ||
1699 | + SDL_RectsEqual | ||
1700 | (...) | ||
1701 | @@ | ||
1702 | @@ | ||
1703 | - SDL_UnionFRect | ||
1704 | + SDL_GetRectUnionFloat | ||
1705 | (...) | ||
1706 | @@ | ||
1707 | @@ | ||
1708 | - SDL_UnionRect | ||
1709 | + SDL_GetRectUnion | ||
1710 | (...) | ||
1711 | @@ | ||
1712 | @@ | ||
1713 | - SDL_RenderCopyExF | ||
1714 | + SDL_RenderTextureRotated | ||
1715 | (...) | ||
1716 | @@ | ||
1717 | @@ | ||
1718 | - SDL_RenderCopyF | ||
1719 | + SDL_RenderTexture | ||
1720 | (...) | ||
1721 | @@ | ||
1722 | @@ | ||
1723 | - SDL_RenderDrawLineF | ||
1724 | + SDL_RenderLine | ||
1725 | (...) | ||
1726 | @@ | ||
1727 | @@ | ||
1728 | - SDL_RenderDrawLinesF | ||
1729 | + SDL_RenderLines | ||
1730 | (...) | ||
1731 | @@ | ||
1732 | @@ | ||
1733 | - SDL_RenderDrawPointF | ||
1734 | + SDL_RenderPoint | ||
1735 | (...) | ||
1736 | @@ | ||
1737 | @@ | ||
1738 | - SDL_RenderDrawPointsF | ||
1739 | + SDL_RenderPoints | ||
1740 | (...) | ||
1741 | @@ | ||
1742 | @@ | ||
1743 | - SDL_RenderDrawRectF | ||
1744 | + SDL_RenderRect | ||
1745 | (...) | ||
1746 | @@ | ||
1747 | @@ | ||
1748 | - SDL_RenderDrawRectsF | ||
1749 | + SDL_RenderRects | ||
1750 | (...) | ||
1751 | @@ | ||
1752 | @@ | ||
1753 | - SDL_RenderFillRectF | ||
1754 | + SDL_RenderFillRect | ||
1755 | (...) | ||
1756 | @@ | ||
1757 | @@ | ||
1758 | - SDL_RenderFillRectsF | ||
1759 | + SDL_RenderFillRects | ||
1760 | (...) | ||
1761 | @@ | ||
1762 | @@ | ||
1763 | - SDL_RenderGetClipRect | ||
1764 | + SDL_GetRenderClipRect | ||
1765 | (...) | ||
1766 | @@ | ||
1767 | SDL_Renderer *renderer; | ||
1768 | int *e1; | ||
1769 | int *e2; | ||
1770 | @@ | ||
1771 | - SDL_RenderGetLogicalSize(renderer, e1, e2) | ||
1772 | + SDL_GetRenderLogicalPresentation(renderer, e1, e2, NULL, NULL) | ||
1773 | @@ | ||
1774 | @@ | ||
1775 | - SDL_RenderGetMetalCommandEncoder | ||
1776 | + SDL_GetRenderMetalCommandEncoder | ||
1777 | (...) | ||
1778 | @@ | ||
1779 | @@ | ||
1780 | - SDL_RenderGetMetalLayer | ||
1781 | + SDL_GetRenderMetalLayer | ||
1782 | (...) | ||
1783 | @@ | ||
1784 | @@ | ||
1785 | - SDL_RenderGetScale | ||
1786 | + SDL_GetRenderScale | ||
1787 | (...) | ||
1788 | @@ | ||
1789 | @@ | ||
1790 | - SDL_RenderGetViewport | ||
1791 | + SDL_GetRenderViewport | ||
1792 | (...) | ||
1793 | @@ | ||
1794 | @@ | ||
1795 | - SDL_RenderGetWindow | ||
1796 | + SDL_GetRenderWindow | ||
1797 | (...) | ||
1798 | @@ | ||
1799 | @@ | ||
1800 | - SDL_RenderIsClipEnabled | ||
1801 | + SDL_RenderClipEnabled | ||
1802 | (...) | ||
1803 | @@ | ||
1804 | @@ | ||
1805 | - SDL_RenderSetClipRect | ||
1806 | + SDL_SetRenderClipRect | ||
1807 | (...) | ||
1808 | @@ | ||
1809 | SDL_Renderer *renderer; | ||
1810 | expression e1; | ||
1811 | expression e2; | ||
1812 | @@ | ||
1813 | ( | ||
1814 | - SDL_RenderSetLogicalSize(renderer, 0, 0) | ||
1815 | + SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED) | ||
1816 | | | ||
1817 | - SDL_RenderSetLogicalSize(renderer, e1, e2) | ||
1818 | + SDL_SetRenderLogicalPresentation(renderer, e1, e2, SDL_LOGICAL_PRESENTATION_LETTERBOX) | ||
1819 | ) | ||
1820 | @@ | ||
1821 | @@ | ||
1822 | - SDL_RenderSetScale | ||
1823 | + SDL_SetRenderScale | ||
1824 | (...) | ||
1825 | @@ | ||
1826 | @@ | ||
1827 | - SDL_RenderSetVSync | ||
1828 | + SDL_SetRenderVSync | ||
1829 | (...) | ||
1830 | @@ | ||
1831 | @@ | ||
1832 | - SDL_RenderSetViewport | ||
1833 | + SDL_SetRenderViewport | ||
1834 | (...) | ||
1835 | @@ | ||
1836 | @@ | ||
1837 | - RW_SEEK_CUR | ||
1838 | + SDL_IO_SEEK_CUR | ||
1839 | @@ | ||
1840 | @@ | ||
1841 | - RW_SEEK_END | ||
1842 | + SDL_IO_SEEK_END | ||
1843 | @@ | ||
1844 | @@ | ||
1845 | - RW_SEEK_SET | ||
1846 | + SDL_IO_SEEK_SET | ||
1847 | @@ | ||
1848 | @@ | ||
1849 | - SDL_SensorClose | ||
1850 | + SDL_CloseSensor | ||
1851 | (...) | ||
1852 | @@ | ||
1853 | @@ | ||
1854 | - SDL_SensorFromInstanceID | ||
1855 | + SDL_GetSensorFromID | ||
1856 | (...) | ||
1857 | @@ | ||
1858 | @@ | ||
1859 | - SDL_SensorGetData | ||
1860 | + SDL_GetSensorData | ||
1861 | (...) | ||
1862 | @@ | ||
1863 | @@ | ||
1864 | - SDL_SensorGetInstanceID | ||
1865 | + SDL_GetSensorID | ||
1866 | (...) | ||
1867 | @@ | ||
1868 | @@ | ||
1869 | - SDL_SensorGetName | ||
1870 | + SDL_GetSensorName | ||
1871 | (...) | ||
1872 | @@ | ||
1873 | @@ | ||
1874 | - SDL_SensorGetNonPortableType | ||
1875 | + SDL_GetSensorNonPortableType | ||
1876 | (...) | ||
1877 | @@ | ||
1878 | @@ | ||
1879 | - SDL_SensorGetType | ||
1880 | + SDL_GetSensorType | ||
1881 | (...) | ||
1882 | @@ | ||
1883 | @@ | ||
1884 | - SDL_SensorOpen | ||
1885 | + SDL_OpenSensor | ||
1886 | (...) | ||
1887 | @@ | ||
1888 | @@ | ||
1889 | - SDL_SensorUpdate | ||
1890 | + SDL_UpdateSensors | ||
1891 | (...) | ||
1892 | @@ | ||
1893 | @@ | ||
1894 | - SDL_FillRect | ||
1895 | + SDL_FillSurfaceRect | ||
1896 | (...) | ||
1897 | @@ | ||
1898 | @@ | ||
1899 | - SDL_FillRects | ||
1900 | + SDL_FillSurfaceRects | ||
1901 | (...) | ||
1902 | @@ | ||
1903 | @@ | ||
1904 | - SDL_FreeSurface | ||
1905 | + SDL_DestroySurface | ||
1906 | (...) | ||
1907 | @@ | ||
1908 | @@ | ||
1909 | - SDL_GetClipRect | ||
1910 | + SDL_GetSurfaceClipRect | ||
1911 | (...) | ||
1912 | @@ | ||
1913 | @@ | ||
1914 | - SDL_GetColorKey | ||
1915 | + SDL_GetSurfaceColorKey | ||
1916 | (...) | ||
1917 | @@ | ||
1918 | @@ | ||
1919 | - SDL_HasColorKey | ||
1920 | + SDL_SurfaceHasColorKey | ||
1921 | (...) | ||
1922 | @@ | ||
1923 | @@ | ||
1924 | - SDL_HasSurfaceRLE | ||
1925 | + SDL_SurfaceHasRLE | ||
1926 | (...) | ||
1927 | @@ | ||
1928 | @@ | ||
1929 | - SDL_LowerBlit | ||
1930 | + SDL_BlitSurfaceUnchecked | ||
1931 | (...) | ||
1932 | @@ | ||
1933 | expression e1, e2, e3, e4; | ||
1934 | @@ | ||
1935 | - SDL_LowerBlitScaled(e1, e2, e3, e4) | ||
1936 | + SDL_BlitSurfaceUncheckedScaled(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) | ||
1937 | @@ | ||
1938 | @@ | ||
1939 | - SDL_SetClipRect | ||
1940 | + SDL_SetSurfaceClipRect | ||
1941 | (...) | ||
1942 | @@ | ||
1943 | @@ | ||
1944 | - SDL_SetColorKey | ||
1945 | + SDL_SetSurfaceColorKey | ||
1946 | (...) | ||
1947 | @@ | ||
1948 | @@ | ||
1949 | - SDL_UpperBlit | ||
1950 | + SDL_BlitSurface | ||
1951 | (...) | ||
1952 | @@ | ||
1953 | expression e1, e2, e3, e4; | ||
1954 | @@ | ||
1955 | - SDL_UpperBlitScaled(e1, e2, e3, e4) | ||
1956 | + SDL_BlitSurfaceScaled(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) | ||
1957 | @@ | ||
1958 | @@ | ||
1959 | - SDL_RenderGetD3D11Device | ||
1960 | + SDL_GetRenderD3D11Device | ||
1961 | (...) | ||
1962 | @@ | ||
1963 | @@ | ||
1964 | - SDL_RenderGetD3D9Device | ||
1965 | + SDL_GetRenderD3D9Device | ||
1966 | (...) | ||
1967 | @@ | ||
1968 | @@ | ||
1969 | - SDL_GetTicks64 | ||
1970 | + SDL_GetTicks | ||
1971 | (...) | ||
1972 | @@ | ||
1973 | @@ | ||
1974 | - SDL_GetPointDisplayIndex | ||
1975 | + SDL_GetDisplayForPoint | ||
1976 | (...) | ||
1977 | @@ | ||
1978 | @@ | ||
1979 | - SDL_GetRectDisplayIndex | ||
1980 | + SDL_GetDisplayForRect | ||
1981 | (...) | ||
1982 | @ depends on rule_init_noparachute @ | ||
1983 | expression e; | ||
1984 | @@ | ||
1985 | - e | 0 | ||
1986 | + e | ||
1987 | @@ | ||
1988 | @@ | ||
1989 | - SDL_FIRSTEVENT | ||
1990 | + SDL_EVENT_FIRST | ||
1991 | @@ | ||
1992 | @@ | ||
1993 | - SDL_QUIT | ||
1994 | + SDL_EVENT_QUIT | ||
1995 | @@ | ||
1996 | @@ | ||
1997 | - SDL_APP_TERMINATING | ||
1998 | + SDL_EVENT_TERMINATING | ||
1999 | @@ | ||
2000 | @@ | ||
2001 | - SDL_APP_LOWMEMORY | ||
2002 | + SDL_EVENT_LOW_MEMORY | ||
2003 | @@ | ||
2004 | @@ | ||
2005 | - SDL_APP_WILLENTERBACKGROUND | ||
2006 | + SDL_EVENT_WILL_ENTER_BACKGROUND | ||
2007 | @@ | ||
2008 | @@ | ||
2009 | - SDL_APP_DIDENTERBACKGROUND | ||
2010 | + SDL_EVENT_DID_ENTER_BACKGROUND | ||
2011 | @@ | ||
2012 | @@ | ||
2013 | - SDL_APP_WILLENTERFOREGROUND | ||
2014 | + SDL_EVENT_WILL_ENTER_FOREGROUND | ||
2015 | @@ | ||
2016 | @@ | ||
2017 | - SDL_APP_DIDENTERFOREGROUND | ||
2018 | + SDL_EVENT_DID_ENTER_FOREGROUND | ||
2019 | @@ | ||
2020 | @@ | ||
2021 | - SDL_LOCALECHANGED | ||
2022 | + SDL_EVENT_LOCALE_CHANGED | ||
2023 | @@ | ||
2024 | @@ | ||
2025 | - SDL_DISPLAYEVENT_ORIENTATION | ||
2026 | + SDL_EVENT_DISPLAY_ORIENTATION | ||
2027 | @@ | ||
2028 | @@ | ||
2029 | - SDL_DISPLAYEVENT_CONNECTED | ||
2030 | + SDL_EVENT_DISPLAY_CONNECTED | ||
2031 | @@ | ||
2032 | @@ | ||
2033 | - SDL_DISPLAYEVENT_DISCONNECTED | ||
2034 | + SDL_EVENT_DISPLAY_DISCONNECTED | ||
2035 | @@ | ||
2036 | @@ | ||
2037 | - SDL_DISPLAYEVENT_MOVED | ||
2038 | + SDL_EVENT_DISPLAY_MOVED | ||
2039 | @@ | ||
2040 | @@ | ||
2041 | - SDL_DISPLAYEVENT_FIRST | ||
2042 | + SDL_EVENT_DISPLAY_FIRST | ||
2043 | @@ | ||
2044 | @@ | ||
2045 | - SDL_DISPLAYEVENT_LAST | ||
2046 | + SDL_EVENT_DISPLAY_LAST | ||
2047 | @@ | ||
2048 | @@ | ||
2049 | - SDL_SYSWMEVENT | ||
2050 | + SDL_EVENT_SYSWM | ||
2051 | @@ | ||
2052 | @@ | ||
2053 | - SDL_WINDOWEVENT_SHOWN | ||
2054 | + SDL_EVENT_WINDOW_SHOWN | ||
2055 | @@ | ||
2056 | @@ | ||
2057 | - SDL_WINDOWEVENT_HIDDEN | ||
2058 | + SDL_EVENT_WINDOW_HIDDEN | ||
2059 | @@ | ||
2060 | @@ | ||
2061 | - SDL_WINDOWEVENT_EXPOSED | ||
2062 | + SDL_EVENT_WINDOW_EXPOSED | ||
2063 | @@ | ||
2064 | @@ | ||
2065 | - SDL_WINDOWEVENT_MOVED | ||
2066 | + SDL_EVENT_WINDOW_MOVED | ||
2067 | @@ | ||
2068 | @@ | ||
2069 | - SDL_WINDOWEVENT_RESIZED | ||
2070 | + SDL_EVENT_WINDOW_RESIZED | ||
2071 | @@ | ||
2072 | @@ | ||
2073 | - SDL_WINDOWEVENT_SIZE_CHANGED | ||
2074 | + SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED | ||
2075 | @@ | ||
2076 | @@ | ||
2077 | - SDL_WINDOWEVENT_MINIMIZED | ||
2078 | + SDL_EVENT_WINDOW_MINIMIZED | ||
2079 | @@ | ||
2080 | @@ | ||
2081 | - SDL_WINDOWEVENT_MAXIMIZED | ||
2082 | + SDL_EVENT_WINDOW_MAXIMIZED | ||
2083 | @@ | ||
2084 | @@ | ||
2085 | - SDL_WINDOWEVENT_RESTORED | ||
2086 | + SDL_EVENT_WINDOW_RESTORED | ||
2087 | @@ | ||
2088 | @@ | ||
2089 | - SDL_WINDOWEVENT_ENTER | ||
2090 | + SDL_EVENT_WINDOW_MOUSE_ENTER | ||
2091 | @@ | ||
2092 | @@ | ||
2093 | - SDL_WINDOWEVENT_LEAVE | ||
2094 | + SDL_EVENT_WINDOW_MOUSE_LEAVE | ||
2095 | @@ | ||
2096 | @@ | ||
2097 | - SDL_WINDOWEVENT_FOCUS_GAINED | ||
2098 | + SDL_EVENT_WINDOW_FOCUS_GAINED | ||
2099 | @@ | ||
2100 | @@ | ||
2101 | - SDL_WINDOWEVENT_FOCUS_LOST | ||
2102 | + SDL_EVENT_WINDOW_FOCUS_LOST | ||
2103 | @@ | ||
2104 | @@ | ||
2105 | - SDL_WINDOWEVENT_CLOSE | ||
2106 | + SDL_EVENT_WINDOW_CLOSE_REQUESTED | ||
2107 | @@ | ||
2108 | @@ | ||
2109 | - SDL_WINDOWEVENT_TAKE_FOCUS | ||
2110 | + /* FIXME MIGRATION: SDL_WINDOWEVENT_TAKE_FOCUS has been removed; there is no replacement. */ 0 | ||
2111 | @@ | ||
2112 | @@ | ||
2113 | - SDL_WINDOWEVENT_HIT_TEST | ||
2114 | + SDL_EVENT_WINDOW_HIT_TEST | ||
2115 | @@ | ||
2116 | @@ | ||
2117 | - SDL_WINDOWEVENT_ICCPROF_CHANGED | ||
2118 | + SDL_EVENT_WINDOW_ICCPROF_CHANGED | ||
2119 | @@ | ||
2120 | @@ | ||
2121 | - SDL_WINDOWEVENT_DISPLAY_CHANGED | ||
2122 | + SDL_EVENT_WINDOW_DISPLAY_CHANGED | ||
2123 | @@ | ||
2124 | @@ | ||
2125 | - SDL_WINDOWEVENT_FIRST | ||
2126 | + SDL_EVENT_WINDOW_FIRST | ||
2127 | @@ | ||
2128 | @@ | ||
2129 | - SDL_WINDOWEVENT_LAST | ||
2130 | + SDL_EVENT_WINDOW_LAST | ||
2131 | @@ | ||
2132 | @@ | ||
2133 | - SDL_KEYDOWN | ||
2134 | + SDL_EVENT_KEY_DOWN | ||
2135 | @@ | ||
2136 | @@ | ||
2137 | - SDL_KEYUP | ||
2138 | + SDL_EVENT_KEY_UP | ||
2139 | @@ | ||
2140 | @@ | ||
2141 | - SDL_TEXTEDITING | ||
2142 | + SDL_EVENT_TEXT_EDITING | ||
2143 | @@ | ||
2144 | @@ | ||
2145 | - SDL_TEXTINPUT | ||
2146 | + SDL_EVENT_TEXT_INPUT | ||
2147 | @@ | ||
2148 | @@ | ||
2149 | - SDL_KEYMAPCHANGED | ||
2150 | + SDL_EVENT_KEYMAP_CHANGED | ||
2151 | @@ | ||
2152 | @@ | ||
2153 | - SDL_TEXTEDITING_EXT | ||
2154 | + SDL_EVENT_TEXT_EDITING_EXT | ||
2155 | @@ | ||
2156 | @@ | ||
2157 | - SDL_MOUSEMOTION | ||
2158 | + SDL_EVENT_MOUSE_MOTION | ||
2159 | @@ | ||
2160 | @@ | ||
2161 | - SDL_MOUSEBUTTONDOWN | ||
2162 | + SDL_EVENT_MOUSE_BUTTON_DOWN | ||
2163 | @@ | ||
2164 | @@ | ||
2165 | - SDL_MOUSEBUTTONUP | ||
2166 | + SDL_EVENT_MOUSE_BUTTON_UP | ||
2167 | @@ | ||
2168 | @@ | ||
2169 | - SDL_MOUSEWHEEL | ||
2170 | + SDL_EVENT_MOUSE_WHEEL | ||
2171 | @@ | ||
2172 | @@ | ||
2173 | - SDL_JOYAXISMOTION | ||
2174 | + SDL_EVENT_JOYSTICK_AXIS_MOTION | ||
2175 | @@ | ||
2176 | @@ | ||
2177 | - SDL_JOYBALLMOTION | ||
2178 | + SDL_EVENT_JOYSTICK_BALL_MOTION | ||
2179 | @@ | ||
2180 | @@ | ||
2181 | - SDL_JOYHATMOTION | ||
2182 | + SDL_EVENT_JOYSTICK_HAT_MOTION | ||
2183 | @@ | ||
2184 | @@ | ||
2185 | - SDL_JOYBUTTONDOWN | ||
2186 | + SDL_EVENT_JOYSTICK_BUTTON_DOWN | ||
2187 | @@ | ||
2188 | @@ | ||
2189 | - SDL_JOYBUTTONUP | ||
2190 | + SDL_EVENT_JOYSTICK_BUTTON_UP | ||
2191 | @@ | ||
2192 | @@ | ||
2193 | - SDL_JOYDEVICEADDED | ||
2194 | + SDL_EVENT_JOYSTICK_ADDED | ||
2195 | @@ | ||
2196 | @@ | ||
2197 | - SDL_JOYDEVICEREMOVED | ||
2198 | + SDL_EVENT_JOYSTICK_REMOVED | ||
2199 | @@ | ||
2200 | @@ | ||
2201 | - SDL_JOYBATTERYUPDATED | ||
2202 | + SDL_EVENT_JOYSTICK_BATTERY_UPDATED | ||
2203 | @@ | ||
2204 | @@ | ||
2205 | - SDL_FINGERDOWN | ||
2206 | + SDL_EVENT_FINGER_DOWN | ||
2207 | @@ | ||
2208 | @@ | ||
2209 | - SDL_FINGERUP | ||
2210 | + SDL_EVENT_FINGER_UP | ||
2211 | @@ | ||
2212 | @@ | ||
2213 | - SDL_FINGERMOTION | ||
2214 | + SDL_EVENT_FINGER_MOTION | ||
2215 | @@ | ||
2216 | @@ | ||
2217 | - SDL_CLIPBOARDUPDATE | ||
2218 | + SDL_EVENT_CLIPBOARD_UPDATE | ||
2219 | @@ | ||
2220 | @@ | ||
2221 | - SDL_DROPFILE | ||
2222 | + SDL_EVENT_DROP_FILE | ||
2223 | @@ | ||
2224 | @@ | ||
2225 | - SDL_DROPTEXT | ||
2226 | + SDL_EVENT_DROP_TEXT | ||
2227 | @@ | ||
2228 | @@ | ||
2229 | - SDL_DROPBEGIN | ||
2230 | + SDL_EVENT_DROP_BEGIN | ||
2231 | @@ | ||
2232 | @@ | ||
2233 | - SDL_DROPCOMPLETE | ||
2234 | + SDL_EVENT_DROP_COMPLETE | ||
2235 | @@ | ||
2236 | @@ | ||
2237 | - SDL_AUDIODEVICEADDED | ||
2238 | + SDL_EVENT_AUDIO_DEVICE_ADDED | ||
2239 | @@ | ||
2240 | @@ | ||
2241 | - SDL_AUDIODEVICEREMOVED | ||
2242 | + SDL_EVENT_AUDIO_DEVICE_REMOVED | ||
2243 | @@ | ||
2244 | @@ | ||
2245 | - SDL_SENSORUPDATE | ||
2246 | + SDL_EVENT_SENSOR_UPDATE | ||
2247 | @@ | ||
2248 | @@ | ||
2249 | - SDL_RENDER_TARGETS_RESET | ||
2250 | + SDL_EVENT_RENDER_TARGETS_RESET | ||
2251 | @@ | ||
2252 | @@ | ||
2253 | - SDL_RENDER_DEVICE_RESET | ||
2254 | + SDL_EVENT_RENDER_DEVICE_RESET | ||
2255 | @@ | ||
2256 | @@ | ||
2257 | - SDL_POLLSENTINEL | ||
2258 | + SDL_EVENT_POLL_SENTINEL | ||
2259 | @@ | ||
2260 | @@ | ||
2261 | - SDL_USEREVENT | ||
2262 | + SDL_EVENT_USER | ||
2263 | @@ | ||
2264 | @@ | ||
2265 | - SDL_LASTEVENT | ||
2266 | + SDL_EVENT_LAST | ||
2267 | @@ | ||
2268 | @@ | ||
2269 | - SDL_WINDOW_INPUT_GRABBED | ||
2270 | + SDL_WINDOW_MOUSE_GRABBED | ||
2271 | @@ | ||
2272 | @@ | ||
2273 | - SDL_GetWindowDisplayIndex | ||
2274 | + SDL_GetDisplayForWindow | ||
2275 | (...) | ||
2276 | @@ | ||
2277 | @@ | ||
2278 | - SDL_SetWindowDisplayMode | ||
2279 | + SDL_SetWindowFullscreenMode | ||
2280 | (...) | ||
2281 | @@ | ||
2282 | @@ | ||
2283 | - SDL_GetWindowDisplayMode | ||
2284 | + SDL_GetWindowFullscreenMode | ||
2285 | (...) | ||
2286 | @@ | ||
2287 | @@ | ||
2288 | - SDL_GetClosestDisplayMode | ||
2289 | + SDL_GetClosestFullscreenDisplayMode | ||
2290 | (...) | ||
2291 | @@ | ||
2292 | @@ | ||
2293 | - SDL_GetRendererOutputSize | ||
2294 | + SDL_GetCurrentRenderOutputSize | ||
2295 | (...) | ||
2296 | @@ | ||
2297 | @@ | ||
2298 | - SDL_RenderWindowToLogical | ||
2299 | + SDL_RenderCoordinatesFromWindow | ||
2300 | (...) | ||
2301 | @@ | ||
2302 | @@ | ||
2303 | - SDL_RenderLogicalToWindow | ||
2304 | + SDL_RenderCoordinatesToWindow | ||
2305 | (...) | ||
2306 | @@ | ||
2307 | symbol SDL_ScaleModeNearest; | ||
2308 | @@ | ||
2309 | - SDL_ScaleModeNearest | ||
2310 | + SDL_SCALEMODE_NEAREST | ||
2311 | @@ | ||
2312 | symbol SDL_ScaleModeLinear; | ||
2313 | @@ | ||
2314 | - SDL_ScaleModeLinear | ||
2315 | + SDL_SCALEMODE_LINEAR | ||
2316 | @@ | ||
2317 | @@ | ||
2318 | - SDL_RenderCopy | ||
2319 | + SDL_RenderTexture | ||
2320 | (...) | ||
2321 | @@ | ||
2322 | @@ | ||
2323 | - SDL_RenderCopyEx | ||
2324 | + SDL_RenderTextureRotated | ||
2325 | (...) | ||
2326 | @@ | ||
2327 | SDL_Renderer *renderer; | ||
2328 | constant c1; | ||
2329 | constant c2; | ||
2330 | constant c3; | ||
2331 | constant c4; | ||
2332 | expression e1; | ||
2333 | expression e2; | ||
2334 | expression e3; | ||
2335 | expression e4; | ||
2336 | @@ | ||
2337 | - SDL_RenderDrawLine(renderer, | ||
2338 | + SDL_RenderLine(renderer, | ||
2339 | ( | ||
2340 | c1 | ||
2341 | | | ||
2342 | - e1 | ||
2343 | + (float)e1 | ||
2344 | ) | ||
2345 | , | ||
2346 | ( | ||
2347 | c2 | ||
2348 | | | ||
2349 | - e2 | ||
2350 | + (float)e2 | ||
2351 | ) | ||
2352 | , | ||
2353 | ( | ||
2354 | c3 | ||
2355 | | | ||
2356 | - e3 | ||
2357 | + (float)e3 | ||
2358 | ) | ||
2359 | , | ||
2360 | ( | ||
2361 | c4 | ||
2362 | | | ||
2363 | - e4 | ||
2364 | + (float)e4 | ||
2365 | ) | ||
2366 | ) | ||
2367 | @@ | ||
2368 | @@ | ||
2369 | - SDL_RenderDrawLines | ||
2370 | + SDL_RenderLines | ||
2371 | (...) | ||
2372 | @@ | ||
2373 | SDL_Renderer *renderer; | ||
2374 | constant c1; | ||
2375 | constant c2; | ||
2376 | expression e1; | ||
2377 | expression e2; | ||
2378 | @@ | ||
2379 | - SDL_RenderDrawPoint(renderer, | ||
2380 | + SDL_RenderPoint(renderer, | ||
2381 | ( | ||
2382 | c1 | ||
2383 | | | ||
2384 | - e1 | ||
2385 | + (float)e1 | ||
2386 | ) | ||
2387 | , | ||
2388 | ( | ||
2389 | c2 | ||
2390 | | | ||
2391 | - e2 | ||
2392 | + (float)e2 | ||
2393 | ) | ||
2394 | ) | ||
2395 | @@ | ||
2396 | @@ | ||
2397 | - SDL_RenderDrawPoints | ||
2398 | + SDL_RenderPoints | ||
2399 | (...) | ||
2400 | @@ | ||
2401 | @@ | ||
2402 | - SDL_RenderDrawRect | ||
2403 | + SDL_RenderRect | ||
2404 | (...) | ||
2405 | @@ | ||
2406 | @@ | ||
2407 | - SDL_RenderDrawRects | ||
2408 | + SDL_RenderRects | ||
2409 | (...) | ||
2410 | @@ | ||
2411 | @@ | ||
2412 | - SDL_GL_GetDrawableSize | ||
2413 | + SDL_GetWindowSizeInPixels | ||
2414 | (...) | ||
2415 | @@ | ||
2416 | @@ | ||
2417 | - SDL_Metal_GetDrawableSize | ||
2418 | + SDL_GetWindowSizeInPixels | ||
2419 | (...) | ||
2420 | @@ | ||
2421 | @@ | ||
2422 | - SDL_Vulkan_GetDrawableSize | ||
2423 | + SDL_GetWindowSizeInPixels | ||
2424 | (...) | ||
2425 | @@ | ||
2426 | @@ | ||
2427 | - SDL_IsScreenSaverEnabled | ||
2428 | + SDL_ScreenSaverEnabled | ||
2429 | (...) | ||
2430 | @@ | ||
2431 | SDL_Event e1; | ||
2432 | @@ | ||
2433 | - e1.caxis | ||
2434 | + e1.gaxis | ||
2435 | @@ | ||
2436 | SDL_Event *e1; | ||
2437 | @@ | ||
2438 | - e1->caxis | ||
2439 | + e1->gaxis | ||
2440 | @@ | ||
2441 | SDL_Event e1; | ||
2442 | @@ | ||
2443 | - e1.cbutton | ||
2444 | + e1.gbutton | ||
2445 | @@ | ||
2446 | SDL_Event *e1; | ||
2447 | @@ | ||
2448 | - e1->cbutton | ||
2449 | + e1->gbutton | ||
2450 | @@ | ||
2451 | SDL_Event e1; | ||
2452 | @@ | ||
2453 | - e1.cdevice | ||
2454 | + e1.gdevice | ||
2455 | @@ | ||
2456 | SDL_Event *e1; | ||
2457 | @@ | ||
2458 | - e1->cdevice | ||
2459 | + e1->gdevice | ||
2460 | @@ | ||
2461 | SDL_Event e1; | ||
2462 | @@ | ||
2463 | - e1.ctouchpad | ||
2464 | + e1.gtouchpad | ||
2465 | @@ | ||
2466 | SDL_Event *e1; | ||
2467 | @@ | ||
2468 | - e1->ctouchpad | ||
2469 | + e1->gtouchpad | ||
2470 | @@ | ||
2471 | SDL_Event e1; | ||
2472 | @@ | ||
2473 | - e1.csensor | ||
2474 | + e1.gsensor | ||
2475 | @@ | ||
2476 | SDL_Event *e1; | ||
2477 | @@ | ||
2478 | - e1->csensor | ||
2479 | + e1->gsensor | ||
2480 | @@ | ||
2481 | SDL_Event e1; | ||
2482 | @@ | ||
2483 | - e1.wheel.mouseX | ||
2484 | + e1.wheel.mouse_x | ||
2485 | @@ | ||
2486 | SDL_Event *e1; | ||
2487 | @@ | ||
2488 | - e1->wheel.mouseX | ||
2489 | + e1->wheel.mouse_x | ||
2490 | @@ | ||
2491 | SDL_MouseWheelEvent *e1; | ||
2492 | @@ | ||
2493 | - e1->mouseX | ||
2494 | + e1->mouse_x | ||
2495 | @@ | ||
2496 | SDL_Event e1; | ||
2497 | @@ | ||
2498 | - e1.wheel.mouseY | ||
2499 | + e1.wheel.mouse_y | ||
2500 | @@ | ||
2501 | SDL_Event *e1; | ||
2502 | @@ | ||
2503 | - e1->wheel.mouseY | ||
2504 | + e1->wheel.mouse_y | ||
2505 | @@ | ||
2506 | SDL_MouseWheelEvent *e1; | ||
2507 | @@ | ||
2508 | - e1->mouseY | ||
2509 | + e1->mouse_y | ||
2510 | @@ | ||
2511 | SDL_Event e1; | ||
2512 | @@ | ||
2513 | - e1.wheel.preciseX | ||
2514 | + e1.wheel.x | ||
2515 | @@ | ||
2516 | SDL_Event *e1; | ||
2517 | @@ | ||
2518 | - e1->wheel.preciseX | ||
2519 | + e1->wheel.x | ||
2520 | @@ | ||
2521 | SDL_MouseWheelEvent *e1; | ||
2522 | @@ | ||
2523 | - e1->preciseX | ||
2524 | + e1->x | ||
2525 | @@ | ||
2526 | SDL_Event e1; | ||
2527 | @@ | ||
2528 | - e1.wheel.preciseY | ||
2529 | + e1.wheel.y | ||
2530 | @@ | ||
2531 | SDL_Event *e1; | ||
2532 | @@ | ||
2533 | - e1->wheel.preciseY | ||
2534 | + e1->wheel.y | ||
2535 | @@ | ||
2536 | SDL_MouseWheelEvent *e1; | ||
2537 | @@ | ||
2538 | - e1->preciseY | ||
2539 | + e1->y | ||
2540 | @@ | ||
2541 | SDL_Event e1; | ||
2542 | @@ | ||
2543 | - e1.tfinger.touchId | ||
2544 | + e1.tfinger.touchID | ||
2545 | @@ | ||
2546 | SDL_Event *e1; | ||
2547 | @@ | ||
2548 | - e1->tfinger.touchId | ||
2549 | + e1->tfinger.touchID | ||
2550 | @@ | ||
2551 | SDL_TouchFingerEvent *e1; | ||
2552 | @@ | ||
2553 | - e1->touchId | ||
2554 | + e1->touchID | ||
2555 | @@ | ||
2556 | SDL_Event e1; | ||
2557 | @@ | ||
2558 | - e1.tfinger.fingerId | ||
2559 | + e1.tfinger.fingerID | ||
2560 | @@ | ||
2561 | SDL_Event *e1; | ||
2562 | @@ | ||
2563 | - e1->tfinger.fingerId | ||
2564 | + e1->tfinger.fingerID | ||
2565 | @@ | ||
2566 | SDL_TouchFingerEvent *e1; | ||
2567 | @@ | ||
2568 | - e1->fingerId | ||
2569 | + e1->fingerID | ||
2570 | @@ | ||
2571 | expression e1, e2, e3, e4; | ||
2572 | @@ | ||
2573 | - SDL_CreateWindow(e1, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, e2, e3, e4) | ||
2574 | + SDL_CreateWindow(e1, e2, e3, e4) | ||
2575 | @@ | ||
2576 | expression e1, e2, e3, e4; | ||
2577 | constant c1, c2; | ||
2578 | @@ | ||
2579 | - SDL_CreateShapedWindow(e1, c1, c2, e2, e3, e4) | ||
2580 | + SDL_CreateShapedWindow(e1, e2, e3, e4) | ||
2581 | @@ | ||
2582 | typedef SDL_atomic_t, SDL_AtomicInt; | ||
2583 | @@ | ||
2584 | - SDL_atomic_t | ||
2585 | + SDL_AtomicInt | ||
2586 | @@ | ||
2587 | @@ | ||
2588 | - SDL_SemWait | ||
2589 | + SDL_WaitSemaphore | ||
2590 | (...) | ||
2591 | @@ | ||
2592 | @@ | ||
2593 | - SDL_SemTryWait | ||
2594 | + SDL_TryWaitSemaphore | ||
2595 | (...) | ||
2596 | @@ | ||
2597 | @@ | ||
2598 | - SDL_SemWaitTimeout | ||
2599 | + SDL_WaitSemaphoreTimeout | ||
2600 | (...) | ||
2601 | @@ | ||
2602 | @@ | ||
2603 | - SDL_SemPost | ||
2604 | + SDL_SignalSemaphore | ||
2605 | (...) | ||
2606 | @@ | ||
2607 | @@ | ||
2608 | - SDL_SemValue | ||
2609 | + SDL_GetSemaphoreValue | ||
2610 | (...) | ||
2611 | @@ | ||
2612 | @@ | ||
2613 | - SDL_CreateCond | ||
2614 | + SDL_CreateCondition | ||
2615 | (...) | ||
2616 | @@ | ||
2617 | @@ | ||
2618 | - SDL_DestroyCond | ||
2619 | + SDL_DestroyCondition | ||
2620 | (...) | ||
2621 | @@ | ||
2622 | @@ | ||
2623 | - SDL_CondSignal | ||
2624 | + SDL_SignalCondition | ||
2625 | (...) | ||
2626 | @@ | ||
2627 | @@ | ||
2628 | - SDL_CondBroadcast | ||
2629 | + SDL_BroadcastCondition | ||
2630 | (...) | ||
2631 | @@ | ||
2632 | @@ | ||
2633 | - SDL_CondWait | ||
2634 | + SDL_WaitCondition | ||
2635 | (...) | ||
2636 | @@ | ||
2637 | @@ | ||
2638 | - SDL_CondWaitTimeout | ||
2639 | + SDL_WaitConditionTimeout | ||
2640 | (...) | ||
2641 | @@ | ||
2642 | typedef SDL_mutex, SDL_Mutex; | ||
2643 | @@ | ||
2644 | - SDL_mutex | ||
2645 | + SDL_Mutex | ||
2646 | @@ | ||
2647 | typedef SDL_sem, SDL_Semaphore; | ||
2648 | @@ | ||
2649 | - SDL_sem | ||
2650 | + SDL_Semaphore | ||
2651 | @@ | ||
2652 | typedef SDL_cond, SDL_Condition; | ||
2653 | @@ | ||
2654 | - SDL_cond | ||
2655 | + SDL_Condition | ||
2656 | @@ | ||
2657 | @@ | ||
2658 | - AUDIO_F32 | ||
2659 | + SDL_AUDIO_F32LE | ||
2660 | @@ | ||
2661 | @@ | ||
2662 | - AUDIO_F32LSB | ||
2663 | + SDL_AUDIO_F32LE | ||
2664 | @@ | ||
2665 | @@ | ||
2666 | - AUDIO_F32MSB | ||
2667 | + SDL_AUDIO_F32BE | ||
2668 | @@ | ||
2669 | @@ | ||
2670 | - AUDIO_F32SYS | ||
2671 | + SDL_AUDIO_F32 | ||
2672 | @@ | ||
2673 | @@ | ||
2674 | - AUDIO_S16 | ||
2675 | + SDL_AUDIO_S16LE | ||
2676 | @@ | ||
2677 | @@ | ||
2678 | - AUDIO_S16LSB | ||
2679 | + SDL_AUDIO_S16LE | ||
2680 | @@ | ||
2681 | @@ | ||
2682 | - AUDIO_S16MSB | ||
2683 | + SDL_AUDIO_S16BE | ||
2684 | @@ | ||
2685 | @@ | ||
2686 | - AUDIO_S16SYS | ||
2687 | + SDL_AUDIO_S16 | ||
2688 | @@ | ||
2689 | @@ | ||
2690 | - AUDIO_S32 | ||
2691 | + SDL_AUDIO_S32LE | ||
2692 | @@ | ||
2693 | @@ | ||
2694 | - AUDIO_S32LSB | ||
2695 | + SDL_AUDIO_S32LE | ||
2696 | @@ | ||
2697 | @@ | ||
2698 | - AUDIO_S32MSB | ||
2699 | + SDL_AUDIO_S32BE | ||
2700 | @@ | ||
2701 | @@ | ||
2702 | - AUDIO_S32SYS | ||
2703 | + SDL_AUDIO_S32 | ||
2704 | @@ | ||
2705 | @@ | ||
2706 | - AUDIO_S8 | ||
2707 | + SDL_AUDIO_S8 | ||
2708 | @@ | ||
2709 | @@ | ||
2710 | - AUDIO_U8 | ||
2711 | + SDL_AUDIO_U8 | ||
2712 | @@ | ||
2713 | @@ | ||
2714 | - SDL_WINDOW_ALLOW_HIGHDPI | ||
2715 | + SDL_WINDOW_HIGH_PIXEL_DENSITY | ||
2716 | @@ | ||
2717 | @@ | ||
2718 | - SDL_TLSGet | ||
2719 | + SDL_GetTLS | ||
2720 | (...) | ||
2721 | @@ | ||
2722 | @@ | ||
2723 | - SDL_TLSSet | ||
2724 | + SDL_SetTLS | ||
2725 | (...) | ||
2726 | @@ | ||
2727 | @@ | ||
2728 | - SDL_TLSCleanup | ||
2729 | + SDL_CleanupTLS | ||
2730 | (...) | ||
2731 | @@ | ||
2732 | @@ | ||
2733 | - SDL_GetDisplayOrientation | ||
2734 | + SDL_GetDisplayCurrentOrientation | ||
2735 | (...) | ||
2736 | @@ | ||
2737 | @@ | ||
2738 | - SDL_WINDOW_SKIP_TASKBAR | ||
2739 | + SDL_WINDOW_UTILITY | ||
2740 | @@ | ||
2741 | @@ | ||
2742 | - SDL_PIXELFORMAT_BGR444 | ||
2743 | + SDL_PIXELFORMAT_XBGR4444 | ||
2744 | @@ | ||
2745 | @@ | ||
2746 | - SDL_PIXELFORMAT_BGR555 | ||
2747 | + SDL_PIXELFORMAT_XBGR1555 | ||
2748 | @@ | ||
2749 | @@ | ||
2750 | - SDL_PIXELFORMAT_BGR888 | ||
2751 | + SDL_PIXELFORMAT_XBGR8888 | ||
2752 | @@ | ||
2753 | @@ | ||
2754 | - SDL_PIXELFORMAT_RGB444 | ||
2755 | + SDL_PIXELFORMAT_XRGB4444 | ||
2756 | @@ | ||
2757 | @@ | ||
2758 | - SDL_PIXELFORMAT_RGB555 | ||
2759 | + SDL_PIXELFORMAT_XRGB1555 | ||
2760 | @@ | ||
2761 | @@ | ||
2762 | - SDL_PIXELFORMAT_RGB888 | ||
2763 | + SDL_PIXELFORMAT_XRGB8888 | ||
2764 | @@ | ||
2765 | @@ | ||
2766 | - SDL_strtokr | ||
2767 | + SDL_strtok_r | ||
2768 | (...) | ||
2769 | @@ | ||
2770 | @@ | ||
2771 | - SDL_ReadLE16 | ||
2772 | + SDL_ReadU16LE | ||
2773 | (...) | ||
2774 | @@ | ||
2775 | @@ | ||
2776 | - SDL_ReadLE32 | ||
2777 | + SDL_ReadU32LE | ||
2778 | (...) | ||
2779 | @@ | ||
2780 | @@ | ||
2781 | - SDL_ReadBE32 | ||
2782 | + SDL_ReadU32BE | ||
2783 | (...) | ||
2784 | @@ | ||
2785 | @@ | ||
2786 | - SDL_ReadBE16 | ||
2787 | + SDL_ReadU16BE | ||
2788 | (...) | ||
2789 | @@ | ||
2790 | @@ | ||
2791 | - SDL_ReadLE64 | ||
2792 | + SDL_ReadU64LE | ||
2793 | (...) | ||
2794 | @@ | ||
2795 | @@ | ||
2796 | - SDL_ReadBE64 | ||
2797 | + SDL_ReadU64BE | ||
2798 | (...) | ||
2799 | @@ | ||
2800 | @@ | ||
2801 | - SDL_WriteLE16 | ||
2802 | + SDL_WriteU16LE | ||
2803 | (...) | ||
2804 | @@ | ||
2805 | @@ | ||
2806 | - SDL_WriteBE16 | ||
2807 | + SDL_WriteU16BE | ||
2808 | (...) | ||
2809 | @@ | ||
2810 | @@ | ||
2811 | - SDL_WriteLE32 | ||
2812 | + SDL_WriteU32LE | ||
2813 | (...) | ||
2814 | @@ | ||
2815 | @@ | ||
2816 | - SDL_WriteBE32 | ||
2817 | + SDL_WriteU32BE | ||
2818 | (...) | ||
2819 | @@ | ||
2820 | @@ | ||
2821 | - SDL_WriteLE64 | ||
2822 | + SDL_WriteU64LE | ||
2823 | (...) | ||
2824 | @@ | ||
2825 | @@ | ||
2826 | - SDL_WriteBE64 | ||
2827 | + SDL_WriteU64BE | ||
2828 | (...) | ||
2829 | @@ | ||
2830 | expression e, n; | ||
2831 | @@ | ||
2832 | - SDL_GetWindowData(e, n) | ||
2833 | + SDL_GetProperty(SDL_GetWindowProperties(e), n) | ||
2834 | @@ | ||
2835 | expression e, n, v; | ||
2836 | @@ | ||
2837 | - SDL_SetWindowData(e, n, v) | ||
2838 | + SDL_SetProperty(SDL_GetWindowProperties(e), n, v, NULL, NULL) | ||
2839 | @@ | ||
2840 | expression w, i, s; | ||
2841 | @@ | ||
2842 | - SDL_Vulkan_CreateSurface(w, i, s) | ||
2843 | + SDL_Vulkan_CreateSurface(w, i, NULL, s) | ||
2844 | @@ | ||
2845 | @@ | ||
2846 | - SDL_RenderFlush | ||
2847 | + SDL_FlushRenderer | ||
2848 | (...) | ||
2849 | @@ | ||
2850 | @@ | ||
2851 | - SDL_CONTROLLERSTEAMHANDLEUPDATED | ||
2852 | + SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED | ||
2853 | @@ | ||
2854 | @@ | ||
2855 | - SDL_GameControllerGetSteamHandle | ||
2856 | + SDL_GetGamepadSteamHandle | ||
2857 | (...) | ||
2858 | @@ | ||
2859 | expression e1, e2, e3, e4; | ||
2860 | @@ | ||
2861 | - SDL_SoftStretch(e1, e2, e3, e4) | ||
2862 | + SDL_SoftStretch(e1, e2, e3, e4, SDL_SCALEMODE_NEAREST) | ||
2863 | @@ | ||
2864 | expression e1, e2, e3, e4; | ||
2865 | @@ | ||
2866 | - SDL_SoftStretchLinear(e1, e2, e3, e4) | ||
2867 | + SDL_SoftStretch(e1, e2, e3, e4, SDL_SCALEMODE_LINEAR) | ||
2868 | @@ | ||
2869 | @@ | ||
2870 | - SDL_HapticClose | ||
2871 | + SDL_CloseHaptic | ||
2872 | (...) | ||
2873 | @@ | ||
2874 | @@ | ||
2875 | - SDL_HapticOpen | ||
2876 | + SDL_OpenHaptic | ||
2877 | (...) | ||
2878 | @@ | ||
2879 | @@ | ||
2880 | - SDL_HapticOpenFromMouse | ||
2881 | + SDL_OpenHapticFromMouse | ||
2882 | (...) | ||
2883 | @@ | ||
2884 | @@ | ||
2885 | - SDL_HapticOpenFromJoystick | ||
2886 | + SDL_OpenHapticFromJoystick | ||
2887 | (...) | ||
2888 | @@ | ||
2889 | @@ | ||
2890 | - SDL_MouseIsHaptic | ||
2891 | + SDL_IsMouseHaptic | ||
2892 | (...) | ||
2893 | @@ | ||
2894 | @@ | ||
2895 | - SDL_JoystickIsHaptic | ||
2896 | + SDL_IsJoystickHaptic | ||
2897 | (...) | ||
2898 | @@ | ||
2899 | @@ | ||
2900 | - SDL_HapticNumEffects | ||
2901 | + SDL_GetMaxHapticEffects | ||
2902 | (...) | ||
2903 | @@ | ||
2904 | @@ | ||
2905 | - SDL_HapticNumEffectsPlaying | ||
2906 | + SDL_GetMaxHapticEffectsPlaying | ||
2907 | (...) | ||
2908 | @@ | ||
2909 | @@ | ||
2910 | - SDL_HapticQuery | ||
2911 | + SDL_GetHapticFeatures | ||
2912 | (...) | ||
2913 | @@ | ||
2914 | @@ | ||
2915 | - SDL_HapticNumAxes | ||
2916 | + SDL_GetNumHapticAxes | ||
2917 | (...) | ||
2918 | @@ | ||
2919 | @@ | ||
2920 | - SDL_HapticNewEffect | ||
2921 | + SDL_CreateHapticEffect | ||
2922 | (...) | ||
2923 | @@ | ||
2924 | @@ | ||
2925 | - SDL_HapticUpdateEffect | ||
2926 | + SDL_UpdateHapticEffect | ||
2927 | (...) | ||
2928 | @@ | ||
2929 | @@ | ||
2930 | - SDL_HapticRunEffect | ||
2931 | + SDL_RunHapticEffect | ||
2932 | (...) | ||
2933 | @@ | ||
2934 | @@ | ||
2935 | - SDL_HapticStopEffect | ||
2936 | + SDL_StopHapticEffect | ||
2937 | (...) | ||
2938 | @@ | ||
2939 | @@ | ||
2940 | - SDL_HapticDestroyEffect | ||
2941 | + SDL_DestroyHapticEffect | ||
2942 | (...) | ||
2943 | @@ | ||
2944 | @@ | ||
2945 | - SDL_HapticGetEffectStatus | ||
2946 | + SDL_GetHapticEffectStatus | ||
2947 | (...) | ||
2948 | @@ | ||
2949 | @@ | ||
2950 | - SDL_HapticSetGain | ||
2951 | + SDL_SetHapticGain | ||
2952 | (...) | ||
2953 | @@ | ||
2954 | @@ | ||
2955 | - SDL_HapticSetAutocenter | ||
2956 | + SDL_SetHapticAutocenter | ||
2957 | (...) | ||
2958 | @@ | ||
2959 | @@ | ||
2960 | - SDL_HapticPause | ||
2961 | + SDL_PauseHaptic | ||
2962 | (...) | ||
2963 | @@ | ||
2964 | @@ | ||
2965 | - SDL_HapticUnpause | ||
2966 | + SDL_ResumeHaptic | ||
2967 | (...) | ||
2968 | @@ | ||
2969 | @@ | ||
2970 | - SDL_HapticStopAll | ||
2971 | + SDL_StopHapticEffects | ||
2972 | (...) | ||
2973 | @@ | ||
2974 | @@ | ||
2975 | - SDL_HapticRumbleInit | ||
2976 | + SDL_InitHapticRumble | ||
2977 | (...) | ||
2978 | @@ | ||
2979 | @@ | ||
2980 | - SDL_HapticRumblePlay | ||
2981 | + SDL_PlayHapticRumble | ||
2982 | (...) | ||
2983 | @@ | ||
2984 | @@ | ||
2985 | - SDL_HapticRumbleStop | ||
2986 | + SDL_StopHapticRumble | ||
2987 | (...) | ||
2988 | @@ | ||
2989 | @@ | ||
2990 | - SDL_AtomicTryLock | ||
2991 | + SDL_TryLockSpinlock | ||
2992 | (...) | ||
2993 | @@ | ||
2994 | @@ | ||
2995 | - SDL_AtomicLock | ||
2996 | + SDL_LockSpinlock | ||
2997 | (...) | ||
2998 | @@ | ||
2999 | @@ | ||
3000 | - SDL_AtomicUnlock | ||
3001 | + SDL_UnlockSpinlock | ||
3002 | (...) | ||
3003 | @@ | ||
3004 | @@ | ||
3005 | - SDL_AtomicCAS | ||
3006 | + SDL_CompareAndSwapAtomicInt | ||
3007 | (...) | ||
3008 | @@ | ||
3009 | @@ | ||
3010 | - SDL_AtomicSet | ||
3011 | + SDL_SetAtomicInt | ||
3012 | (...) | ||
3013 | @@ | ||
3014 | @@ | ||
3015 | - SDL_AtomicGet | ||
3016 | + SDL_GetAtomicInt | ||
3017 | (...) | ||
3018 | @@ | ||
3019 | @@ | ||
3020 | - SDL_AtomicAdd | ||
3021 | + SDL_AddAtomicInt | ||
3022 | (...) | ||
3023 | @@ | ||
3024 | @@ | ||
3025 | - SDL_AtomicCASPtr | ||
3026 | + SDL_CompareAndSwapAtomicPointer | ||
3027 | (...) | ||
3028 | @@ | ||
3029 | @@ | ||
3030 | - SDL_AtomicSetPtr | ||
3031 | + SDL_SetAtomicPointer | ||
3032 | (...) | ||
3033 | @@ | ||
3034 | @@ | ||
3035 | - SDL_AtomicGetPtr | ||
3036 | + SDL_GetAtomicPointer | ||
3037 | (...) | ||
3038 | @@ | ||
3039 | @@ | ||
3040 | - SDL_ThreadID | ||
3041 | + SDL_GetCurrentThreadID | ||
3042 | (...) | ||
3043 | @@ | ||
3044 | @@ | ||
3045 | - SDL_threadID | ||
3046 | + SDL_ThreadID | ||
3047 | (...) | ||
3048 | @@ | ||
3049 | @@ | ||
3050 | - SDL_HasWindowSurface | ||
3051 | + SDL_WindowHasSurface | ||
3052 | (...) | ||
3053 | @@ | ||
3054 | SDL_PixelFormat e1; | ||
3055 | @@ | ||
3056 | - e1.BitsPerPixel | ||
3057 | + e1.bits_per_pixel | ||
3058 | @@ | ||
3059 | SDL_PixelFormat *e1; | ||
3060 | @@ | ||
3061 | - e1->BitsPerPixel | ||
3062 | + e1->bits_per_pixel | ||
3063 | @@ | ||
3064 | SDL_PixelFormat e1; | ||
3065 | @@ | ||
3066 | - e1.BytesPerPixel | ||
3067 | + e1.bytes_per_pixel | ||
3068 | @@ | ||
3069 | SDL_PixelFormat *e1; | ||
3070 | @@ | ||
3071 | - e1->BytesPerPixel | ||
3072 | + e1->bytes_per_pixel | ||
3073 | @@ | ||
3074 | SDL_MessageBoxButtonData e1; | ||
3075 | @@ | ||
3076 | - e1.buttonid | ||
3077 | + e1.buttonID | ||
3078 | @@ | ||
3079 | SDL_MessageBoxButtonData *e1; | ||
3080 | @@ | ||
3081 | - e1->buttonid | ||
3082 | + e1->buttonID | ||
3083 | @@ | ||
3084 | SDL_GamepadBinding e1; | ||
3085 | @@ | ||
3086 | - e1.inputType | ||
3087 | + e1.input_type | ||
3088 | @@ | ||
3089 | SDL_GamepadBinding *e1; | ||
3090 | @@ | ||
3091 | - e1->inputType | ||
3092 | + e1->input_type | ||
3093 | @@ | ||
3094 | SDL_GamepadBinding e1; | ||
3095 | @@ | ||
3096 | - e1.outputType | ||
3097 | + e1.output_type | ||
3098 | @@ | ||
3099 | SDL_GamepadBinding *e1; | ||
3100 | @@ | ||
3101 | - e1->outputType | ||
3102 | + e1->output_type | ||
3103 | @@ | ||
3104 | @@ | ||
3105 | - SDL_HINT_ALLOW_TOPMOST | ||
3106 | + SDL_HINT_WINDOW_ALLOW_TOPMOST | ||
3107 | @@ | ||
3108 | @@ | ||
3109 | - SDL_HINT_DIRECTINPUT_ENABLED | ||
3110 | + SDL_HINT_JOYSTICK_DIRECTINPUT | ||
3111 | @@ | ||
3112 | @@ | ||
3113 | - SDL_HINT_GDK_TEXTINPUT_DEFAULT | ||
3114 | + SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT | ||
3115 | @@ | ||
3116 | @@ | ||
3117 | - SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE | ||
3118 | + SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE | ||
3119 | @@ | ||
3120 | @@ | ||
3121 | - SDL_HINT_LINUX_DIGITAL_HATS | ||
3122 | + SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS | ||
3123 | @@ | ||
3124 | @@ | ||
3125 | - SDL_HINT_LINUX_HAT_DEADZONES | ||
3126 | + SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES | ||
3127 | @@ | ||
3128 | @@ | ||
3129 | - SDL_HINT_LINUX_JOYSTICK_CLASSIC | ||
3130 | + SDL_HINT_JOYSTICK_LINUX_CLASSIC | ||
3131 | @@ | ||
3132 | @@ | ||
3133 | - SDL_HINT_LINUX_JOYSTICK_DEADZONES | ||
3134 | + SDL_HINT_JOYSTICK_LINUX_DEADZONES | ||
3135 | @@ | ||
3136 | @@ | ||
3137 | - SDL_HINT_PS2_DYNAMIC_VSYNC | ||
3138 | + SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC | ||
3139 | @@ | ||
3140 | @@ | ||
3141 | - SDL_JoystickNumBalls | ||
3142 | + SDL_GetNumJoystickBalls | ||
3143 | (...) | ||
3144 | @@ | ||
3145 | @@ | ||
3146 | - SDL_JoystickGetBall | ||
3147 | + SDL_GetJoystickBall | ||
3148 | (...) | ||
3149 | @@ | ||
3150 | @@ | ||
3151 | - SDL_RWclose | ||
3152 | + SDL_CloseIO | ||
3153 | (...) | ||
3154 | @@ | ||
3155 | @@ | ||
3156 | - SDL_RWread | ||
3157 | + SDL_ReadIO | ||
3158 | (...) | ||
3159 | @@ | ||
3160 | @@ | ||
3161 | - SDL_RWwrite | ||
3162 | + SDL_WriteIO | ||
3163 | (...) | ||
3164 | @@ | ||
3165 | @@ | ||
3166 | - SDL_RWtell | ||
3167 | + SDL_TellIO | ||
3168 | (...) | ||
3169 | @@ | ||
3170 | @@ | ||
3171 | - SDL_RWsize | ||
3172 | + SDL_SizeIO | ||
3173 | (...) | ||
3174 | @@ | ||
3175 | @@ | ||
3176 | - SDL_RWseek | ||
3177 | + SDL_SeekIO | ||
3178 | (...) | ||
3179 | @@ | ||
3180 | @@ | ||
3181 | - SDL_LoadBMP_RW | ||
3182 | + SDL_LoadBMP_IO | ||
3183 | (...) | ||
3184 | @@ | ||
3185 | @@ | ||
3186 | - SDL_LoadWAV_RW | ||
3187 | + SDL_LoadWAV_IO | ||
3188 | (...) | ||
3189 | @@ | ||
3190 | @@ | ||
3191 | - SDL_SaveBMP_RW | ||
3192 | + SDL_SaveBMP_IO | ||
3193 | (...) | ||
3194 | @@ | ||
3195 | @@ | ||
3196 | - SDL_RWFromFile | ||
3197 | + SDL_IOFromFile | ||
3198 | (...) | ||
3199 | @@ | ||
3200 | @@ | ||
3201 | - SDL_RWFromMem | ||
3202 | + SDL_IOFromMem | ||
3203 | (...) | ||
3204 | @@ | ||
3205 | @@ | ||
3206 | - SDL_RWFromConstMem | ||
3207 | + SDL_IOFromConstMem | ||
3208 | (...) | ||
3209 | @@ | ||
3210 | typedef SDL_RWops, SDL_IOStream; | ||
3211 | @@ | ||
3212 | - SDL_RWops | ||
3213 | + SDL_IOStream | ||
3214 | @@ | ||
3215 | @@ | ||
3216 | - SDL_LogGetOutputFunction | ||
3217 | + SDL_GetLogOutputFunction | ||
3218 | (...) | ||
3219 | @@ | ||
3220 | @@ | ||
3221 | - SDL_LogSetOutputFunction | ||
3222 | + SDL_SetLogOutputFunction | ||
3223 | (...) | ||
3224 | @@ | ||
3225 | typedef SDL_eventaction, SDL_EventAction; | ||
3226 | @@ | ||
3227 | - SDL_eventaction | ||
3228 | + SDL_EventAction | ||
3229 | @@ | ||
3230 | typedef SDL_RendererFlip, SDL_FlipMode; | ||
3231 | @@ | ||
3232 | - SDL_RendererFlip | ||
3233 | + SDL_FlipMode | ||
3234 | @@ | ||
3235 | typedef SDL_Colour, SDL_Color; | ||
3236 | @@ | ||
3237 | - SDL_Colour | ||
3238 | + SDL_Color | ||
3239 | @@ | ||
3240 | @@ | ||
3241 | - SDL_iPhoneSetAnimationCallback | ||
3242 | + SDL_SetiOSAnimationCallback | ||
3243 | (...) | ||
3244 | @@ | ||
3245 | @@ | ||
3246 | - SDL_iPhoneSetEventPump | ||
3247 | + SDL_SetiOSEventPump | ||
3248 | (...) | ||
3249 | @@ | ||
3250 | @@ | ||
3251 | - SDL_COMPILEDVERSION | ||
3252 | + SDL_VERSION | ||
3253 | @@ | ||
3254 | @@ | ||
3255 | - SDL_PATCHLEVEL | ||
3256 | + SDL_MICRO_VERSION | ||
3257 | @@ | ||
3258 | @@ | ||
3259 | - SDL_TABLESIZE | ||
3260 | + SDL_arraysize | ||
3261 | @@ | ||
3262 | @@ | ||
3263 | - SDLK_QUOTE | ||
3264 | + SDLK_APOSTROPHE | ||
3265 | @@ | ||
3266 | @@ | ||
3267 | - SDLK_BACKQUOTE | ||
3268 | + SDLK_GRAVE | ||
3269 | @@ | ||
3270 | @@ | ||
3271 | - SDLK_QUOTEDBL | ||
3272 | + SDLK_DBLAPOSTROPHE | ||
3273 | @@ | ||
3274 | @@ | ||
3275 | - SDL_LogSetAllPriority | ||
3276 | + SDL_SetLogPriorities | ||
3277 | (...) | ||
3278 | @@ | ||
3279 | @@ | ||
3280 | - SDL_LogSetPriority | ||
3281 | + SDL_SetLogPriority | ||
3282 | (...) | ||
3283 | @@ | ||
3284 | @@ | ||
3285 | - SDL_LogGetPriority | ||
3286 | + SDL_GetLogPriority | ||
3287 | (...) | ||
3288 | @@ | ||
3289 | @@ | ||
3290 | - SDL_LogResetPriorities | ||
3291 | + SDL_ResetLogPriorities | ||
3292 | (...) | ||
3293 | @@ | ||
3294 | @@ | ||
3295 | - SDL_SIMDGetAlignment | ||
3296 | + SDL_GetSIMDAlignment | ||
3297 | (...) | ||
3298 | @@ | ||
3299 | @@ | ||
3300 | - SDL_MixAudioFormat | ||
3301 | + SDL_MixAudio | ||
3302 | (...) | ||
3303 | @@ | ||
3304 | @@ | ||
3305 | - SDL_BlitScaled | ||
3306 | + SDL_BlitSurfaceScaled | ||
3307 | (...) | ||
3308 | @@ | ||
3309 | @@ | ||
3310 | - SDL_SYSTEM_CURSOR_ARROW | ||
3311 | + SDL_SYSTEM_CURSOR_DEFAULT | ||
3312 | @@ | ||
3313 | @@ | ||
3314 | - SDL_SYSTEM_CURSOR_IBEAM | ||
3315 | + SDL_SYSTEM_CURSOR_TEXT | ||
3316 | @@ | ||
3317 | @@ | ||
3318 | - SDL_SYSTEM_CURSOR_WAITARROW | ||
3319 | + SDL_SYSTEM_CURSOR_PROGRESS | ||
3320 | @@ | ||
3321 | @@ | ||
3322 | - SDL_SYSTEM_CURSOR_SIZENWSE | ||
3323 | + SDL_SYSTEM_CURSOR_NWSE_RESIZE | ||
3324 | @@ | ||
3325 | @@ | ||
3326 | - SDL_SYSTEM_CURSOR_SIZENESW | ||
3327 | + SDL_SYSTEM_CURSOR_NESW_RESIZE | ||
3328 | @@ | ||
3329 | @@ | ||
3330 | - SDL_SYSTEM_CURSOR_SIZEWE | ||
3331 | + SDL_SYSTEM_CURSOR_EW_RESIZE | ||
3332 | @@ | ||
3333 | @@ | ||
3334 | - SDL_SYSTEM_CURSOR_SIZENS | ||
3335 | + SDL_SYSTEM_CURSOR_NS_RESIZE | ||
3336 | @@ | ||
3337 | @@ | ||
3338 | - SDL_SYSTEM_CURSOR_SIZEALL | ||
3339 | + SDL_SYSTEM_CURSOR_MOVE | ||
3340 | @@ | ||
3341 | @@ | ||
3342 | - SDL_SYSTEM_CURSOR_NO | ||
3343 | + SDL_SYSTEM_CURSOR_NOT_ALLOWED | ||
3344 | @@ | ||
3345 | @@ | ||
3346 | - SDL_SYSTEM_CURSOR_HAND | ||
3347 | + SDL_SYSTEM_CURSOR_POINTER | ||
3348 | @@ | ||
3349 | @@ | ||
3350 | - SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT | ||
3351 | + SDL_SYSTEM_CURSOR_NW_RESIZE | ||
3352 | @@ | ||
3353 | @@ | ||
3354 | - SDL_SYSTEM_CURSOR_WINDOW_TOP | ||
3355 | + SDL_SYSTEM_CURSOR_N_RESIZE | ||
3356 | @@ | ||
3357 | @@ | ||
3358 | - SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT | ||
3359 | + SDL_SYSTEM_CURSOR_NE_RESIZE | ||
3360 | @@ | ||
3361 | @@ | ||
3362 | - SDL_SYSTEM_CURSOR_WINDOW_RIGHT | ||
3363 | + SDL_SYSTEM_CURSOR_E_RESIZE | ||
3364 | @@ | ||
3365 | @@ | ||
3366 | - SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT | ||
3367 | + SDL_SYSTEM_CURSOR_SE_RESIZE | ||
3368 | @@ | ||
3369 | @@ | ||
3370 | - SDL_SYSTEM_CURSOR_WINDOW_BOTTOM | ||
3371 | + SDL_SYSTEM_CURSOR_S_RESIZE | ||
3372 | @@ | ||
3373 | @@ | ||
3374 | - SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT | ||
3375 | + SDL_SYSTEM_CURSOR_SW_RESIZE | ||
3376 | @@ | ||
3377 | @@ | ||
3378 | - SDL_SYSTEM_CURSOR_WINDOW_LEFT | ||
3379 | + SDL_SYSTEM_CURSOR_W_RESIZE | ||
3380 | @@ | ||
3381 | @@ | ||
3382 | - SDL_SwapLE16 | ||
3383 | + SDL_Swap16LE | ||
3384 | (...) | ||
3385 | @@ | ||
3386 | @@ | ||
3387 | - SDL_SwapLE32 | ||
3388 | + SDL_Swap32LE | ||
3389 | (...) | ||
3390 | @@ | ||
3391 | @@ | ||
3392 | - SDL_SwapBE16 | ||
3393 | + SDL_Swap16BE | ||
3394 | (...) | ||
3395 | @@ | ||
3396 | @@ | ||
3397 | - SDL_SwapBE32 | ||
3398 | + SDL_Swap32BE | ||
3399 | (...) | ||
3400 | @@ | ||
3401 | @@ | ||
3402 | - SDL_SwapLE64 | ||
3403 | + SDL_Swap64LE | ||
3404 | (...) | ||
3405 | @@ | ||
3406 | @@ | ||
3407 | - SDL_SwapBE64 | ||
3408 | + SDL_Swap64BE | ||
3409 | (...) | ||
3410 | @@ | ||
3411 | @@ | ||
3412 | - SDL_SCANCODE_AUDIOMUTE | ||
3413 | + SDL_SCANCODE_MUTE | ||
3414 | @@ | ||
3415 | @@ | ||
3416 | - SDLK_AUDIOMUTE | ||
3417 | + SDLK_MUTE | ||
3418 | @@ | ||
3419 | @@ | ||
3420 | - SDL_SCANCODE_EJECT | ||
3421 | + SDL_SCANCODE_MEDIA_EJECT | ||
3422 | @@ | ||
3423 | @@ | ||
3424 | - SDLK_EJECT | ||
3425 | + SDLK_MEDIA_EJECT | ||
3426 | @@ | ||
3427 | @@ | ||
3428 | - SDL_SCANCODE_AUDIONEXT | ||
3429 | + SDL_SCANCODE_MEDIA_NEXT_TRACK | ||
3430 | @@ | ||
3431 | @@ | ||
3432 | - SDLK_AUDIONEXT | ||
3433 | + SDLK_MEDIA_NEXT_TRACK | ||
3434 | @@ | ||
3435 | @@ | ||
3436 | - SDL_SCANCODE_AUDIOPREV | ||
3437 | + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK | ||
3438 | @@ | ||
3439 | @@ | ||
3440 | - SDLK_AUDIOPREV | ||
3441 | + SDLK_MEDIA_PREVIOUS_TRACK | ||
3442 | @@ | ||
3443 | @@ | ||
3444 | - SDL_SCANCODE_AUDIOSTOP | ||
3445 | + SDL_SCANCODE_MEDIA_STOP | ||
3446 | @@ | ||
3447 | @@ | ||
3448 | - SDLK_AUDIOSTOP | ||
3449 | + SDLK_MEDIA_STOP | ||
3450 | @@ | ||
3451 | @@ | ||
3452 | - SDL_SCANCODE_AUDIOPLAY | ||
3453 | + SDL_SCANCODE_MEDIA_PLAY | ||
3454 | @@ | ||
3455 | @@ | ||
3456 | - SDLK_AUDIOPLAY | ||
3457 | + SDLK_MEDIA_PLAY | ||
3458 | @@ | ||
3459 | @@ | ||
3460 | - SDL_SCANCODE_AUDIOREWIND | ||
3461 | + SDL_SCANCODE_MEDIA_REWIND | ||
3462 | @@ | ||
3463 | @@ | ||
3464 | - SDLK_AUDIOREWIND | ||
3465 | + SDLK_MEDIA_REWIND | ||
3466 | @@ | ||
3467 | @@ | ||
3468 | - SDL_SCANCODE_AUDIOFASTFORWARD | ||
3469 | + SDL_SCANCODE_MEDIA_FAST_FORWARD | ||
3470 | @@ | ||
3471 | @@ | ||
3472 | - SDLK_AUDIOFASTFORWARD | ||
3473 | + SDLK_MEDIA_FAST_FORWARD | ||
3474 | @@ | ||
3475 | @@ | ||
3476 | - SDL_SCANCODE_MEDIASELECT | ||
3477 | + SDL_SCANCODE_MEDIA_SELECT | ||
3478 | @@ | ||
3479 | @@ | ||
3480 | - SDLK_MEDIASELECT | ||
3481 | + SDLK_MEDIA_SELECT | ||
3482 | @@ | ||
3483 | @@ | ||
3484 | - SDLK_a | ||
3485 | + SDLK_A | ||
3486 | @@ | ||
3487 | @@ | ||
3488 | - SDLK_b | ||
3489 | + SDLK_B | ||
3490 | @@ | ||
3491 | @@ | ||
3492 | - SDLK_c | ||
3493 | + SDLK_C | ||
3494 | @@ | ||
3495 | @@ | ||
3496 | - SDLK_d | ||
3497 | + SDLK_D | ||
3498 | @@ | ||
3499 | @@ | ||
3500 | - SDLK_e | ||
3501 | + SDLK_E | ||
3502 | @@ | ||
3503 | @@ | ||
3504 | - SDLK_f | ||
3505 | + SDLK_F | ||
3506 | @@ | ||
3507 | @@ | ||
3508 | - SDLK_g | ||
3509 | + SDLK_G | ||
3510 | @@ | ||
3511 | @@ | ||
3512 | - SDLK_h | ||
3513 | + SDLK_H | ||
3514 | @@ | ||
3515 | @@ | ||
3516 | - SDLK_i | ||
3517 | + SDLK_I | ||
3518 | @@ | ||
3519 | @@ | ||
3520 | - SDLK_j | ||
3521 | + SDLK_J | ||
3522 | @@ | ||
3523 | @@ | ||
3524 | - SDLK_k | ||
3525 | + SDLK_K | ||
3526 | @@ | ||
3527 | @@ | ||
3528 | - SDLK_l | ||
3529 | + SDLK_L | ||
3530 | @@ | ||
3531 | @@ | ||
3532 | - SDLK_m | ||
3533 | + SDLK_M | ||
3534 | @@ | ||
3535 | @@ | ||
3536 | - SDLK_n | ||
3537 | + SDLK_N | ||
3538 | @@ | ||
3539 | @@ | ||
3540 | - SDLK_o | ||
3541 | + SDLK_O | ||
3542 | @@ | ||
3543 | @@ | ||
3544 | - SDLK_p | ||
3545 | + SDLK_P | ||
3546 | @@ | ||
3547 | @@ | ||
3548 | - SDLK_q | ||
3549 | + SDLK_Q | ||
3550 | @@ | ||
3551 | @@ | ||
3552 | - SDLK_r | ||
3553 | + SDLK_R | ||
3554 | @@ | ||
3555 | @@ | ||
3556 | - SDLK_s | ||
3557 | + SDLK_S | ||
3558 | @@ | ||
3559 | @@ | ||
3560 | - SDLK_t | ||
3561 | + SDLK_T | ||
3562 | @@ | ||
3563 | @@ | ||
3564 | - SDLK_u | ||
3565 | + SDLK_U | ||
3566 | @@ | ||
3567 | @@ | ||
3568 | - SDLK_v | ||
3569 | + SDLK_V | ||
3570 | @@ | ||
3571 | @@ | ||
3572 | - SDLK_w | ||
3573 | + SDLK_W | ||
3574 | @@ | ||
3575 | @@ | ||
3576 | - SDLK_x | ||
3577 | + SDLK_X | ||
3578 | @@ | ||
3579 | @@ | ||
3580 | - SDLK_y | ||
3581 | + SDLK_Y | ||
3582 | @@ | ||
3583 | @@ | ||
3584 | - SDLK_z | ||
3585 | + SDLK_Z | ||
3586 | @@ | ||
3587 | @@ | ||
3588 | - SDL_ConvertSurfaceFormat | ||
3589 | + SDL_ConvertSurface | ||
3590 | (...) | ||
3591 | @@ | ||
3592 | @@ | ||
3593 | - SDL_PREALLOC | ||
3594 | + SDL_SURFACE_PREALLOCATED | ||
3595 | @@ | ||
3596 | @@ | ||
3597 | - SDL_SIMD_ALIGNED | ||
3598 | + SDL_SURFACE_SIMD_ALIGNED | ||
3599 | @@ | ||
3600 | @@ | ||
3601 | - SDL_GL_DeleteContext | ||
3602 | + SDL_GL_DestroyContext | ||
3603 | (...) | ||
3604 | @@ | ||
3605 | @@ | ||
3606 | - SDL_AndroidGetActivity | ||
3607 | + SDL_GetAndroidActivity | ||
3608 | (...) | ||
3609 | @@ | ||
3610 | @@ | ||
3611 | - SDL_AndroidGetExternalStoragePath | ||
3612 | + SDL_GetAndroidExternalStoragePath | ||
3613 | (...) | ||
3614 | @@ | ||
3615 | @@ | ||
3616 | - SDL_AndroidGetExternalStorageState | ||
3617 | + SDL_GetAndroidExternalStorageState | ||
3618 | (...) | ||
3619 | @@ | ||
3620 | @@ | ||
3621 | - SDL_AndroidGetInternalStoragePath | ||
3622 | + SDL_GetAndroidInternalStoragePath | ||
3623 | (...) | ||
3624 | @@ | ||
3625 | @@ | ||
3626 | - SDL_AndroidGetJNIEnv | ||
3627 | + SDL_GetAndroidJNIEnv | ||
3628 | (...) | ||
3629 | @@ | ||
3630 | @@ | ||
3631 | - SDL_Direct3D9GetAdapterIndex | ||
3632 | + SDL_GetDirect3D9AdapterIndex | ||
3633 | (...) | ||
3634 | @@ | ||
3635 | @@ | ||
3636 | - SDL_GDKGetDefaultUser | ||
3637 | + SDL_GetGDKDefaultUser | ||
3638 | (...) | ||
3639 | @@ | ||
3640 | @@ | ||
3641 | - SDL_GDKGetTaskQueue | ||
3642 | + SDL_GetGDKTaskQueue | ||
3643 | (...) | ||
3644 | @@ | ||
3645 | @@ | ||
3646 | - SDL_LinuxSetThreadPriority | ||
3647 | + SDL_SetLinuxThreadPriority | ||
3648 | (...) | ||
3649 | @@ | ||
3650 | @@ | ||
3651 | - SDL_LinuxSetThreadPriorityAndPolicy | ||
3652 | + SDL_SetLinuxThreadPriorityAndPolicy | ||
3653 | (...) | ||
3654 | @@ | ||
3655 | @@ | ||
3656 | - SDL_DXGIGetOutputInfo | ||
3657 | + SDL_GetDXGIOutputInfo | ||
3658 | (...) | ||
3659 | @@ | ||
3660 | @@ | ||
3661 | - SDL_AndroidBackButton | ||
3662 | + SDL_TriggerAndroidBackButton | ||
3663 | (...) | ||
3664 | @@ | ||
3665 | @@ | ||
3666 | - SDL_AndroidRequestPermission | ||
3667 | + SDL_RequestAndroidPermission | ||
3668 | (...) | ||
3669 | @@ | ||
3670 | @@ | ||
3671 | - SDL_AndroidRequestPermissionCallback | ||
3672 | + SDL_RequestAndroidPermissionCallback | ||
3673 | (...) | ||
3674 | @@ | ||
3675 | @@ | ||
3676 | - SDL_AndroidShowToast | ||
3677 | + SDL_ShowAndroidToast | ||
3678 | (...) | ||
3679 | @@ | ||
3680 | @@ | ||
3681 | - SDL_AndroidSendMessage | ||
3682 | + SDL_SendAndroidMessage | ||
3683 | (...) | ||
3684 | @@ | ||
3685 | typedef SDL_JoystickGUID, SDL_GUID; | ||
3686 | @@ | ||
3687 | - SDL_JoystickGUID | ||
3688 | + SDL_GUID | ||
3689 | @@ | ||
3690 | @@ | ||
3691 | - SDL_GUIDFromString | ||
3692 | + SDL_StringToGUID | ||
3693 | (...) | ||
3694 | @@ | ||
3695 | @@ | ||
3696 | - SDL_OnApplicationWillResignActive | ||
3697 | + SDL_OnApplicationWillEnterBackground | ||
3698 | (...) | ||
3699 | @@ | ||
3700 | @@ | ||
3701 | - SDL_OnApplicationDidBecomeActive | ||
3702 | + SDL_OnApplicationDidEnterForeground | ||
3703 | (...) | ||
3704 | @@ | ||
3705 | @@ | ||
3706 | - SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP | ||
3707 | + SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE | ||
3708 | @@ | ||
3709 | @@ | ||
3710 | - SDL_DelEventWatch | ||
3711 | + SDL_RemoveEventWatch | ||
3712 | (...) | ||
3713 | @@ | ||
3714 | @@ | ||
3715 | - SDL_DelHintCallback | ||
3716 | + SDL_RemoveHintCallback | ||
3717 | (...) | ||
3718 | @@ | ||
3719 | @@ | ||
3720 | - SDL_size_mul_overflow | ||
3721 | + SDL_size_mul_check_overflow | ||
3722 | (...) | ||
3723 | @@ | ||
3724 | @@ | ||
3725 | - SDL_size_add_overflow | ||
3726 | + SDL_size_add_check_overflow | ||
3727 | (...) | ||
3728 | @@ | ||
3729 | @@ | ||
3730 | - SDL_PRESSED | ||
3731 | + true | ||
3732 | @@ | ||
3733 | @@ | ||
3734 | - SDL_RELEASED | ||
3735 | + false | ||
3736 | |||
3737 | // This should be the last rule in the file, since it works on SDL3 functions and previous rules may have renamed old functions. | ||
3738 | @ bool_return_type @ | ||
3739 | identifier func =~ "^(SDL_AddEventWatch|SDL_AddHintCallback|SDL_AddSurfaceAlternateImage|SDL_AddVulkanRenderSemaphores|SDL_BindAudioStream|SDL_BindAudioStreams|SDL_BlitSurface|SDL_BlitSurface9Grid|SDL_BlitSurfaceScaled|SDL_BlitSurfaceTiled|SDL_BlitSurfaceTiledWithScale|SDL_BlitSurfaceUnchecked|SDL_BlitSurfaceUncheckedScaled|SDL_CaptureMouse|SDL_ClearAudioStream|SDL_ClearClipboardData|SDL_ClearComposition|SDL_ClearError|SDL_ClearProperty|SDL_ClearSurface|SDL_CloseIO|SDL_CloseStorage|SDL_ConvertAudioSamples|SDL_ConvertEventToRenderCoordinates|SDL_ConvertPixels|SDL_ConvertPixelsAndColorspace|SDL_CopyFile|SDL_CopyProperties|SDL_CopyStorageFile|SDL_CreateDirectory|SDL_CreateStorageDirectory|SDL_CreateWindowAndRenderer|SDL_DateTimeToTime|SDL_DestroyWindowSurface|SDL_DetachVirtualJoystick|SDL_DisableScreenSaver|SDL_EnableScreenSaver|SDL_EnumerateDirectory|SDL_EnumerateProperties|SDL_EnumerateStorageDirectory|SDL_FillSurfaceRect|SDL_FillSurfaceRects|SDL_FlashWindow|SDL_FlipSurface|SDL_FlushAudioStream|SDL_FlushRenderer|SDL_GL_DestroyContext|SDL_GL_GetAttribute|SDL_GL_GetSwapInterval|SDL_GL_LoadLibrary|SDL_GL_MakeCurrent|SDL_GL_SetAttribute|SDL_GL_SetSwapInterval|SDL_GL_SwapWindow|SDL_GetAudioDeviceFormat|SDL_GetAudioStreamFormat|SDL_GetCameraFormat|SDL_GetClosestFullscreenDisplayMode|SDL_GetCurrentRenderOutputSize|SDL_GetCurrentTime|SDL_GetDXGIOutputInfo|SDL_GetDateTimeLocalePreferences|SDL_GetDisplayBounds|SDL_GetDisplayUsableBounds|SDL_GetGDKDefaultUser|SDL_GetGDKTaskQueue|SDL_GetGamepadSensorData|SDL_GetGamepadTouchpadFinger|SDL_GetHapticEffectStatus|SDL_GetJoystickBall|SDL_GetMasksForPixelFormat|SDL_GetPathInfo|SDL_GetRectUnion|SDL_GetRectUnionFloat|SDL_GetRenderClipRect|SDL_GetRenderColorScale|SDL_GetRenderDrawBlendMode|SDL_GetRenderDrawColor|SDL_GetRenderDrawColorFloat|SDL_GetRenderLogicalPresentation|SDL_GetRenderLogicalPresentationRect|SDL_GetRenderOutputSize|SDL_GetRenderSafeArea|SDL_GetRenderScale|SDL_GetRenderVSync|SDL_GetRenderViewport|SDL_GetSensorData|SDL_GetStorageFileSize|SDL_GetStoragePathInfo|SDL_GetSurfaceAlphaMod|SDL_GetSurfaceBlendMode|SDL_GetSurfaceClipRect|SDL_GetSurfaceColorKey|SDL_GetSurfaceColorMod|SDL_GetTextInputArea|SDL_GetTextureAlphaMod|SDL_GetTextureAlphaModFloat|SDL_GetTextureBlendMode|SDL_GetTextureColorMod|SDL_GetTextureColorModFloat|SDL_GetTextureScaleMode|SDL_GetTextureSize|SDL_GetWindowAspectRatio|SDL_GetWindowBordersSize|SDL_GetWindowMaximumSize|SDL_GetWindowMinimumSize|SDL_GetWindowPosition|SDL_GetWindowRelativeMouseMode|SDL_GetWindowSafeArea|SDL_GetWindowSize|SDL_GetWindowSizeInPixels|SDL_GetWindowSurfaceVSync|SDL_HideCursor|SDL_HideWindow|SDL_Init|SDL_InitHapticRumble|SDL_InitSubSystem|SDL_LoadWAV|SDL_LoadWAV_IO|SDL_LockAudioStream|SDL_LockProperties|SDL_LockSurface|SDL_LockTexture|SDL_LockTextureToSurface|SDL_MaximizeWindow|SDL_MinimizeWindow|SDL_MixAudio|SDL_OpenURL|SDL_OutOfMemory|SDL_PauseAudioDevice|SDL_PauseAudioStreamDevice|SDL_PauseHaptic|SDL_PlayHapticRumble|SDL_PremultiplyAlpha|SDL_PremultiplySurfaceAlpha|SDL_PushEvent|SDL_PutAudioStreamData|SDL_RaiseWindow|SDL_ReadStorageFile|SDL_ReadSurfacePixel|SDL_ReadSurfacePixelFloat|SDL_RegisterApp|SDL_ReloadGamepadMappings|SDL_RemovePath|SDL_RemoveStoragePath|SDL_RemoveTimer|SDL_RenamePath|SDL_RenameStoragePath|SDL_RenderClear|SDL_RenderCoordinatesFromWindow|SDL_RenderCoordinatesToWindow|SDL_RenderFillRect|SDL_RenderFillRects|SDL_RenderGeometry|SDL_RenderGeometryRaw|SDL_RenderLine|SDL_RenderLines|SDL_RenderPoint|SDL_RenderPoints|SDL_RenderPresent|SDL_RenderRect|SDL_RenderRects|SDL_RenderTexture|SDL_RenderTexture9Grid|SDL_RenderTextureRotated|SDL_RenderTextureTiled|SDL_RequestAndroidPermission|SDL_RestoreWindow|SDL_ResumeAudioDevice|SDL_ResumeAudioStreamDevice|SDL_ResumeHaptic|SDL_RumbleGamepad|SDL_RumbleGamepadTriggers|SDL_RumbleJoystick|SDL_RumbleJoystickTriggers|SDL_RunHapticEffect|SDL_SaveBMP|SDL_SaveBMP_IO|SDL_SendAndroidMessage|SDL_SendGamepadEffect|SDL_SendJoystickEffect|SDL_SendJoystickVirtualSensorData|SDL_SetAppMetadata|SDL_SetAppMetadataProperty|SDL_SetAudioDeviceGain|SDL_SetAudioPostmixCallback|SDL_SetAudioStreamFormat|SDL_SetAudioStreamFrequencyRatio|SDL_SetAudioStreamGain|SDL_SetAudioStreamGetCallback|SDL_SetAudioStreamInputChannelMap|SDL_SetAudioStreamOutputChannelMap|SDL_SetAudioStreamPutCallback|SDL_SetBooleanProperty|SDL_SetClipboardData|SDL_SetClipboardText|SDL_SetCursor|SDL_SetFloatProperty|SDL_SetGamepadLED|SDL_SetGamepadMapping|SDL_SetGamepadPlayerIndex|SDL_SetGamepadSensorEnabled|SDL_SetHapticAutocenter|SDL_SetHapticGain|SDL_SetJoystickLED|SDL_SetJoystickPlayerIndex|SDL_SetJoystickVirtualAxis|SDL_SetJoystickVirtualBall|SDL_SetJoystickVirtualButton|SDL_SetJoystickVirtualHat|SDL_SetJoystickVirtualTouchpad|SDL_SetLinuxThreadPriority|SDL_SetLinuxThreadPriorityAndPolicy|SDL_SetLogPriorityPrefix|SDL_SetMemoryFunctions|SDL_SetNumberProperty|SDL_SetPaletteColors|SDL_SetPointerProperty|SDL_SetPointerPropertyWithCleanup|SDL_SetPrimarySelectionText|SDL_SetRenderClipRect|SDL_SetRenderColorScale|SDL_SetRenderDrawBlendMode|SDL_SetRenderDrawColor|SDL_SetRenderDrawColorFloat|SDL_SetRenderLogicalPresentation|SDL_SetRenderScale|SDL_SetRenderTarget|SDL_SetRenderVSync|SDL_SetRenderViewport|SDL_SetScancodeName|SDL_SetStringProperty|SDL_SetSurfaceAlphaMod|SDL_SetSurfaceBlendMode|SDL_SetSurfaceColorKey|SDL_SetSurfaceColorMod|SDL_SetSurfaceColorspace|SDL_SetSurfacePalette|SDL_SetSurfaceRLE|SDL_SetTLS|SDL_SetTextInputArea|SDL_SetTextureAlphaMod|SDL_SetTextureAlphaModFloat|SDL_SetTextureBlendMode|SDL_SetTextureColorMod|SDL_SetTextureColorModFloat|SDL_SetTextureScaleMode|SDL_SetThreadPriority|SDL_SetWindowAlwaysOnTop|SDL_SetWindowAspectRatio|SDL_SetWindowBordered|SDL_SetWindowFocusable|SDL_SetWindowFullscreen|SDL_SetWindowFullscreenMode|SDL_SetWindowHitTest|SDL_SetWindowIcon|SDL_SetWindowKeyboardGrab|SDL_SetWindowMaximumSize|SDL_SetWindowMinimumSize|SDL_SetWindowModalFor|SDL_SetWindowMouseGrab|SDL_SetWindowMouseRect|SDL_SetWindowOpacity|SDL_SetWindowPosition|SDL_SetWindowRelativeMouseMode|SDL_SetWindowResizable|SDL_SetWindowShape|SDL_SetWindowSize|SDL_SetWindowSurfaceVSync|SDL_SetWindowTitle|SDL_SetiOSAnimationCallback|SDL_ShowAndroidToast|SDL_ShowCursor|SDL_ShowMessageBox|SDL_ShowSimpleMessageBox|SDL_ShowWindow|SDL_ShowWindowSystemMenu|SDL_StartTextInput|SDL_StartTextInputWithProperties|SDL_StopHapticEffect|SDL_StopHapticEffects|SDL_StopHapticRumble|SDL_StopTextInput|SDL_SyncWindow|SDL_TimeToDateTime|SDL_TryLockMutex|SDL_TryLockRWLockForReading|SDL_TryLockRWLockForWriting|SDL_TryWaitSemaphore|SDL_UnlockAudioStream|SDL_UpdateHapticEffect|SDL_UpdateNVTexture|SDL_UpdateTexture|SDL_UpdateWindowSurface|SDL_UpdateWindowSurfaceRects|SDL_UpdateYUVTexture|SDL_Vulkan_CreateSurface|SDL_Vulkan_LoadLibrary|SDL_WaitConditionTimeout|SDL_WaitSemaphoreTimeout|SDL_WarpMouseGlobal|SDL_WriteStorageFile|SDL_WriteSurfacePixel|SDL_WriteSurfacePixelFloat|SDL_size_mul_check_overflow|SDL_size_add_check_overflow|TTF_GlyphMetrics|TTF_GlyphMetrics32|TTF_Init|TTF_MeasureText|TTF_MeasureUNICODE|TTF_MeasureUTF8|TTF_SetFontDirection|TTF_SetFontLanguage|TTF_SetFontScriptName|TTF_SetFontSDF|TTF_SetFontSize|TTF_SetFontSizeDPI|TTF_SizeText|TTF_SizeUNICODE|TTF_SizeUTF8|IMG_SaveAVIF|IMG_SaveAVIF_IO|IMG_SaveJPG|IMG_SaveJPG_IO|IMG_SavePNG|IMG_SavePNG_IO|Mix_FadeInMusic|Mix_FadeInMusicPos|Mix_GroupChannels|Mix_ModMusicJumpToOrder|Mix_OpenAudio|Mix_PlayMusic|Mix_SetMusicCMD|Mix_SetMusicPosition|Mix_SetSoundFonts|Mix_StartTrack)$"; | ||
3740 | @@ | ||
3741 | ( | ||
3742 | func( | ||
3743 | ... | ||
3744 | ) | ||
3745 | - == 0 | ||
3746 | | | ||
3747 | - func( | ||
3748 | + !func( | ||
3749 | ... | ||
3750 | ) | ||
3751 | - < 0 | ||
3752 | | | ||
3753 | - func( | ||
3754 | + !func( | ||
3755 | ... | ||
3756 | ) | ||
3757 | - != 0 | ||
3758 | | | ||
3759 | - func( | ||
3760 | + !func( | ||
3761 | ... | ||
3762 | ) | ||
3763 | - == -1 | ||
3764 | ) | ||
3765 | @@ | ||
3766 | @@ | ||
3767 | - SDL_NUM_LOG_PRIORITIES | ||
3768 | + SDL_LOG_PRIORITY_COUNT | ||
3769 | @@ | ||
3770 | @@ | ||
3771 | - SDL_MESSAGEBOX_COLOR_MAX | ||
3772 | + SDL_MESSAGEBOX_COLOR_COUNT | ||
3773 | @@ | ||
3774 | @@ | ||
3775 | - SDL_NUM_SYSTEM_CURSORS | ||
3776 | + SDL_SYSTEM_CURSOR_COUNT | ||
3777 | @@ | ||
3778 | @@ | ||
3779 | - SDL_NUM_SCANCODES | ||
3780 | + SDL_SCANCODE_COUNT | ||
3781 | @@ | ||
3782 | @@ | ||
3783 | - SDL_GetCPUCount | ||
3784 | + SDL_GetNumLogicalCPUCores | ||
3785 | (...) | ||
3786 | @@ | ||
3787 | typedef SDL_bool, bool; | ||
3788 | @@ | ||
3789 | - SDL_bool | ||
3790 | + bool | ||
3791 | @@ | ||
3792 | @@ | ||
3793 | - SDL_TRUE | ||
3794 | + true | ||
3795 | @@ | ||
3796 | @@ | ||
3797 | - SDL_FALSE | ||
3798 | + false | ||
3799 | @@ | ||
3800 | @@ | ||
3801 | - SDL_IsAndroidTV | ||
3802 | + SDL_IsTV | ||
3803 | (...) | ||
3804 | @@ | ||
3805 | @@ | ||
3806 | - SDL_SetThreadPriority | ||
3807 | + SDL_SetCurrentThreadPriority | ||
3808 | (...) | ||
3809 | @@ | ||
3810 | @@ | ||
3811 | - SDL_BUTTON | ||
3812 | + SDL_BUTTON_MASK | ||
3813 | @@ | ||
3814 | @@ | ||
3815 | - SDL_GLprofile | ||
3816 | + SDL_GLProfile | ||
3817 | @@ | ||
3818 | @@ | ||
3819 | - SDL_GLcontextFlag | ||
3820 | + SDL_GLContextFlag | ||
3821 | @@ | ||
3822 | @@ | ||
3823 | - SDL_GLcontextReleaseFlag | ||
3824 | + SDL_GLContextReleaseFlag | ||
3825 | @@ | ||
3826 | @@ | ||
3827 | - SDL_GLattr | ||
3828 | + SDL_GLAttr | ||
3829 | @@ | ||
3830 | @@ | ||
3831 | - SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE | ||
3832 | + SDL_HINT_JOYSTICK_ENHANCED_REPORTS | ||
3833 | @@ | ||
3834 | @@ | ||
3835 | - SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE | ||
3836 | + SDL_HINT_JOYSTICK_ENHANCED_REPORTS | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/add-source-to-projects.pl b/src/contrib/SDL-3.2.20/build-scripts/add-source-to-projects.pl new file mode 100755 index 0000000..5ba0a69 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/add-source-to-projects.pl | |||
@@ -0,0 +1,599 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | # Add source files and headers to Xcode and Visual Studio projects. | ||
4 | # THIS IS NOT ROBUST, THIS IS JUST RYAN AVOIDING RUNNING BETWEEN | ||
5 | # THREE COMPUTERS AND A BUNCH OF DEVELOPMENT ENVIRONMENTS TO ADD | ||
6 | # A STUPID FILE TO THE BUILD. | ||
7 | |||
8 | |||
9 | use warnings; | ||
10 | use strict; | ||
11 | use File::Basename; | ||
12 | |||
13 | |||
14 | my %xcode_references = (); | ||
15 | sub generate_xcode_id { | ||
16 | my @chars = ('0'..'9', 'A'..'F'); | ||
17 | my $str; | ||
18 | |||
19 | do { | ||
20 | my $len = 16; | ||
21 | $str = '0000'; # start and end with '0000' so we know we added it. | ||
22 | while ($len--) { | ||
23 | $str .= $chars[rand @chars] | ||
24 | }; | ||
25 | $str .= '0000'; # start and end with '0000' so we know we added it. | ||
26 | } while (defined($xcode_references{$str})); | ||
27 | |||
28 | $xcode_references{$str} = 1; # so future calls can't generate this one. | ||
29 | |||
30 | return $str; | ||
31 | } | ||
32 | |||
33 | sub process_xcode { | ||
34 | my $addpath = shift; | ||
35 | my $pbxprojfname = shift; | ||
36 | my $lineno; | ||
37 | |||
38 | %xcode_references = (); | ||
39 | |||
40 | my $addfname = basename($addpath); | ||
41 | my $addext = ''; | ||
42 | if ($addfname =~ /\.(.*?)\Z/) { | ||
43 | $addext = $1; | ||
44 | } | ||
45 | |||
46 | my $is_public_header = ($addpath =~ /\Ainclude\/SDL3\//) ? 1 : 0; | ||
47 | my $filerefpath = $is_public_header ? "SDL3/$addfname" : $addfname; | ||
48 | |||
49 | my $srcs_or_headers = ''; | ||
50 | my $addfiletype = ''; | ||
51 | |||
52 | if ($addext eq 'c') { | ||
53 | $srcs_or_headers = 'Sources'; | ||
54 | $addfiletype = 'sourcecode.c.c'; | ||
55 | } elsif ($addext eq 'm') { | ||
56 | $srcs_or_headers = 'Sources'; | ||
57 | $addfiletype = 'sourcecode.c.objc'; | ||
58 | } elsif ($addext eq 'h') { | ||
59 | $srcs_or_headers = 'Headers'; | ||
60 | $addfiletype = 'sourcecode.c.h'; | ||
61 | } else { | ||
62 | die("Unexpected file extension '$addext'\n"); | ||
63 | } | ||
64 | |||
65 | my $fh; | ||
66 | |||
67 | open $fh, '<', $pbxprojfname or die("Failed to open '$pbxprojfname': $!\n"); | ||
68 | chomp(my @pbxproj = <$fh>); | ||
69 | close($fh); | ||
70 | |||
71 | # build a table of all ids, in case we duplicate one by some miracle. | ||
72 | $lineno = 0; | ||
73 | foreach (@pbxproj) { | ||
74 | $lineno++; | ||
75 | |||
76 | # like "F3676F582A7885080091160D /* SDL3.dmg */ = {" | ||
77 | if (/\A\t\t([A-F0-9]{24}) \/\* (.*?) \*\/ \= \{\Z/) { | ||
78 | $xcode_references{$1} = $2; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | # build out of a tree of PBXGroup items. | ||
83 | my %pbxgroups = (); | ||
84 | my $thispbxgroup; | ||
85 | my $pbxgroup_children; | ||
86 | my $pbxgroup_state = 0; | ||
87 | my $pubheaders_group_hash = ''; | ||
88 | my $libsrc_group_hash = ''; | ||
89 | $lineno = 0; | ||
90 | foreach (@pbxproj) { | ||
91 | $lineno++; | ||
92 | if ($pbxgroup_state == 0) { | ||
93 | $pbxgroup_state++ if /\A\/\* Begin PBXGroup section \*\/\Z/; | ||
94 | } elsif ($pbxgroup_state == 1) { | ||
95 | # like "F3676F582A7885080091160D /* SDL3.dmg */ = {" | ||
96 | if (/\A\t\t([A-F0-9]{24}) \/\* (.*?) \*\/ \= \{\Z/) { | ||
97 | my %newhash = (); | ||
98 | $pbxgroups{$1} = \%newhash; | ||
99 | $thispbxgroup = \%newhash; | ||
100 | $pubheaders_group_hash = $1 if $2 eq 'Public Headers'; | ||
101 | $libsrc_group_hash = $1 if $2 eq 'Library Source'; | ||
102 | $pbxgroup_state++; | ||
103 | } elsif (/\A\/\* End PBXGroup section \*\/\Z/) { | ||
104 | last; | ||
105 | } else { | ||
106 | die("Expected pbxgroup obj on '$pbxprojfname' line $lineno\n"); | ||
107 | } | ||
108 | } elsif ($pbxgroup_state == 2) { | ||
109 | if (/\A\t\t\tisa \= PBXGroup;\Z/) { | ||
110 | $pbxgroup_state++; | ||
111 | } else { | ||
112 | die("Expected pbxgroup obj's isa field on '$pbxprojfname' line $lineno\n"); | ||
113 | } | ||
114 | } elsif ($pbxgroup_state == 3) { | ||
115 | if (/\A\t\t\tchildren \= \(\Z/) { | ||
116 | my %newhash = (); | ||
117 | $$thispbxgroup{'children'} = \%newhash; | ||
118 | $pbxgroup_children = \%newhash; | ||
119 | $pbxgroup_state++; | ||
120 | } else { | ||
121 | die("Expected pbxgroup obj's children field on '$pbxprojfname' line $lineno\n"); | ||
122 | } | ||
123 | } elsif ($pbxgroup_state == 4) { | ||
124 | if (/\A\t\t\t\t([A-F0-9]{24}) \/\* (.*?) \*\/,\Z/) { | ||
125 | $$pbxgroup_children{$1} = $2; | ||
126 | } elsif (/\A\t\t\t\);\Z/) { | ||
127 | $pbxgroup_state++; | ||
128 | } else { | ||
129 | die("Expected pbxgroup obj's children element on '$pbxprojfname' line $lineno\n"); | ||
130 | } | ||
131 | } elsif ($pbxgroup_state == 5) { | ||
132 | if (/\A\t\t\t(.*?) \= (.*?);\Z/) { | ||
133 | $$thispbxgroup{$1} = $2; | ||
134 | } elsif (/\A\t\t\};\Z/) { | ||
135 | $pbxgroup_state = 1; | ||
136 | } else { | ||
137 | die("Expected pbxgroup obj field on '$pbxprojfname' line $lineno\n"); | ||
138 | } | ||
139 | } else { | ||
140 | die("bug in this script."); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | die("Didn't see PBXGroup section in '$pbxprojfname'. Bug?\n") if $pbxgroup_state == 0; | ||
145 | die("Didn't see Public Headers PBXGroup in '$pbxprojfname'. Bug?\n") if $pubheaders_group_hash eq ''; | ||
146 | die("Didn't see Library Source PBXGroup in '$pbxprojfname'. Bug?\n") if $libsrc_group_hash eq ''; | ||
147 | |||
148 | # Some debug log dumping... | ||
149 | if (0) { | ||
150 | foreach (keys %pbxgroups) { | ||
151 | my $k = $_; | ||
152 | my $g = $pbxgroups{$k}; | ||
153 | print("$_:\n"); | ||
154 | foreach (keys %$g) { | ||
155 | print(" $_:\n"); | ||
156 | if ($_ eq 'children') { | ||
157 | my $kids = $$g{$_}; | ||
158 | foreach (keys %$kids) { | ||
159 | print(" $_ -> " . $$kids{$_} . "\n"); | ||
160 | } | ||
161 | } else { | ||
162 | print(' ' . $$g{$_} . "\n"); | ||
163 | } | ||
164 | } | ||
165 | print("\n"); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | # Get some unique IDs for our new thing. | ||
170 | my $fileref = generate_xcode_id(); | ||
171 | my $buildfileref = generate_xcode_id(); | ||
172 | |||
173 | |||
174 | # Figure out what group to insert this into (or what groups to make) | ||
175 | my $add_to_group_fileref = $fileref; | ||
176 | my $add_to_group_addfname = $addfname; | ||
177 | my $newgrptext = ''; | ||
178 | my $grphash = ''; | ||
179 | if ($is_public_header) { | ||
180 | $grphash = $pubheaders_group_hash; # done! | ||
181 | } else { | ||
182 | $grphash = $libsrc_group_hash; | ||
183 | my @splitpath = split(/\//, dirname($addpath)); | ||
184 | if ($splitpath[0] eq 'src') { | ||
185 | shift @splitpath; | ||
186 | } | ||
187 | while (my $elem = shift(@splitpath)) { | ||
188 | my $g = $pbxgroups{$grphash}; | ||
189 | my $kids = $$g{'children'}; | ||
190 | my $found = 0; | ||
191 | foreach (keys %$kids) { | ||
192 | my $hash = $_; | ||
193 | my $fname = $$kids{$hash}; | ||
194 | if (uc($fname) eq uc($elem)) { | ||
195 | $grphash = $hash; | ||
196 | $found = 1; | ||
197 | last; | ||
198 | } | ||
199 | } | ||
200 | unshift(@splitpath, $elem), last if (not $found); | ||
201 | } | ||
202 | |||
203 | if (@splitpath) { # still elements? We need to build groups. | ||
204 | my $newgroupref = generate_xcode_id(); | ||
205 | |||
206 | $add_to_group_fileref = $newgroupref; | ||
207 | $add_to_group_addfname = $splitpath[0]; | ||
208 | |||
209 | while (my $elem = shift(@splitpath)) { | ||
210 | my $lastelem = @splitpath ? 0 : 1; | ||
211 | my $childhash = $lastelem ? $fileref : generate_xcode_id(); | ||
212 | my $childpath = $lastelem ? $addfname : $splitpath[0]; | ||
213 | $newgrptext .= "\t\t$newgroupref /* $elem */ = {\n"; | ||
214 | $newgrptext .= "\t\t\tisa = PBXGroup;\n"; | ||
215 | $newgrptext .= "\t\t\tchildren = (\n"; | ||
216 | $newgrptext .= "\t\t\t\t$childhash /* $childpath */,\n"; | ||
217 | $newgrptext .= "\t\t\t);\n"; | ||
218 | $newgrptext .= "\t\t\tpath = $elem;\n"; | ||
219 | $newgrptext .= "\t\t\tsourceTree = \"<group>\";\n"; | ||
220 | $newgrptext .= "\t\t};\n"; | ||
221 | $newgroupref = $childhash; | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | my $tmpfname = "$pbxprojfname.tmp"; | ||
227 | open $fh, '>', $tmpfname or die("Failed to open '$tmpfname': $!\n"); | ||
228 | |||
229 | my $add_to_this_group = 0; | ||
230 | $pbxgroup_state = 0; | ||
231 | $lineno = 0; | ||
232 | foreach (@pbxproj) { | ||
233 | $lineno++; | ||
234 | if ($pbxgroup_state == 0) { | ||
235 | # Drop in new references at the end of their sections... | ||
236 | if (/\A\/\* End PBXBuildFile section \*\/\Z/) { | ||
237 | print $fh "\t\t$buildfileref /* $addfname in $srcs_or_headers */ = {isa = PBXBuildFile; fileRef = $fileref /* $addfname */;"; | ||
238 | if ($is_public_header) { | ||
239 | print $fh " settings = {ATTRIBUTES = (Public, ); };"; | ||
240 | } | ||
241 | print $fh " };\n"; | ||
242 | } elsif (/\A\/\* End PBXFileReference section \*\/\Z/) { | ||
243 | print $fh "\t\t$fileref /* $addfname */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = $addfiletype; name = $addfname; path = $filerefpath; sourceTree = \"<group>\"; };\n"; | ||
244 | } elsif (/\A\/\* Begin PBXGroup section \*\/\Z/) { | ||
245 | $pbxgroup_state = 1; | ||
246 | } elsif (/\A\/\* Begin PBXSourcesBuildPhase section \*\/\Z/) { | ||
247 | $pbxgroup_state = 5; | ||
248 | } | ||
249 | } elsif ($pbxgroup_state == 1) { | ||
250 | if (/\A\t\t([A-F0-9]{24}) \/\* (.*?) \*\/ \= \{\Z/) { | ||
251 | $pbxgroup_state++; | ||
252 | $add_to_this_group = $1 eq $grphash; | ||
253 | } elsif (/\A\/\* End PBXGroup section \*\/\Z/) { | ||
254 | print $fh $newgrptext; | ||
255 | $pbxgroup_state = 0; | ||
256 | } | ||
257 | } elsif ($pbxgroup_state == 2) { | ||
258 | if (/\A\t\t\tchildren \= \(\Z/) { | ||
259 | $pbxgroup_state++; | ||
260 | } | ||
261 | } elsif ($pbxgroup_state == 3) { | ||
262 | if (/\A\t\t\t\);\Z/) { | ||
263 | if ($add_to_this_group) { | ||
264 | print $fh "\t\t\t\t$add_to_group_fileref /* $add_to_group_addfname */,\n"; | ||
265 | } | ||
266 | $pbxgroup_state++; | ||
267 | } | ||
268 | } elsif ($pbxgroup_state == 4) { | ||
269 | if (/\A\t\t\};\Z/) { | ||
270 | $add_to_this_group = 0; | ||
271 | } | ||
272 | $pbxgroup_state = 1; | ||
273 | } elsif ($pbxgroup_state == 5) { | ||
274 | if (/\A\t\t\t\);\Z/) { | ||
275 | if ($srcs_or_headers eq 'Sources') { | ||
276 | print $fh "\t\t\t\t$buildfileref /* $addfname in $srcs_or_headers */,\n"; | ||
277 | } | ||
278 | $pbxgroup_state = 0; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | print $fh "$_\n"; | ||
283 | } | ||
284 | |||
285 | close($fh); | ||
286 | rename($tmpfname, $pbxprojfname); | ||
287 | } | ||
288 | |||
289 | my %visualc_references = (); | ||
290 | sub generate_visualc_id { # these are just standard Windows GUIDs. | ||
291 | my @chars = ('0'..'9', 'a'..'f'); | ||
292 | my $str; | ||
293 | |||
294 | do { | ||
295 | my $len = 24; | ||
296 | $str = '0000'; # start and end with '0000' so we know we added it. | ||
297 | while ($len--) { | ||
298 | $str .= $chars[rand @chars] | ||
299 | }; | ||
300 | $str .= '0000'; # start and end with '0000' so we know we added it. | ||
301 | $str =~ s/\A(........)(....)(....)(............)\Z/$1-$2-$3-$4/; # add dashes in the appropriate places. | ||
302 | } while (defined($visualc_references{$str})); | ||
303 | |||
304 | $visualc_references{$str} = 1; # so future calls can't generate this one. | ||
305 | |||
306 | return $str; | ||
307 | } | ||
308 | |||
309 | |||
310 | sub process_visualstudio { | ||
311 | my $addpath = shift; | ||
312 | my $vcxprojfname = shift; | ||
313 | my $lineno; | ||
314 | |||
315 | %visualc_references = (); | ||
316 | |||
317 | my $is_public_header = ($addpath =~ /\Ainclude\/SDL3\//) ? 1 : 0; | ||
318 | |||
319 | my $addfname = basename($addpath); | ||
320 | my $addext = ''; | ||
321 | if ($addfname =~ /\.(.*?)\Z/) { | ||
322 | $addext = $1; | ||
323 | } | ||
324 | |||
325 | my $isheader = 0; | ||
326 | if ($addext eq 'c') { | ||
327 | $isheader = 0; | ||
328 | } elsif ($addext eq 'm') { | ||
329 | return; # don't add Objective-C files to Visual Studio projects! | ||
330 | } elsif ($addext eq 'h') { | ||
331 | $isheader = 1; | ||
332 | } else { | ||
333 | die("Unexpected file extension '$addext'\n"); | ||
334 | } | ||
335 | |||
336 | my $fh; | ||
337 | |||
338 | open $fh, '<', $vcxprojfname or die("Failed to open '$vcxprojfname': $!\n"); | ||
339 | chomp(my @vcxproj = <$fh>); | ||
340 | close($fh); | ||
341 | |||
342 | my $vcxgroup_state; | ||
343 | |||
344 | my $rawaddvcxpath = "$addpath"; | ||
345 | $rawaddvcxpath =~ s/\//\\/g; | ||
346 | |||
347 | # Figure out relative path from vcxproj file... | ||
348 | my $addvcxpath = ''; | ||
349 | my @subdirs = split(/\//, $vcxprojfname); | ||
350 | pop @subdirs; | ||
351 | foreach (@subdirs) { | ||
352 | $addvcxpath .= "..\\"; | ||
353 | } | ||
354 | $addvcxpath .= $rawaddvcxpath; | ||
355 | |||
356 | my $prevname = undef; | ||
357 | |||
358 | my $tmpfname; | ||
359 | |||
360 | $tmpfname = "$vcxprojfname.tmp"; | ||
361 | open $fh, '>', $tmpfname or die("Failed to open '$tmpfname': $!\n"); | ||
362 | |||
363 | my $added = 0; | ||
364 | |||
365 | $added = 0; | ||
366 | $vcxgroup_state = 0; | ||
367 | $prevname = undef; | ||
368 | $lineno = 0; | ||
369 | foreach (@vcxproj) { | ||
370 | $lineno++; | ||
371 | if ($vcxgroup_state == 0) { | ||
372 | if (/\A \<ItemGroup\>\Z/) { | ||
373 | $vcxgroup_state = 1; | ||
374 | $prevname = undef; | ||
375 | } | ||
376 | } elsif ($vcxgroup_state == 1) { | ||
377 | if (/\A \<ClInclude .*\Z/) { | ||
378 | $vcxgroup_state = 2 if $isheader; | ||
379 | } elsif (/\A \<ClCompile .*\Z/) { | ||
380 | $vcxgroup_state = 3 if not $isheader; | ||
381 | } elsif (/\A \<\/ItemGroup\>\Z/) { | ||
382 | $vcxgroup_state = 0; | ||
383 | $prevname = undef; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | # Don't do elsif, we need to check this line again. | ||
388 | if ($vcxgroup_state == 2) { | ||
389 | if (/\A <ClInclude Include="(.*?)" \/\>\Z/) { | ||
390 | my $nextname = $1; | ||
391 | if ((not $added) && (((not defined $prevname) || (uc($prevname) lt uc($addvcxpath))) && (uc($nextname) gt uc($addvcxpath)))) { | ||
392 | print $fh " <ClInclude Include=\"$addvcxpath\" />\n"; | ||
393 | $vcxgroup_state = 0; | ||
394 | $added = 1; | ||
395 | } | ||
396 | $prevname = $nextname; | ||
397 | } elsif (/\A \<\/ItemGroup\>\Z/) { | ||
398 | if ((not $added) && ((not defined $prevname) || (uc($prevname) lt uc($addvcxpath)))) { | ||
399 | print $fh " <ClInclude Include=\"$addvcxpath\" />\n"; | ||
400 | $vcxgroup_state = 0; | ||
401 | $added = 1; | ||
402 | } | ||
403 | } | ||
404 | } elsif ($vcxgroup_state == 3) { | ||
405 | if (/\A <ClCompile Include="(.*?)" \/\>\Z/) { | ||
406 | my $nextname = $1; | ||
407 | if ((not $added) && (((not defined $prevname) || (uc($prevname) lt uc($addvcxpath))) && (uc($nextname) gt uc($addvcxpath)))) { | ||
408 | print $fh " <ClCompile Include=\"$addvcxpath\" />\n"; | ||
409 | $vcxgroup_state = 0; | ||
410 | $added = 1; | ||
411 | } | ||
412 | $prevname = $nextname; | ||
413 | } elsif (/\A \<\/ItemGroup\>\Z/) { | ||
414 | if ((not $added) && ((not defined $prevname) || (uc($prevname) lt uc($addvcxpath)))) { | ||
415 | print $fh " <ClCompile Include=\"$addvcxpath\" />\n"; | ||
416 | $vcxgroup_state = 0; | ||
417 | $added = 1; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | print $fh "$_\n"; | ||
423 | } | ||
424 | |||
425 | close($fh); | ||
426 | rename($tmpfname, $vcxprojfname); | ||
427 | |||
428 | my $vcxfiltersfname = "$vcxprojfname.filters"; | ||
429 | open $fh, '<', $vcxfiltersfname or die("Failed to open '$vcxfiltersfname': $!\n"); | ||
430 | chomp(my @vcxfilters = <$fh>); | ||
431 | close($fh); | ||
432 | |||
433 | my $newgrptext = ''; | ||
434 | my $filter = ''; | ||
435 | if ($is_public_header) { | ||
436 | $filter = 'API Headers'; | ||
437 | } else { | ||
438 | $filter = lc(dirname($addpath)); | ||
439 | $filter =~ s/\Asrc\///; # there's no filter for the base "src/" dir, where SDL.c and friends live. | ||
440 | $filter =~ s/\//\\/g; | ||
441 | $filter = '' if $filter eq 'src'; | ||
442 | |||
443 | if ($filter ne '') { | ||
444 | # see if the filter already exists, otherwise add it. | ||
445 | my %existing_filters = (); | ||
446 | my $current_filter = ''; | ||
447 | my $found = 0; | ||
448 | foreach (@vcxfilters) { | ||
449 | # These lines happen to be unique, so we don't have to parse down to find this section. | ||
450 | if (/\A \<Filter Include\="(.*?)"\>\Z/) { | ||
451 | $current_filter = lc($1); | ||
452 | if ($current_filter eq $filter) { | ||
453 | $found = 1; | ||
454 | } | ||
455 | } elsif (/\A \<UniqueIdentifier\>\{(.*?)\}\<\/UniqueIdentifier\>\Z/) { | ||
456 | $visualc_references{$1} = $current_filter; # gather up existing GUIDs to avoid duplicates. | ||
457 | $existing_filters{$current_filter} = $1; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | if (not $found) { # didn't find it? We need to build filters. | ||
462 | my $subpath = ''; | ||
463 | my @splitpath = split(/\\/, $filter); | ||
464 | while (my $elem = shift(@splitpath)) { | ||
465 | $subpath .= "\\" if ($subpath ne ''); | ||
466 | $subpath .= $elem; | ||
467 | if (not $existing_filters{$subpath}) { | ||
468 | my $newgroupref = generate_visualc_id(); | ||
469 | $newgrptext .= " <Filter Include=\"$subpath\">\n"; | ||
470 | $newgrptext .= " <UniqueIdentifier>{$newgroupref}</UniqueIdentifier>\n"; | ||
471 | $newgrptext .= " </Filter>\n" | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | } | ||
477 | |||
478 | $tmpfname = "$vcxfiltersfname.tmp"; | ||
479 | open $fh, '>', $tmpfname or die("Failed to open '$tmpfname': $!\n"); | ||
480 | |||
481 | $added = 0; | ||
482 | $vcxgroup_state = 0; | ||
483 | $prevname = undef; | ||
484 | $lineno = 0; | ||
485 | foreach (@vcxfilters) { | ||
486 | $lineno++; | ||
487 | |||
488 | # We cheat here, because these lines are unique, we don't have to fully parse this file. | ||
489 | if ($vcxgroup_state == 0) { | ||
490 | if (/\A \<Filter Include\="(.*?)"\>\Z/) { | ||
491 | if ($newgrptext ne '') { | ||
492 | $vcxgroup_state = 1; | ||
493 | $prevname = undef; | ||
494 | } | ||
495 | } elsif (/\A \<ClInclude .*\Z/) { | ||
496 | if ($isheader) { | ||
497 | $vcxgroup_state = 2; | ||
498 | $prevname = undef; | ||
499 | } | ||
500 | } elsif (/\A \<ClCompile .*\Z/) { | ||
501 | if (not $isheader) { | ||
502 | $vcxgroup_state = 3; | ||
503 | $prevname = undef; | ||
504 | } | ||
505 | } | ||
506 | } | ||
507 | |||
508 | # Don't do elsif, we need to check this line again. | ||
509 | if ($vcxgroup_state == 1) { | ||
510 | if (/\A \<\/ItemGroup\>\Z/) { | ||
511 | print $fh $newgrptext; | ||
512 | $newgrptext = ''; | ||
513 | $vcxgroup_state = 0; | ||
514 | } | ||
515 | } elsif ($vcxgroup_state == 2) { | ||
516 | if (/\A <ClInclude Include="(.*?)"/) { | ||
517 | my $nextname = $1; | ||
518 | if ((not $added) && (((not defined $prevname) || (uc($prevname) lt uc($addvcxpath))) && (uc($nextname) gt uc($addvcxpath)))) { | ||
519 | print $fh " <ClInclude Include=\"$addvcxpath\""; | ||
520 | if ($filter ne '') { | ||
521 | print $fh ">\n"; | ||
522 | print $fh " <Filter>$filter</Filter>\n"; | ||
523 | print $fh " </ClInclude>\n"; | ||
524 | } else { | ||
525 | print $fh " />\n"; | ||
526 | } | ||
527 | $added = 1; | ||
528 | } | ||
529 | $prevname = $nextname; | ||
530 | } elsif (/\A \<\/ItemGroup\>\Z/) { | ||
531 | if ((not $added) && ((not defined $prevname) || (uc($prevname) lt uc($addvcxpath)))) { | ||
532 | print $fh " <ClInclude Include=\"$addvcxpath\""; | ||
533 | if ($filter ne '') { | ||
534 | print $fh ">\n"; | ||
535 | print $fh " <Filter>$filter</Filter>\n"; | ||
536 | print $fh " </ClInclude>\n"; | ||
537 | } else { | ||
538 | print $fh " />\n"; | ||
539 | } | ||
540 | $added = 1; | ||
541 | } | ||
542 | $vcxgroup_state = 0; | ||
543 | } | ||
544 | } elsif ($vcxgroup_state == 3) { | ||
545 | if (/\A <ClCompile Include="(.*?)"/) { | ||
546 | my $nextname = $1; | ||
547 | if ((not $added) && (((not defined $prevname) || (uc($prevname) lt uc($addvcxpath))) && (uc($nextname) gt uc($addvcxpath)))) { | ||
548 | print $fh " <ClCompile Include=\"$addvcxpath\""; | ||
549 | if ($filter ne '') { | ||
550 | print $fh ">\n"; | ||
551 | print $fh " <Filter>$filter</Filter>\n"; | ||
552 | print $fh " </ClCompile>\n"; | ||
553 | } else { | ||
554 | print $fh " />\n"; | ||
555 | } | ||
556 | $added = 1; | ||
557 | } | ||
558 | $prevname = $nextname; | ||
559 | } elsif (/\A \<\/ItemGroup\>\Z/) { | ||
560 | if ((not $added) && ((not defined $prevname) || (uc($prevname) lt uc($addvcxpath)))) { | ||
561 | print $fh " <ClCompile Include=\"$addvcxpath\""; | ||
562 | if ($filter ne '') { | ||
563 | print $fh ">\n"; | ||
564 | print $fh " <Filter>$filter</Filter>\n"; | ||
565 | print $fh " </ClCompile>\n"; | ||
566 | } else { | ||
567 | print $fh " />\n"; | ||
568 | } | ||
569 | $added = 1; | ||
570 | } | ||
571 | $vcxgroup_state = 0; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | print $fh "$_\n"; | ||
576 | } | ||
577 | |||
578 | close($fh); | ||
579 | rename($tmpfname, $vcxfiltersfname); | ||
580 | } | ||
581 | |||
582 | |||
583 | # Mainline! | ||
584 | |||
585 | chdir(dirname($0)); # assumed to be in build-scripts | ||
586 | chdir('..'); # head to root of source tree. | ||
587 | |||
588 | foreach (@ARGV) { | ||
589 | s/\A\.\///; # Turn "./path/to/file.txt" into "path/to/file.txt" | ||
590 | my $arg = $_; | ||
591 | process_xcode($arg, 'Xcode/SDL/SDL.xcodeproj/project.pbxproj'); | ||
592 | process_visualstudio($arg, 'VisualC/SDL/SDL.vcxproj'); | ||
593 | process_visualstudio($arg, 'VisualC-GDK/SDL/SDL.vcxproj'); | ||
594 | } | ||
595 | |||
596 | print("Done. Please run `git diff` and make sure this looks okay!\n"); | ||
597 | |||
598 | exit(0); | ||
599 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/androidbuildlibs.sh b/src/contrib/SDL-3.2.20/build-scripts/androidbuildlibs.sh new file mode 100755 index 0000000..1004a98 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/androidbuildlibs.sh | |||
@@ -0,0 +1,85 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Build the Android libraries without needing a project | ||
4 | # (AndroidManifest.xml, jni/{Application,Android}.mk, etc.) | ||
5 | # | ||
6 | # Usage: androidbuildlibs.sh [arg for ndk-build ...]" | ||
7 | # | ||
8 | # Useful NDK arguments: | ||
9 | # | ||
10 | # NDK_DEBUG=1 - build debug version | ||
11 | # NDK_LIBS_OUT=<dest> - specify alternate destination for installable | ||
12 | # modules. | ||
13 | # | ||
14 | |||
15 | |||
16 | # Android.mk is in srcdir | ||
17 | srcdir=`dirname $0`/.. | ||
18 | srcdir=`cd $srcdir && pwd` | ||
19 | cd $srcdir | ||
20 | |||
21 | |||
22 | # | ||
23 | # Create the build directories | ||
24 | # | ||
25 | |||
26 | build=build | ||
27 | buildandroid=$build/android | ||
28 | platform=android-21 | ||
29 | abi="arm64-v8a" # "armeabi-v7a arm64-v8a x86 x86_64" | ||
30 | obj= | ||
31 | lib= | ||
32 | ndk_args= | ||
33 | flexpage=true | ||
34 | |||
35 | # Allow an external caller to specify locations and platform. | ||
36 | while [ $# -gt 0 ]; do | ||
37 | arg=$1 | ||
38 | if [ "${arg:0:8}" == "NDK_OUT=" ]; then | ||
39 | obj=${arg#NDK_OUT=} | ||
40 | elif [ "${arg:0:13}" == "NDK_LIBS_OUT=" ]; then | ||
41 | lib=${arg#NDK_LIBS_OUT=} | ||
42 | elif [ "${arg:0:13}" == "APP_PLATFORM=" ]; then | ||
43 | platform=${arg#APP_PLATFORM=} | ||
44 | elif [ "${arg:0:8}" == "APP_ABI=" ]; then | ||
45 | abi=${arg#APP_ABI=} | ||
46 | elif [ "${arg:0:32}" == "APP_SUPPORT_FLEXIBLE_PAGE_SIZES=" ]; then | ||
47 | flexpage=${arg#APP_SUPPORT_FLEXIBLE_PAGE_SIZES=} | ||
48 | else | ||
49 | ndk_args="$ndk_args $arg" | ||
50 | fi | ||
51 | shift | ||
52 | done | ||
53 | |||
54 | if [ -z $obj ]; then | ||
55 | obj=$buildandroid/obj | ||
56 | fi | ||
57 | if [ -z $lib ]; then | ||
58 | lib=$buildandroid/lib | ||
59 | fi | ||
60 | |||
61 | for dir in $build $buildandroid $obj $lib; do | ||
62 | if test -d $dir; then | ||
63 | : | ||
64 | else | ||
65 | mkdir $dir || exit 1 | ||
66 | fi | ||
67 | done | ||
68 | |||
69 | |||
70 | # APP_* variables set in the environment here will not be seen by the | ||
71 | # ndk-build makefile segments that use them, e.g., default-application.mk. | ||
72 | # For consistency, pass all values on the command line. | ||
73 | # | ||
74 | # Add support for Google Play 16 KB Page size requirement: | ||
75 | # https://developer.android.com/guide/practices/page-sizes#ndk-build | ||
76 | ndk-build \ | ||
77 | NDK_PROJECT_PATH=null \ | ||
78 | NDK_OUT=$obj \ | ||
79 | NDK_LIBS_OUT=$lib \ | ||
80 | APP_BUILD_SCRIPT=Android.mk \ | ||
81 | APP_ABI="$abi" \ | ||
82 | APP_PLATFORM="$platform" \ | ||
83 | APP_MODULES="SDL3" \ | ||
84 | APP_SUPPORT_FLEXIBLE_PAGE_SIZES="$flexpage" \ | ||
85 | $ndk_args | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/build-release.py b/src/contrib/SDL-3.2.20/build-scripts/build-release.py new file mode 100755 index 0000000..f3faa06 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/build-release.py | |||
@@ -0,0 +1,1556 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | |||
3 | """ | ||
4 | This script is shared between SDL2, SDL3, and all satellite libraries. | ||
5 | Don't specialize this script for doing project-specific modifications. | ||
6 | Rather, modify release-info.json. | ||
7 | """ | ||
8 | |||
9 | import argparse | ||
10 | import collections | ||
11 | import dataclasses | ||
12 | from collections.abc import Callable | ||
13 | import contextlib | ||
14 | import datetime | ||
15 | import fnmatch | ||
16 | import glob | ||
17 | import io | ||
18 | import json | ||
19 | import logging | ||
20 | import multiprocessing | ||
21 | import os | ||
22 | from pathlib import Path | ||
23 | import platform | ||
24 | import re | ||
25 | import shlex | ||
26 | import shutil | ||
27 | import subprocess | ||
28 | import sys | ||
29 | import tarfile | ||
30 | import tempfile | ||
31 | import textwrap | ||
32 | import typing | ||
33 | import zipfile | ||
34 | |||
35 | |||
36 | logger = logging.getLogger(__name__) | ||
37 | GIT_HASH_FILENAME = ".git-hash" | ||
38 | REVISION_TXT = "REVISION.txt" | ||
39 | |||
40 | RE_ILLEGAL_MINGW_LIBRARIES = re.compile(r"(?:lib)?(?:gcc|(?:std)?c[+][+]|(?:win)?pthread).*", flags=re.I) | ||
41 | |||
42 | |||
43 | def safe_isotime_to_datetime(str_isotime: str) -> datetime.datetime: | ||
44 | try: | ||
45 | return datetime.datetime.fromisoformat(str_isotime) | ||
46 | except ValueError: | ||
47 | pass | ||
48 | logger.warning("Invalid iso time: %s", str_isotime) | ||
49 | if str_isotime[-6:-5] in ("+", "-"): | ||
50 | # Commits can have isotime with invalid timezone offset (e.g. "2021-07-04T20:01:40+32:00") | ||
51 | modified_str_isotime = str_isotime[:-6] + "+00:00" | ||
52 | try: | ||
53 | return datetime.datetime.fromisoformat(modified_str_isotime) | ||
54 | except ValueError: | ||
55 | pass | ||
56 | raise ValueError(f"Invalid isotime: {str_isotime}") | ||
57 | |||
58 | |||
59 | def arc_join(*parts: list[str]) -> str: | ||
60 | assert all(p[:1] != "/" and p[-1:] != "/" for p in parts), f"None of {parts} may start or end with '/'" | ||
61 | return "/".join(p for p in parts if p) | ||
62 | |||
63 | |||
64 | @dataclasses.dataclass(frozen=True) | ||
65 | class VsArchPlatformConfig: | ||
66 | arch: str | ||
67 | configuration: str | ||
68 | platform: str | ||
69 | |||
70 | def extra_context(self): | ||
71 | return { | ||
72 | "ARCH": self.arch, | ||
73 | "CONFIGURATION": self.configuration, | ||
74 | "PLATFORM": self.platform, | ||
75 | } | ||
76 | |||
77 | |||
78 | @contextlib.contextmanager | ||
79 | def chdir(path): | ||
80 | original_cwd = os.getcwd() | ||
81 | try: | ||
82 | os.chdir(path) | ||
83 | yield | ||
84 | finally: | ||
85 | os.chdir(original_cwd) | ||
86 | |||
87 | |||
88 | class Executer: | ||
89 | def __init__(self, root: Path, dry: bool=False): | ||
90 | self.root = root | ||
91 | self.dry = dry | ||
92 | |||
93 | def run(self, cmd, cwd=None, env=None): | ||
94 | logger.info("Executing args=%r", cmd) | ||
95 | sys.stdout.flush() | ||
96 | if not self.dry: | ||
97 | subprocess.check_call(cmd, cwd=cwd or self.root, env=env, text=True) | ||
98 | |||
99 | def check_output(self, cmd, cwd=None, dry_out=None, env=None, text=True): | ||
100 | logger.info("Executing args=%r", cmd) | ||
101 | sys.stdout.flush() | ||
102 | if self.dry: | ||
103 | return dry_out | ||
104 | return subprocess.check_output(cmd, cwd=cwd or self.root, env=env, text=text) | ||
105 | |||
106 | |||
107 | class SectionPrinter: | ||
108 | @contextlib.contextmanager | ||
109 | def group(self, title: str): | ||
110 | print(f"{title}:") | ||
111 | yield | ||
112 | |||
113 | |||
114 | class GitHubSectionPrinter(SectionPrinter): | ||
115 | def __init__(self): | ||
116 | super().__init__() | ||
117 | self.in_group = False | ||
118 | |||
119 | @contextlib.contextmanager | ||
120 | def group(self, title: str): | ||
121 | print(f"::group::{title}") | ||
122 | assert not self.in_group, "Can enter a group only once" | ||
123 | self.in_group = True | ||
124 | yield | ||
125 | self.in_group = False | ||
126 | print("::endgroup::") | ||
127 | |||
128 | |||
129 | class VisualStudio: | ||
130 | def __init__(self, executer: Executer, year: typing.Optional[str]=None): | ||
131 | self.executer = executer | ||
132 | self.vsdevcmd = self.find_vsdevcmd(year) | ||
133 | self.msbuild = self.find_msbuild() | ||
134 | |||
135 | @property | ||
136 | def dry(self) -> bool: | ||
137 | return self.executer.dry | ||
138 | |||
139 | VS_YEAR_TO_VERSION = { | ||
140 | "2022": 17, | ||
141 | "2019": 16, | ||
142 | "2017": 15, | ||
143 | "2015": 14, | ||
144 | "2013": 12, | ||
145 | } | ||
146 | |||
147 | def find_vsdevcmd(self, year: typing.Optional[str]=None) -> typing.Optional[Path]: | ||
148 | vswhere_spec = ["-latest"] | ||
149 | if year is not None: | ||
150 | try: | ||
151 | version = self.VS_YEAR_TO_VERSION[year] | ||
152 | except KeyError: | ||
153 | logger.error("Invalid Visual Studio year") | ||
154 | return None | ||
155 | vswhere_spec.extend(["-version", f"[{version},{version+1})"]) | ||
156 | vswhere_cmd = ["vswhere"] + vswhere_spec + ["-property", "installationPath"] | ||
157 | vs_install_path = Path(self.executer.check_output(vswhere_cmd, dry_out="/tmp").strip()) | ||
158 | logger.info("VS install_path = %s", vs_install_path) | ||
159 | assert vs_install_path.is_dir(), "VS installation path does not exist" | ||
160 | vsdevcmd_path = vs_install_path / "Common7/Tools/vsdevcmd.bat" | ||
161 | logger.info("vsdevcmd path = %s", vsdevcmd_path) | ||
162 | if self.dry: | ||
163 | vsdevcmd_path.parent.mkdir(parents=True, exist_ok=True) | ||
164 | vsdevcmd_path.touch(exist_ok=True) | ||
165 | assert vsdevcmd_path.is_file(), "vsdevcmd.bat batch file does not exist" | ||
166 | return vsdevcmd_path | ||
167 | |||
168 | def find_msbuild(self) -> typing.Optional[Path]: | ||
169 | vswhere_cmd = ["vswhere", "-latest", "-requires", "Microsoft.Component.MSBuild", "-find", r"MSBuild\**\Bin\MSBuild.exe"] | ||
170 | msbuild_path = Path(self.executer.check_output(vswhere_cmd, dry_out="/tmp/MSBuild.exe").strip()) | ||
171 | logger.info("MSBuild path = %s", msbuild_path) | ||
172 | if self.dry: | ||
173 | msbuild_path.parent.mkdir(parents=True, exist_ok=True) | ||
174 | msbuild_path.touch(exist_ok=True) | ||
175 | assert msbuild_path.is_file(), "MSBuild.exe does not exist" | ||
176 | return msbuild_path | ||
177 | |||
178 | def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path]): | ||
179 | assert projects, "Need at least one project to build" | ||
180 | |||
181 | vsdev_cmd_str = f"\"{self.vsdevcmd}\" -arch={arch_platform.arch}" | ||
182 | msbuild_cmd_str = " && ".join([f"\"{self.msbuild}\" \"{project}\" /m /p:BuildInParallel=true /p:Platform={arch_platform.platform} /p:Configuration={arch_platform.configuration}" for project in projects]) | ||
183 | bat_contents = f"{vsdev_cmd_str} && {msbuild_cmd_str}\n" | ||
184 | bat_path = Path(tempfile.gettempdir()) / "cmd.bat" | ||
185 | with bat_path.open("w") as f: | ||
186 | f.write(bat_contents) | ||
187 | |||
188 | logger.info("Running cmd.exe script (%s): %s", bat_path, bat_contents) | ||
189 | cmd = ["cmd.exe", "/D", "/E:ON", "/V:OFF", "/S", "/C", f"CALL {str(bat_path)}"] | ||
190 | self.executer.run(cmd) | ||
191 | |||
192 | |||
193 | class Archiver: | ||
194 | def __init__(self, zip_path: typing.Optional[Path]=None, tgz_path: typing.Optional[Path]=None, txz_path: typing.Optional[Path]=None): | ||
195 | self._zip_files = [] | ||
196 | self._tar_files = [] | ||
197 | self._added_files = set() | ||
198 | if zip_path: | ||
199 | self._zip_files.append(zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED)) | ||
200 | if tgz_path: | ||
201 | self._tar_files.append(tarfile.open(tgz_path, "w:gz")) | ||
202 | if txz_path: | ||
203 | self._tar_files.append(tarfile.open(txz_path, "w:xz")) | ||
204 | |||
205 | @property | ||
206 | def added_files(self) -> set[str]: | ||
207 | return self._added_files | ||
208 | |||
209 | def add_file_data(self, arcpath: str, data: bytes, mode: int, time: datetime.datetime): | ||
210 | for zf in self._zip_files: | ||
211 | file_data_time = (time.year, time.month, time.day, time.hour, time.minute, time.second) | ||
212 | zip_info = zipfile.ZipInfo(filename=arcpath, date_time=file_data_time) | ||
213 | zip_info.external_attr = mode << 16 | ||
214 | zip_info.compress_type = zipfile.ZIP_DEFLATED | ||
215 | zf.writestr(zip_info, data=data) | ||
216 | for tf in self._tar_files: | ||
217 | tar_info = tarfile.TarInfo(arcpath) | ||
218 | tar_info.type = tarfile.REGTYPE | ||
219 | tar_info.mode = mode | ||
220 | tar_info.size = len(data) | ||
221 | tar_info.mtime = int(time.timestamp()) | ||
222 | tf.addfile(tar_info, fileobj=io.BytesIO(data)) | ||
223 | |||
224 | self._added_files.add(arcpath) | ||
225 | |||
226 | def add_symlink(self, arcpath: str, target: str, time: datetime.datetime, files_for_zip): | ||
227 | logger.debug("Adding symlink (target=%r) -> %s", target, arcpath) | ||
228 | for zf in self._zip_files: | ||
229 | file_data_time = (time.year, time.month, time.day, time.hour, time.minute, time.second) | ||
230 | for f in files_for_zip: | ||
231 | zip_info = zipfile.ZipInfo(filename=f["arcpath"], date_time=file_data_time) | ||
232 | zip_info.external_attr = f["mode"] << 16 | ||
233 | zip_info.compress_type = zipfile.ZIP_DEFLATED | ||
234 | zf.writestr(zip_info, data=f["data"]) | ||
235 | for tf in self._tar_files: | ||
236 | tar_info = tarfile.TarInfo(arcpath) | ||
237 | tar_info.type = tarfile.SYMTYPE | ||
238 | tar_info.mode = 0o777 | ||
239 | tar_info.mtime = int(time.timestamp()) | ||
240 | tar_info.linkname = target | ||
241 | tf.addfile(tar_info) | ||
242 | |||
243 | self._added_files.update(f["arcpath"] for f in files_for_zip) | ||
244 | |||
245 | def add_git_hash(self, arcdir: str, commit: str, time: datetime.datetime): | ||
246 | arcpath = arc_join(arcdir, GIT_HASH_FILENAME) | ||
247 | data = f"{commit}\n".encode() | ||
248 | self.add_file_data(arcpath=arcpath, data=data, mode=0o100644, time=time) | ||
249 | |||
250 | def add_file_path(self, arcpath: str, path: Path): | ||
251 | assert path.is_file(), f"{path} should be a file" | ||
252 | logger.debug("Adding %s -> %s", path, arcpath) | ||
253 | for zf in self._zip_files: | ||
254 | zf.write(path, arcname=arcpath) | ||
255 | for tf in self._tar_files: | ||
256 | tf.add(path, arcname=arcpath) | ||
257 | |||
258 | def add_file_directory(self, arcdirpath: str, dirpath: Path): | ||
259 | assert dirpath.is_dir() | ||
260 | if arcdirpath and arcdirpath[-1:] != "/": | ||
261 | arcdirpath += "/" | ||
262 | for f in dirpath.iterdir(): | ||
263 | if f.is_file(): | ||
264 | arcpath = f"{arcdirpath}{f.name}" | ||
265 | logger.debug("Adding %s to %s", f, arcpath) | ||
266 | self.add_file_path(arcpath=arcpath, path=f) | ||
267 | |||
268 | def close(self): | ||
269 | # Archiver is intentionally made invalid after this function | ||
270 | del self._zip_files | ||
271 | self._zip_files = None | ||
272 | del self._tar_files | ||
273 | self._tar_files = None | ||
274 | |||
275 | def __enter__(self): | ||
276 | return self | ||
277 | |||
278 | def __exit__(self, type, value, traceback): | ||
279 | self.close() | ||
280 | |||
281 | |||
282 | class NodeInArchive: | ||
283 | def __init__(self, arcpath: str, path: typing.Optional[Path]=None, data: typing.Optional[bytes]=None, mode: typing.Optional[int]=None, symtarget: typing.Optional[str]=None, time: typing.Optional[datetime.datetime]=None, directory: bool=False): | ||
284 | self.arcpath = arcpath | ||
285 | self.path = path | ||
286 | self.data = data | ||
287 | self.mode = mode | ||
288 | self.symtarget = symtarget | ||
289 | self.time = time | ||
290 | self.directory = directory | ||
291 | |||
292 | @classmethod | ||
293 | def from_fs(cls, arcpath: str, path: Path, mode: int=0o100644, time: typing.Optional[datetime.datetime]=None) -> "NodeInArchive": | ||
294 | if time is None: | ||
295 | time = datetime.datetime.fromtimestamp(os.stat(path).st_mtime) | ||
296 | return cls(arcpath=arcpath, path=path, mode=mode) | ||
297 | |||
298 | @classmethod | ||
299 | def from_data(cls, arcpath: str, data: bytes, time: datetime.datetime) -> "NodeInArchive": | ||
300 | return cls(arcpath=arcpath, data=data, time=time, mode=0o100644) | ||
301 | |||
302 | @classmethod | ||
303 | def from_text(cls, arcpath: str, text: str, time: datetime.datetime) -> "NodeInArchive": | ||
304 | return cls.from_data(arcpath=arcpath, data=text.encode(), time=time) | ||
305 | |||
306 | @classmethod | ||
307 | def from_symlink(cls, arcpath: str, symtarget: str) -> "NodeInArchive": | ||
308 | return cls(arcpath=arcpath, symtarget=symtarget) | ||
309 | |||
310 | @classmethod | ||
311 | def from_directory(cls, arcpath: str) -> "NodeInArchive": | ||
312 | return cls(arcpath=arcpath, directory=True) | ||
313 | |||
314 | def __repr__(self) -> str: | ||
315 | return f"<{type(self).__name__}:arcpath={self.arcpath},path='{str(self.path)}',len(data)={len(self.data) if self.data else 'n/a'},directory={self.directory},symtarget={self.symtarget}>" | ||
316 | |||
317 | |||
318 | def configure_file(path: Path, context: dict[str, str]) -> bytes: | ||
319 | text = path.read_text() | ||
320 | return configure_text(text, context=context).encode() | ||
321 | |||
322 | |||
323 | def configure_text(text: str, context: dict[str, str]) -> str: | ||
324 | original_text = text | ||
325 | for txt, repl in context.items(): | ||
326 | text = text.replace(f"@<@{txt}@>@", repl) | ||
327 | success = all(thing not in text for thing in ("@<@", "@>@")) | ||
328 | if not success: | ||
329 | raise ValueError(f"Failed to configure {repr(original_text)}") | ||
330 | return text | ||
331 | |||
332 | |||
333 | def configure_text_list(text_list: list[str], context: dict[str, str]) -> list[str]: | ||
334 | return [configure_text(text=e, context=context) for e in text_list] | ||
335 | |||
336 | |||
337 | class ArchiveFileTree: | ||
338 | def __init__(self): | ||
339 | self._tree: dict[str, NodeInArchive] = {} | ||
340 | |||
341 | def add_file(self, file: NodeInArchive): | ||
342 | self._tree[file.arcpath] = file | ||
343 | |||
344 | def __iter__(self) -> typing.Iterable[NodeInArchive]: | ||
345 | yield from self._tree.values() | ||
346 | |||
347 | def __contains__(self, value: str) -> bool: | ||
348 | return value in self._tree | ||
349 | |||
350 | def get_latest_mod_time(self) -> datetime.datetime: | ||
351 | return max(item.time for item in self._tree.values() if item.time) | ||
352 | |||
353 | def add_to_archiver(self, archive_base: str, archiver: Archiver): | ||
354 | remaining_symlinks = set() | ||
355 | added_files = dict() | ||
356 | |||
357 | def calculate_symlink_target(s: NodeInArchive) -> str: | ||
358 | dest_dir = os.path.dirname(s.arcpath) | ||
359 | if dest_dir: | ||
360 | dest_dir += "/" | ||
361 | target = dest_dir + s.symtarget | ||
362 | while True: | ||
363 | new_target, n = re.subn(r"([^/]+/+[.]{2}/)", "", target) | ||
364 | target = new_target | ||
365 | if not n: | ||
366 | break | ||
367 | return target | ||
368 | |||
369 | # Add files in first pass | ||
370 | for arcpath, node in self._tree.items(): | ||
371 | assert node is not None, f"{arcpath} -> node" | ||
372 | if node.data is not None: | ||
373 | archiver.add_file_data(arcpath=arc_join(archive_base, arcpath), data=node.data, time=node.time, mode=node.mode) | ||
374 | assert node.arcpath is not None, f"{node=}" | ||
375 | added_files[node.arcpath] = node | ||
376 | elif node.path is not None: | ||
377 | archiver.add_file_path(arcpath=arc_join(archive_base, arcpath), path=node.path) | ||
378 | assert node.arcpath is not None, f"{node=}" | ||
379 | added_files[node.arcpath] = node | ||
380 | elif node.symtarget is not None: | ||
381 | remaining_symlinks.add(node) | ||
382 | elif node.directory: | ||
383 | pass | ||
384 | else: | ||
385 | raise ValueError(f"Invalid Archive Node: {repr(node)}") | ||
386 | |||
387 | assert None not in added_files | ||
388 | |||
389 | # Resolve symlinks in second pass: zipfile does not support symlinks, so add files to zip archive | ||
390 | while True: | ||
391 | if not remaining_symlinks: | ||
392 | break | ||
393 | symlinks_this_time = set() | ||
394 | extra_added_files = {} | ||
395 | for symlink in remaining_symlinks: | ||
396 | symlink_files_for_zip = {} | ||
397 | symlink_target_path = calculate_symlink_target(symlink) | ||
398 | if symlink_target_path in added_files: | ||
399 | symlink_files_for_zip[symlink.arcpath] = added_files[symlink_target_path] | ||
400 | else: | ||
401 | symlink_target_path_slash = symlink_target_path + "/" | ||
402 | for added_file in added_files: | ||
403 | if added_file.startswith(symlink_target_path_slash): | ||
404 | path_in_symlink = symlink.arcpath + "/" + added_file.removeprefix(symlink_target_path_slash) | ||
405 | symlink_files_for_zip[path_in_symlink] = added_files[added_file] | ||
406 | if symlink_files_for_zip: | ||
407 | symlinks_this_time.add(symlink) | ||
408 | extra_added_files.update(symlink_files_for_zip) | ||
409 | files_for_zip = [{"arcpath": f"{archive_base}/{sym_path}", "data": sym_info.data, "mode": sym_info.mode} for sym_path, sym_info in symlink_files_for_zip.items()] | ||
410 | archiver.add_symlink(arcpath=f"{archive_base}/{symlink.arcpath}", target=symlink.symtarget, time=symlink.time, files_for_zip=files_for_zip) | ||
411 | # if not symlinks_this_time: | ||
412 | # logger.info("files added: %r", set(path for path in added_files.keys())) | ||
413 | assert symlinks_this_time, f"No targets found for symlinks: {remaining_symlinks}" | ||
414 | remaining_symlinks.difference_update(symlinks_this_time) | ||
415 | added_files.update(extra_added_files) | ||
416 | |||
417 | def add_directory_tree(self, arc_dir: str, path: Path, time: datetime.datetime): | ||
418 | assert path.is_dir() | ||
419 | for files_dir, _, filenames in os.walk(path): | ||
420 | files_dir_path = Path(files_dir) | ||
421 | rel_files_path = files_dir_path.relative_to(path) | ||
422 | for filename in filenames: | ||
423 | self.add_file(NodeInArchive.from_fs(arcpath=arc_join(arc_dir, str(rel_files_path), filename), path=files_dir_path / filename, time=time)) | ||
424 | |||
425 | def _add_files_recursively(self, arc_dir: str, paths: list[Path], time: datetime.datetime): | ||
426 | logger.debug(f"_add_files_recursively({arc_dir=} {paths=})") | ||
427 | for path in paths: | ||
428 | arcpath = arc_join(arc_dir, path.name) | ||
429 | if path.is_file(): | ||
430 | logger.debug("Adding %s as %s", path, arcpath) | ||
431 | self.add_file(NodeInArchive.from_fs(arcpath=arcpath, path=path, time=time)) | ||
432 | elif path.is_dir(): | ||
433 | self._add_files_recursively(arc_dir=arc_join(arc_dir, path.name), paths=list(path.iterdir()), time=time) | ||
434 | else: | ||
435 | raise ValueError(f"Unsupported file type to add recursively: {path}") | ||
436 | |||
437 | def add_file_mapping(self, arc_dir: str, file_mapping: dict[str, list[str]], file_mapping_root: Path, context: dict[str, str], time: datetime.datetime): | ||
438 | for meta_rel_destdir, meta_file_globs in file_mapping.items(): | ||
439 | rel_destdir = configure_text(meta_rel_destdir, context=context) | ||
440 | assert "@" not in rel_destdir, f"archive destination should not contain an @ after configuration ({repr(meta_rel_destdir)}->{repr(rel_destdir)})" | ||
441 | for meta_file_glob in meta_file_globs: | ||
442 | file_glob = configure_text(meta_file_glob, context=context) | ||
443 | assert "@" not in rel_destdir, f"archive glob should not contain an @ after configuration ({repr(meta_file_glob)}->{repr(file_glob)})" | ||
444 | if ":" in file_glob: | ||
445 | original_path, new_filename = file_glob.rsplit(":", 1) | ||
446 | assert ":" not in original_path, f"Too many ':' in {repr(file_glob)}" | ||
447 | assert "/" not in new_filename, f"New filename cannot contain a '/' in {repr(file_glob)}" | ||
448 | path = file_mapping_root / original_path | ||
449 | arcpath = arc_join(arc_dir, rel_destdir, new_filename) | ||
450 | if path.suffix == ".in": | ||
451 | data = configure_file(path, context=context) | ||
452 | logger.debug("Adding processed %s -> %s", path, arcpath) | ||
453 | self.add_file(NodeInArchive.from_data(arcpath=arcpath, data=data, time=time)) | ||
454 | else: | ||
455 | logger.debug("Adding %s -> %s", path, arcpath) | ||
456 | self.add_file(NodeInArchive.from_fs(arcpath=arcpath, path=path, time=time)) | ||
457 | else: | ||
458 | relative_file_paths = glob.glob(file_glob, root_dir=file_mapping_root) | ||
459 | assert relative_file_paths, f"Glob '{file_glob}' does not match any file" | ||
460 | self._add_files_recursively(arc_dir=arc_join(arc_dir, rel_destdir), paths=[file_mapping_root / p for p in relative_file_paths], time=time) | ||
461 | |||
462 | |||
463 | class SourceCollector: | ||
464 | # TreeItem = collections.namedtuple("TreeItem", ("path", "mode", "data", "symtarget", "directory", "time")) | ||
465 | def __init__(self, root: Path, commit: str, filter: typing.Optional[Callable[[str], bool]], executer: Executer): | ||
466 | self.root = root | ||
467 | self.commit = commit | ||
468 | self.filter = filter | ||
469 | self.executer = executer | ||
470 | |||
471 | def get_archive_file_tree(self) -> ArchiveFileTree: | ||
472 | git_archive_args = ["git", "archive", "--format=tar.gz", self.commit, "-o", "/dev/stdout"] | ||
473 | logger.info("Executing args=%r", git_archive_args) | ||
474 | contents_tgz = subprocess.check_output(git_archive_args, cwd=self.root, text=False) | ||
475 | tar_archive = tarfile.open(fileobj=io.BytesIO(contents_tgz), mode="r:gz") | ||
476 | filenames = tuple(m.name for m in tar_archive if (m.isfile() or m.issym())) | ||
477 | |||
478 | file_times = self._get_file_times(paths=filenames) | ||
479 | git_contents = ArchiveFileTree() | ||
480 | for ti in tar_archive: | ||
481 | if self.filter and not self.filter(ti.name): | ||
482 | continue | ||
483 | data = None | ||
484 | symtarget = None | ||
485 | directory = False | ||
486 | file_time = None | ||
487 | if ti.isfile(): | ||
488 | contents_file = tar_archive.extractfile(ti.name) | ||
489 | data = contents_file.read() | ||
490 | file_time = file_times[ti.name] | ||
491 | elif ti.issym(): | ||
492 | symtarget = ti.linkname | ||
493 | file_time = file_times[ti.name] | ||
494 | elif ti.isdir(): | ||
495 | directory = True | ||
496 | else: | ||
497 | raise ValueError(f"{ti.name}: unknown type") | ||
498 | node = NodeInArchive(arcpath=ti.name, data=data, mode=ti.mode, symtarget=symtarget, time=file_time, directory=directory) | ||
499 | git_contents.add_file(node) | ||
500 | return git_contents | ||
501 | |||
502 | def _get_file_times(self, paths: tuple[str, ...]) -> dict[str, datetime.datetime]: | ||
503 | dry_out = textwrap.dedent("""\ | ||
504 | time=2024-03-14T15:40:25-07:00 | ||
505 | |||
506 | M\tCMakeLists.txt | ||
507 | """) | ||
508 | git_log_out = self.executer.check_output(["git", "log", "--name-status", '--pretty=time=%cI', self.commit], dry_out=dry_out, cwd=self.root).splitlines(keepends=False) | ||
509 | current_time = None | ||
510 | set_paths = set(paths) | ||
511 | path_times: dict[str, datetime.datetime] = {} | ||
512 | for line in git_log_out: | ||
513 | if not line: | ||
514 | continue | ||
515 | if line.startswith("time="): | ||
516 | current_time = safe_isotime_to_datetime(line.removeprefix("time=")) | ||
517 | continue | ||
518 | mod_type, file_paths = line.split(maxsplit=1) | ||
519 | assert current_time is not None | ||
520 | for file_path in file_paths.split("\t"): | ||
521 | if file_path in set_paths and file_path not in path_times: | ||
522 | path_times[file_path] = current_time | ||
523 | |||
524 | # FIXME: find out why some files are not shown in "git log" | ||
525 | # assert set(path_times.keys()) == set_paths | ||
526 | if set(path_times.keys()) != set_paths: | ||
527 | found_times = set(path_times.keys()) | ||
528 | paths_without_times = set_paths.difference(found_times) | ||
529 | logger.warning("No times found for these paths: %s", paths_without_times) | ||
530 | max_time = max(time for time in path_times.values()) | ||
531 | for path in paths_without_times: | ||
532 | path_times[path] = max_time | ||
533 | |||
534 | return path_times | ||
535 | |||
536 | |||
537 | class AndroidApiVersion: | ||
538 | def __init__(self, name: str, ints: tuple[int, ...]): | ||
539 | self.name = name | ||
540 | self.ints = ints | ||
541 | |||
542 | def __repr__(self) -> str: | ||
543 | return f"<{self.name} ({'.'.join(str(v) for v in self.ints)})>" | ||
544 | |||
545 | |||
546 | class Releaser: | ||
547 | def __init__(self, release_info: dict, commit: str, revision: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str, deps_path: Path, overwrite: bool, github: bool, fast: bool): | ||
548 | self.release_info = release_info | ||
549 | self.project = release_info["name"] | ||
550 | self.version = self.extract_sdl_version(root=root, release_info=release_info) | ||
551 | self.root = root | ||
552 | self.commit = commit | ||
553 | self.revision = revision | ||
554 | self.dist_path = dist_path | ||
555 | self.section_printer = section_printer | ||
556 | self.executer = executer | ||
557 | self.cmake_generator = cmake_generator | ||
558 | self.cpu_count = multiprocessing.cpu_count() | ||
559 | self.deps_path = deps_path | ||
560 | self.overwrite = overwrite | ||
561 | self.github = github | ||
562 | self.fast = fast | ||
563 | self.arc_time = datetime.datetime.now() | ||
564 | |||
565 | self.artifacts: dict[str, Path] = {} | ||
566 | |||
567 | def get_context(self, extra_context: typing.Optional[dict[str, str]]=None) -> dict[str, str]: | ||
568 | ctx = { | ||
569 | "PROJECT_NAME": self.project, | ||
570 | "PROJECT_VERSION": self.version, | ||
571 | "PROJECT_COMMIT": self.commit, | ||
572 | "PROJECT_REVISION": self.revision, | ||
573 | "PROJECT_ROOT": str(self.root), | ||
574 | } | ||
575 | if extra_context: | ||
576 | ctx.update(extra_context) | ||
577 | return ctx | ||
578 | |||
579 | @property | ||
580 | def dry(self) -> bool: | ||
581 | return self.executer.dry | ||
582 | |||
583 | def prepare(self): | ||
584 | logger.debug("Creating dist folder") | ||
585 | self.dist_path.mkdir(parents=True, exist_ok=True) | ||
586 | |||
587 | @classmethod | ||
588 | def _path_filter(cls, path: str) -> bool: | ||
589 | if ".gitmodules" in path: | ||
590 | return True | ||
591 | if path.startswith(".git"): | ||
592 | return False | ||
593 | return True | ||
594 | |||
595 | @classmethod | ||
596 | def _external_repo_path_filter(cls, path: str) -> bool: | ||
597 | if not cls._path_filter(path): | ||
598 | return False | ||
599 | if path.startswith("test/") or path.startswith("tests/"): | ||
600 | return False | ||
601 | return True | ||
602 | |||
603 | def create_source_archives(self) -> None: | ||
604 | source_collector = SourceCollector(root=self.root, commit=self.commit, executer=self.executer, filter=self._path_filter) | ||
605 | print(f"Collecting sources of {self.project}...") | ||
606 | archive_tree: ArchiveFileTree = source_collector.get_archive_file_tree() | ||
607 | latest_mod_time = archive_tree.get_latest_mod_time() | ||
608 | archive_tree.add_file(NodeInArchive.from_text(arcpath=REVISION_TXT, text=f"{self.revision}\n", time=latest_mod_time)) | ||
609 | archive_tree.add_file(NodeInArchive.from_text(arcpath=f"{GIT_HASH_FILENAME}", text=f"{self.commit}\n", time=latest_mod_time)) | ||
610 | archive_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["source"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=latest_mod_time) | ||
611 | |||
612 | if "Makefile.am" in archive_tree: | ||
613 | patched_time = latest_mod_time + datetime.timedelta(minutes=1) | ||
614 | print(f"Makefile.am detected -> touching aclocal.m4, */Makefile.in, configure") | ||
615 | for node_data in archive_tree: | ||
616 | arc_name = os.path.basename(node_data.arcpath) | ||
617 | arc_name_we, arc_name_ext = os.path.splitext(arc_name) | ||
618 | if arc_name in ("aclocal.m4", "configure", "Makefile.in"): | ||
619 | print(f"Bumping time of {node_data.arcpath}") | ||
620 | node_data.time = patched_time | ||
621 | |||
622 | archive_base = f"{self.project}-{self.version}" | ||
623 | zip_path = self.dist_path / f"{archive_base}.zip" | ||
624 | tgz_path = self.dist_path / f"{archive_base}.tar.gz" | ||
625 | txz_path = self.dist_path / f"{archive_base}.tar.xz" | ||
626 | |||
627 | logger.info("Creating zip/tgz/txz source archives ...") | ||
628 | if self.dry: | ||
629 | zip_path.touch() | ||
630 | tgz_path.touch() | ||
631 | txz_path.touch() | ||
632 | else: | ||
633 | with Archiver(zip_path=zip_path, tgz_path=tgz_path, txz_path=txz_path) as archiver: | ||
634 | print(f"Adding source files of {self.project}...") | ||
635 | archive_tree.add_to_archiver(archive_base=archive_base, archiver=archiver) | ||
636 | |||
637 | for extra_repo in self.release_info["source"].get("extra-repos", []): | ||
638 | extra_repo_root = self.root / extra_repo | ||
639 | assert (extra_repo_root / ".git").exists(), f"{extra_repo_root} must be a git repo" | ||
640 | extra_repo_commit = self.executer.check_output(["git", "rev-parse", "HEAD"], dry_out=f"gitsha-extra-repo-{extra_repo}", cwd=extra_repo_root).strip() | ||
641 | extra_repo_source_collector = SourceCollector(root=extra_repo_root, commit=extra_repo_commit, executer=self.executer, filter=self._external_repo_path_filter) | ||
642 | print(f"Collecting sources of {extra_repo} ...") | ||
643 | extra_repo_archive_tree = extra_repo_source_collector.get_archive_file_tree() | ||
644 | print(f"Adding source files of {extra_repo} ...") | ||
645 | extra_repo_archive_tree.add_to_archiver(archive_base=f"{archive_base}/{extra_repo}", archiver=archiver) | ||
646 | |||
647 | for file in self.release_info["source"]["checks"]: | ||
648 | assert f"{archive_base}/{file}" in archiver.added_files, f"'{archive_base}/{file}' must exist" | ||
649 | |||
650 | logger.info("... done") | ||
651 | |||
652 | self.artifacts["src-zip"] = zip_path | ||
653 | self.artifacts["src-tar-gz"] = tgz_path | ||
654 | self.artifacts["src-tar-xz"] = txz_path | ||
655 | |||
656 | if not self.dry: | ||
657 | with tgz_path.open("r+b") as f: | ||
658 | # Zero the embedded timestamp in the gzip'ed tarball | ||
659 | f.seek(4, 0) | ||
660 | f.write(b"\x00\x00\x00\x00") | ||
661 | |||
662 | def create_dmg(self, configuration: str="Release") -> None: | ||
663 | dmg_in = self.root / self.release_info["dmg"]["path"] | ||
664 | xcode_project = self.root / self.release_info["dmg"]["project"] | ||
665 | assert xcode_project.is_dir(), f"{xcode_project} must be a directory" | ||
666 | assert (xcode_project / "project.pbxproj").is_file, f"{xcode_project} must contain project.pbxproj" | ||
667 | if not self.fast: | ||
668 | dmg_in.unlink(missing_ok=True) | ||
669 | build_xcconfig = self.release_info["dmg"].get("build-xcconfig") | ||
670 | if build_xcconfig: | ||
671 | shutil.copy(self.root / build_xcconfig, xcode_project.parent / "build.xcconfig") | ||
672 | |||
673 | xcode_scheme = self.release_info["dmg"].get("scheme") | ||
674 | xcode_target = self.release_info["dmg"].get("target") | ||
675 | assert xcode_scheme or xcode_target, "dmg needs scheme or target" | ||
676 | assert not (xcode_scheme and xcode_target), "dmg cannot have both scheme and target set" | ||
677 | if xcode_scheme: | ||
678 | scheme_or_target = "-scheme" | ||
679 | target_like = xcode_scheme | ||
680 | else: | ||
681 | scheme_or_target = "-target" | ||
682 | target_like = xcode_target | ||
683 | self.executer.run(["xcodebuild", "ONLY_ACTIVE_ARCH=NO", "-project", xcode_project, scheme_or_target, target_like, "-configuration", configuration]) | ||
684 | if self.dry: | ||
685 | dmg_in.parent.mkdir(parents=True, exist_ok=True) | ||
686 | dmg_in.touch() | ||
687 | |||
688 | assert dmg_in.is_file(), f"{self.project}.dmg was not created by xcodebuild" | ||
689 | |||
690 | dmg_out = self.dist_path / f"{self.project}-{self.version}.dmg" | ||
691 | shutil.copy(dmg_in, dmg_out) | ||
692 | self.artifacts["dmg"] = dmg_out | ||
693 | |||
694 | @property | ||
695 | def git_hash_data(self) -> bytes: | ||
696 | return f"{self.commit}\n".encode() | ||
697 | |||
698 | def verify_mingw_library(self, triplet: str, path: Path): | ||
699 | objdump_output = self.executer.check_output([f"{triplet}-objdump", "-p", str(path)]) | ||
700 | libraries = re.findall(r"DLL Name: ([^\n]+)", objdump_output) | ||
701 | logger.info("%s (%s) libraries: %r", path, triplet, libraries) | ||
702 | illegal_libraries = list(filter(RE_ILLEGAL_MINGW_LIBRARIES.match, libraries)) | ||
703 | logger.error("Detected 'illegal' libraries: %r", illegal_libraries) | ||
704 | if illegal_libraries: | ||
705 | raise Exception(f"{path} links to illegal libraries: {illegal_libraries}") | ||
706 | |||
707 | def create_mingw_archives(self) -> None: | ||
708 | build_type = "Release" | ||
709 | build_parent_dir = self.root / "build-mingw" | ||
710 | ARCH_TO_GNU_ARCH = { | ||
711 | # "arm64": "aarch64", | ||
712 | "x86": "i686", | ||
713 | "x64": "x86_64", | ||
714 | } | ||
715 | ARCH_TO_TRIPLET = { | ||
716 | # "arm64": "aarch64-w64-mingw32", | ||
717 | "x86": "i686-w64-mingw32", | ||
718 | "x64": "x86_64-w64-mingw32", | ||
719 | } | ||
720 | |||
721 | new_env = dict(os.environ) | ||
722 | |||
723 | cmake_prefix_paths = [] | ||
724 | mingw_deps_path = self.deps_path / "mingw-deps" | ||
725 | |||
726 | if "dependencies" in self.release_info["mingw"]: | ||
727 | shutil.rmtree(mingw_deps_path, ignore_errors=True) | ||
728 | mingw_deps_path.mkdir() | ||
729 | |||
730 | for triplet in ARCH_TO_TRIPLET.values(): | ||
731 | (mingw_deps_path / triplet).mkdir() | ||
732 | |||
733 | def extract_filter(member: tarfile.TarInfo, path: str, /): | ||
734 | if member.name.startswith("SDL"): | ||
735 | member.name = "/".join(Path(member.name).parts[1:]) | ||
736 | return member | ||
737 | for dep in self.release_info.get("dependencies", {}): | ||
738 | extract_path = mingw_deps_path / f"extract-{dep}" | ||
739 | extract_path.mkdir() | ||
740 | with chdir(extract_path): | ||
741 | tar_path = self.deps_path / glob.glob(self.release_info["mingw"]["dependencies"][dep]["artifact"], root_dir=self.deps_path)[0] | ||
742 | logger.info("Extracting %s to %s", tar_path, mingw_deps_path) | ||
743 | assert tar_path.suffix in (".gz", ".xz") | ||
744 | with tarfile.open(tar_path, mode=f"r:{tar_path.suffix.strip('.')}") as tarf: | ||
745 | tarf.extractall(filter=extract_filter) | ||
746 | for arch, triplet in ARCH_TO_TRIPLET.items(): | ||
747 | install_cmd = self.release_info["mingw"]["dependencies"][dep]["install-command"] | ||
748 | extra_configure_data = { | ||
749 | "ARCH": ARCH_TO_GNU_ARCH[arch], | ||
750 | "TRIPLET": triplet, | ||
751 | "PREFIX": str(mingw_deps_path / triplet), | ||
752 | } | ||
753 | install_cmd = configure_text(install_cmd, context=self.get_context(extra_configure_data)) | ||
754 | self.executer.run(shlex.split(install_cmd), cwd=str(extract_path)) | ||
755 | |||
756 | dep_binpath = mingw_deps_path / triplet / "bin" | ||
757 | assert dep_binpath.is_dir(), f"{dep_binpath} for PATH should exist" | ||
758 | dep_pkgconfig = mingw_deps_path / triplet / "lib/pkgconfig" | ||
759 | assert dep_pkgconfig.is_dir(), f"{dep_pkgconfig} for PKG_CONFIG_PATH should exist" | ||
760 | |||
761 | new_env["PATH"] = os.pathsep.join([str(dep_binpath), new_env["PATH"]]) | ||
762 | new_env["PKG_CONFIG_PATH"] = str(dep_pkgconfig) | ||
763 | cmake_prefix_paths.append(mingw_deps_path) | ||
764 | |||
765 | new_env["CFLAGS"] = f"-O2 -ffile-prefix-map={self.root}=/src/{self.project}" | ||
766 | new_env["CXXFLAGS"] = f"-O2 -ffile-prefix-map={self.root}=/src/{self.project}" | ||
767 | |||
768 | assert any(system in self.release_info["mingw"] for system in ("autotools", "cmake")) | ||
769 | assert not all(system in self.release_info["mingw"] for system in ("autotools", "cmake")) | ||
770 | |||
771 | mingw_archs = set() | ||
772 | arc_root = f"{self.project}-{self.version}" | ||
773 | archive_file_tree = ArchiveFileTree() | ||
774 | |||
775 | if "autotools" in self.release_info["mingw"]: | ||
776 | for arch in self.release_info["mingw"]["autotools"]["archs"]: | ||
777 | triplet = ARCH_TO_TRIPLET[arch] | ||
778 | new_env["CC"] = f"{triplet}-gcc" | ||
779 | new_env["CXX"] = f"{triplet}-g++" | ||
780 | new_env["RC"] = f"{triplet}-windres" | ||
781 | |||
782 | assert arch not in mingw_archs | ||
783 | mingw_archs.add(arch) | ||
784 | |||
785 | build_path = build_parent_dir / f"build-{triplet}" | ||
786 | install_path = build_parent_dir / f"install-{triplet}" | ||
787 | shutil.rmtree(install_path, ignore_errors=True) | ||
788 | build_path.mkdir(parents=True, exist_ok=True) | ||
789 | context = self.get_context({ | ||
790 | "ARCH": arch, | ||
791 | "DEP_PREFIX": str(mingw_deps_path / triplet), | ||
792 | }) | ||
793 | extra_args = configure_text_list(text_list=self.release_info["mingw"]["autotools"]["args"], context=context) | ||
794 | |||
795 | with self.section_printer.group(f"Configuring MinGW {triplet} (autotools)"): | ||
796 | assert "@" not in " ".join(extra_args), f"@ should not be present in extra arguments ({extra_args})" | ||
797 | self.executer.run([ | ||
798 | self.root / "configure", | ||
799 | f"--prefix={install_path}", | ||
800 | f"--includedir=${{prefix}}/include", | ||
801 | f"--libdir=${{prefix}}/lib", | ||
802 | f"--bindir=${{prefix}}/bin", | ||
803 | f"--host={triplet}", | ||
804 | f"--build=x86_64-none-linux-gnu", | ||
805 | "CFLAGS=-O2", | ||
806 | "CXXFLAGS=-O2", | ||
807 | "LDFLAGS=-Wl,-s", | ||
808 | ] + extra_args, cwd=build_path, env=new_env) | ||
809 | with self.section_printer.group(f"Build MinGW {triplet} (autotools)"): | ||
810 | self.executer.run(["make", f"-j{self.cpu_count}"], cwd=build_path, env=new_env) | ||
811 | with self.section_printer.group(f"Install MinGW {triplet} (autotools)"): | ||
812 | self.executer.run(["make", "install"], cwd=build_path, env=new_env) | ||
813 | self.verify_mingw_library(triplet=ARCH_TO_TRIPLET[arch], path=install_path / "bin" / f"{self.project}.dll") | ||
814 | archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path, time=self.arc_time) | ||
815 | |||
816 | print("Recording arch-dependent extra files for MinGW development archive ...") | ||
817 | extra_context = { | ||
818 | "TRIPLET": ARCH_TO_TRIPLET[arch], | ||
819 | } | ||
820 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["mingw"]["autotools"].get("files", {}), file_mapping_root=self.root, context=self.get_context(extra_context=extra_context), time=self.arc_time) | ||
821 | |||
822 | if "cmake" in self.release_info["mingw"]: | ||
823 | assert self.release_info["mingw"]["cmake"]["shared-static"] in ("args", "both") | ||
824 | for arch in self.release_info["mingw"]["cmake"]["archs"]: | ||
825 | triplet = ARCH_TO_TRIPLET[arch] | ||
826 | new_env["CC"] = f"{triplet}-gcc" | ||
827 | new_env["CXX"] = f"{triplet}-g++" | ||
828 | new_env["RC"] = f"{triplet}-windres" | ||
829 | |||
830 | assert arch not in mingw_archs | ||
831 | mingw_archs.add(arch) | ||
832 | |||
833 | context = self.get_context({ | ||
834 | "ARCH": arch, | ||
835 | "DEP_PREFIX": str(mingw_deps_path / triplet), | ||
836 | }) | ||
837 | extra_args = configure_text_list(text_list=self.release_info["mingw"]["cmake"]["args"], context=context) | ||
838 | |||
839 | build_path = build_parent_dir / f"build-{triplet}" | ||
840 | install_path = build_parent_dir / f"install-{triplet}" | ||
841 | shutil.rmtree(install_path, ignore_errors=True) | ||
842 | build_path.mkdir(parents=True, exist_ok=True) | ||
843 | if self.release_info["mingw"]["cmake"]["shared-static"] == "args": | ||
844 | args_for_shared_static = ([], ) | ||
845 | elif self.release_info["mingw"]["cmake"]["shared-static"] == "both": | ||
846 | args_for_shared_static = (["-DBUILD_SHARED_LIBS=ON"], ["-DBUILD_SHARED_LIBS=OFF"]) | ||
847 | for arg_for_shared_static in args_for_shared_static: | ||
848 | with self.section_printer.group(f"Configuring MinGW {triplet} (CMake)"): | ||
849 | assert "@" not in " ".join(extra_args), f"@ should not be present in extra arguments ({extra_args})" | ||
850 | self.executer.run([ | ||
851 | f"cmake", | ||
852 | f"-S", str(self.root), "-B", str(build_path), | ||
853 | f"-DCMAKE_BUILD_TYPE={build_type}", | ||
854 | f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', | ||
855 | f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', | ||
856 | f"-DCMAKE_PREFIX_PATH={mingw_deps_path / triplet}", | ||
857 | f"-DCMAKE_INSTALL_PREFIX={install_path}", | ||
858 | f"-DCMAKE_INSTALL_INCLUDEDIR=include", | ||
859 | f"-DCMAKE_INSTALL_LIBDIR=lib", | ||
860 | f"-DCMAKE_INSTALL_BINDIR=bin", | ||
861 | f"-DCMAKE_INSTALL_DATAROOTDIR=share", | ||
862 | f"-DCMAKE_TOOLCHAIN_FILE={self.root}/build-scripts/cmake-toolchain-mingw64-{ARCH_TO_GNU_ARCH[arch]}.cmake", | ||
863 | f"-G{self.cmake_generator}", | ||
864 | ] + extra_args + ([] if self.fast else ["--fresh"]) + arg_for_shared_static, cwd=build_path, env=new_env) | ||
865 | with self.section_printer.group(f"Build MinGW {triplet} (CMake)"): | ||
866 | self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type], cwd=build_path, env=new_env) | ||
867 | with self.section_printer.group(f"Install MinGW {triplet} (CMake)"): | ||
868 | self.executer.run(["cmake", "--install", str(build_path)], cwd=build_path, env=new_env) | ||
869 | self.verify_mingw_library(triplet=ARCH_TO_TRIPLET[arch], path=install_path / "bin" / f"{self.project}.dll") | ||
870 | archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path, time=self.arc_time) | ||
871 | |||
872 | print("Recording arch-dependent extra files for MinGW development archive ...") | ||
873 | extra_context = { | ||
874 | "TRIPLET": ARCH_TO_TRIPLET[arch], | ||
875 | } | ||
876 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["mingw"]["cmake"].get("files", {}), file_mapping_root=self.root, context=self.get_context(extra_context=extra_context), time=self.arc_time) | ||
877 | print("... done") | ||
878 | |||
879 | print("Recording extra files for MinGW development archive ...") | ||
880 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["mingw"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) | ||
881 | print("... done") | ||
882 | |||
883 | print("Creating zip/tgz/txz development archives ...") | ||
884 | zip_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.zip" | ||
885 | tgz_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.tar.gz" | ||
886 | txz_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.tar.xz" | ||
887 | |||
888 | with Archiver(zip_path=zip_path, tgz_path=tgz_path, txz_path=txz_path) as archiver: | ||
889 | archive_file_tree.add_to_archiver(archive_base="", archiver=archiver) | ||
890 | archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) | ||
891 | print("... done") | ||
892 | |||
893 | self.artifacts["mingw-devel-zip"] = zip_path | ||
894 | self.artifacts["mingw-devel-tar-gz"] = tgz_path | ||
895 | self.artifacts["mingw-devel-tar-xz"] = txz_path | ||
896 | |||
897 | def _detect_android_api(self, android_home: str) -> typing.Optional[AndroidApiVersion]: | ||
898 | platform_dirs = list(Path(p) for p in glob.glob(f"{android_home}/platforms/android-*")) | ||
899 | re_platform = re.compile("^android-([0-9]+)(?:-ext([0-9]+))?$") | ||
900 | platform_versions: list[AndroidApiVersion] = [] | ||
901 | for platform_dir in platform_dirs: | ||
902 | logger.debug("Found Android Platform SDK: %s", platform_dir) | ||
903 | if not (platform_dir / "android.jar").is_file(): | ||
904 | logger.debug("Skipping SDK, missing android.jar") | ||
905 | continue | ||
906 | if m:= re_platform.match(platform_dir.name): | ||
907 | platform_versions.append(AndroidApiVersion(name=platform_dir.name, ints=(int(m.group(1)), int(m.group(2) or 0)))) | ||
908 | platform_versions.sort(key=lambda v: v.ints) | ||
909 | logger.info("Available platform versions: %s", platform_versions) | ||
910 | platform_versions = list(filter(lambda v: v.ints >= self._android_api_minimum.ints, platform_versions)) | ||
911 | logger.info("Valid platform versions (>=%s): %s", self._android_api_minimum.ints, platform_versions) | ||
912 | if not platform_versions: | ||
913 | return None | ||
914 | android_api = platform_versions[0] | ||
915 | logger.info("Selected API version %s", android_api) | ||
916 | return android_api | ||
917 | |||
918 | def _get_prefab_json_text(self) -> str: | ||
919 | return textwrap.dedent(f"""\ | ||
920 | {{ | ||
921 | "schema_version": 2, | ||
922 | "name": "{self.project}", | ||
923 | "version": "{self.version}", | ||
924 | "dependencies": [] | ||
925 | }} | ||
926 | """) | ||
927 | |||
928 | def _get_prefab_module_json_text(self, library_name: typing.Optional[str], export_libraries: list[str]) -> str: | ||
929 | for lib in export_libraries: | ||
930 | assert isinstance(lib, str), f"{lib} must be a string" | ||
931 | module_json_dict = { | ||
932 | "export_libraries": export_libraries, | ||
933 | } | ||
934 | if library_name: | ||
935 | module_json_dict["library_name"] = f"lib{library_name}" | ||
936 | return json.dumps(module_json_dict, indent=4) | ||
937 | |||
938 | @property | ||
939 | def _android_api_minimum(self) -> AndroidApiVersion: | ||
940 | value = self.release_info["android"]["api-minimum"] | ||
941 | if isinstance(value, int): | ||
942 | ints = (value, ) | ||
943 | elif isinstance(value, str): | ||
944 | ints = tuple(split(".")) | ||
945 | else: | ||
946 | raise ValueError("Invalid android.api-minimum: must be X or X.Y") | ||
947 | match len(ints): | ||
948 | case 1: name = f"android-{ints[0]}" | ||
949 | case 2: name = f"android-{ints[0]}-ext-{ints[1]}" | ||
950 | case _: raise ValueError("Invalid android.api-minimum: must be X or X.Y") | ||
951 | return AndroidApiVersion(name=name, ints=ints) | ||
952 | |||
953 | @property | ||
954 | def _android_api_target(self): | ||
955 | return self.release_info["android"]["api-target"] | ||
956 | |||
957 | @property | ||
958 | def _android_ndk_minimum(self): | ||
959 | return self.release_info["android"]["ndk-minimum"] | ||
960 | |||
961 | def _get_prefab_abi_json_text(self, abi: str, cpp: bool, shared: bool) -> str: | ||
962 | abi_json_dict = { | ||
963 | "abi": abi, | ||
964 | "api": self._android_api_minimum.ints[0], | ||
965 | "ndk": self._android_ndk_minimum, | ||
966 | "stl": "c++_shared" if cpp else "none", | ||
967 | "static": not shared, | ||
968 | } | ||
969 | return json.dumps(abi_json_dict, indent=4) | ||
970 | |||
971 | def _get_android_manifest_text(self) -> str: | ||
972 | return textwrap.dedent(f"""\ | ||
973 | <manifest | ||
974 | xmlns:android="http://schemas.android.com/apk/res/android" | ||
975 | package="org.libsdl.android.{self.project}" android:versionCode="1" | ||
976 | android:versionName="1.0"> | ||
977 | <uses-sdk android:minSdkVersion="{self._android_api_minimum.ints[0]}" | ||
978 | android:targetSdkVersion="{self._android_api_target}" /> | ||
979 | </manifest> | ||
980 | """) | ||
981 | |||
982 | def create_android_archives(self, android_api: int, android_home: Path, android_ndk_home: Path) -> None: | ||
983 | cmake_toolchain_file = Path(android_ndk_home) / "build/cmake/android.toolchain.cmake" | ||
984 | if not cmake_toolchain_file.exists(): | ||
985 | logger.error("CMake toolchain file does not exist (%s)", cmake_toolchain_file) | ||
986 | raise SystemExit(1) | ||
987 | aar_path = self.root / "build-android" / f"{self.project}-{self.version}.aar" | ||
988 | android_dist_path = self.dist_path / f"{self.project}-devel-{self.version}-android.zip" | ||
989 | android_abis = self.release_info["android"]["abis"] | ||
990 | java_jars_added = False | ||
991 | module_data_added = False | ||
992 | android_deps_path = self.deps_path / "android-deps" | ||
993 | shutil.rmtree(android_deps_path, ignore_errors=True) | ||
994 | |||
995 | for dep, depinfo in self.release_info["android"].get("dependencies", {}).items(): | ||
996 | dep_devel_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] | ||
997 | |||
998 | dep_extract_path = self.deps_path / f"extract/android/{dep}" | ||
999 | shutil.rmtree(dep_extract_path, ignore_errors=True) | ||
1000 | dep_extract_path.mkdir(parents=True, exist_ok=True) | ||
1001 | |||
1002 | with self.section_printer.group(f"Extracting Android dependency {dep} ({dep_devel_zip})"): | ||
1003 | with zipfile.ZipFile(dep_devel_zip, "r") as zf: | ||
1004 | zf.extractall(dep_extract_path) | ||
1005 | |||
1006 | dep_devel_aar = dep_extract_path / glob.glob("*.aar", root_dir=dep_extract_path)[0] | ||
1007 | self.executer.run([sys.executable, str(dep_devel_aar), "-o", str(android_deps_path)]) | ||
1008 | |||
1009 | for module_name, module_info in self.release_info["android"]["modules"].items(): | ||
1010 | assert "type" in module_info and module_info["type"] in ("interface", "library"), f"module {module_name} must have a valid type" | ||
1011 | |||
1012 | aar_file_tree = ArchiveFileTree() | ||
1013 | android_devel_file_tree = ArchiveFileTree() | ||
1014 | |||
1015 | for android_abi in android_abis: | ||
1016 | with self.section_printer.group(f"Building for Android {android_api} {android_abi}"): | ||
1017 | build_dir = self.root / "build-android" / f"{android_abi}-build" | ||
1018 | install_dir = self.root / "install-android" / f"{android_abi}-install" | ||
1019 | shutil.rmtree(install_dir, ignore_errors=True) | ||
1020 | assert not install_dir.is_dir(), f"{install_dir} should not exist prior to build" | ||
1021 | build_type = "Release" | ||
1022 | cmake_args = [ | ||
1023 | "cmake", | ||
1024 | "-S", str(self.root), | ||
1025 | "-B", str(build_dir), | ||
1026 | f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', | ||
1027 | f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', | ||
1028 | f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}", | ||
1029 | f"-DCMAKE_PREFIX_PATH={str(android_deps_path)}", | ||
1030 | f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", | ||
1031 | f"-DANDROID_HOME={android_home}", | ||
1032 | f"-DANDROID_PLATFORM={android_api}", | ||
1033 | f"-DANDROID_ABI={android_abi}", | ||
1034 | "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", | ||
1035 | f"-DCMAKE_INSTALL_PREFIX={install_dir}", | ||
1036 | "-DCMAKE_INSTALL_INCLUDEDIR=include ", | ||
1037 | "-DCMAKE_INSTALL_LIBDIR=lib", | ||
1038 | "-DCMAKE_INSTALL_DATAROOTDIR=share", | ||
1039 | f"-DCMAKE_BUILD_TYPE={build_type}", | ||
1040 | f"-G{self.cmake_generator}", | ||
1041 | ] + self.release_info["android"]["cmake"]["args"] + ([] if self.fast else ["--fresh"]) | ||
1042 | build_args = [ | ||
1043 | "cmake", | ||
1044 | "--build", str(build_dir), | ||
1045 | "--verbose", | ||
1046 | "--config", build_type, | ||
1047 | ] | ||
1048 | install_args = [ | ||
1049 | "cmake", | ||
1050 | "--install", str(build_dir), | ||
1051 | "--config", build_type, | ||
1052 | ] | ||
1053 | self.executer.run(cmake_args) | ||
1054 | self.executer.run(build_args) | ||
1055 | self.executer.run(install_args) | ||
1056 | |||
1057 | for module_name, module_info in self.release_info["android"]["modules"].items(): | ||
1058 | arcdir_prefab_module = f"prefab/modules/{module_name}" | ||
1059 | if module_info["type"] == "library": | ||
1060 | library = install_dir / module_info["library"] | ||
1061 | assert library.suffix in (".so", ".a") | ||
1062 | assert library.is_file(), f"CMake should have built library '{library}' for module {module_name}" | ||
1063 | arcdir_prefab_libs = f"{arcdir_prefab_module}/libs/android.{android_abi}" | ||
1064 | aar_file_tree.add_file(NodeInArchive.from_fs(arcpath=f"{arcdir_prefab_libs}/{library.name}", path=library, time=self.arc_time)) | ||
1065 | aar_file_tree.add_file(NodeInArchive.from_text(arcpath=f"{arcdir_prefab_libs}/abi.json", text=self._get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=library.suffix == ".so"), time=self.arc_time)) | ||
1066 | |||
1067 | if not module_data_added: | ||
1068 | library_name = None | ||
1069 | if module_info["type"] == "library": | ||
1070 | library_name = Path(module_info["library"]).stem.removeprefix("lib") | ||
1071 | export_libraries = module_info.get("export-libraries", []) | ||
1072 | aar_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_module, "module.json"), text=self._get_prefab_module_json_text(library_name=library_name, export_libraries=export_libraries), time=self.arc_time)) | ||
1073 | arcdir_prefab_include = f"prefab/modules/{module_name}/include" | ||
1074 | if "includes" in module_info: | ||
1075 | aar_file_tree.add_file_mapping(arc_dir=arcdir_prefab_include, file_mapping=module_info["includes"], file_mapping_root=install_dir, context=self.get_context(), time=self.arc_time) | ||
1076 | else: | ||
1077 | aar_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_include, ".keep"), text="\n", time=self.arc_time)) | ||
1078 | module_data_added = True | ||
1079 | |||
1080 | if not java_jars_added: | ||
1081 | java_jars_added = True | ||
1082 | if "jars" in self.release_info["android"]: | ||
1083 | classes_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["classes"], context=self.get_context()) | ||
1084 | sources_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["sources"], context=self.get_context()) | ||
1085 | doc_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["doc"], context=self.get_context()) | ||
1086 | assert classes_jar_path.is_file(), f"CMake should have compiled the java sources and archived them into a JAR ({classes_jar_path})" | ||
1087 | assert sources_jar_path.is_file(), f"CMake should have archived the java sources into a JAR ({sources_jar_path})" | ||
1088 | assert doc_jar_path.is_file(), f"CMake should have archived javadoc into a JAR ({doc_jar_path})" | ||
1089 | |||
1090 | aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes.jar", path=classes_jar_path, time=self.arc_time)) | ||
1091 | aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-sources.jar", path=sources_jar_path, time=self.arc_time)) | ||
1092 | aar_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-doc.jar", path=doc_jar_path, time=self.arc_time)) | ||
1093 | |||
1094 | assert ("jars" in self.release_info["android"] and java_jars_added) or "jars" not in self.release_info["android"], "Must have archived java JAR archives" | ||
1095 | |||
1096 | aar_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"]["aar-files"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) | ||
1097 | |||
1098 | aar_file_tree.add_file(NodeInArchive.from_text(arcpath="prefab/prefab.json", text=self._get_prefab_json_text(), time=self.arc_time)) | ||
1099 | aar_file_tree.add_file(NodeInArchive.from_text(arcpath="AndroidManifest.xml", text=self._get_android_manifest_text(), time=self.arc_time)) | ||
1100 | |||
1101 | with Archiver(zip_path=aar_path) as archiver: | ||
1102 | aar_file_tree.add_to_archiver(archive_base="", archiver=archiver) | ||
1103 | archiver.add_git_hash(arcdir="", commit=self.commit, time=self.arc_time) | ||
1104 | |||
1105 | android_devel_file_tree.add_file(NodeInArchive.from_fs(arcpath=aar_path.name, path=aar_path)) | ||
1106 | android_devel_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"]["files"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) | ||
1107 | with Archiver(zip_path=android_dist_path) as archiver: | ||
1108 | android_devel_file_tree.add_to_archiver(archive_base="", archiver=archiver) | ||
1109 | archiver.add_git_hash(arcdir="", commit=self.commit, time=self.arc_time) | ||
1110 | |||
1111 | self.artifacts[f"android-aar"] = android_dist_path | ||
1112 | |||
1113 | def download_dependencies(self): | ||
1114 | shutil.rmtree(self.deps_path, ignore_errors=True) | ||
1115 | self.deps_path.mkdir(parents=True) | ||
1116 | |||
1117 | if self.github: | ||
1118 | with open(os.environ["GITHUB_OUTPUT"], "a") as f: | ||
1119 | f.write(f"dep-path={self.deps_path.absolute()}\n") | ||
1120 | |||
1121 | for dep, depinfo in self.release_info.get("dependencies", {}).items(): | ||
1122 | startswith = depinfo["startswith"] | ||
1123 | dep_repo = depinfo["repo"] | ||
1124 | # FIXME: dropped "--exclude-pre-releases" | ||
1125 | dep_string_data = self.executer.check_output(["gh", "-R", dep_repo, "release", "list", "--exclude-drafts", "--json", "name,createdAt,tagName", "--jq", f'[.[]|select(.name|startswith("{startswith}"))]|max_by(.createdAt)']).strip() | ||
1126 | dep_data = json.loads(dep_string_data) | ||
1127 | dep_tag = dep_data["tagName"] | ||
1128 | dep_version = dep_data["name"] | ||
1129 | logger.info("Download dependency %s version %s (tag=%s) ", dep, dep_version, dep_tag) | ||
1130 | self.executer.run(["gh", "-R", dep_repo, "release", "download", dep_tag], cwd=self.deps_path) | ||
1131 | if self.github: | ||
1132 | with open(os.environ["GITHUB_OUTPUT"], "a") as f: | ||
1133 | f.write(f"dep-{dep.lower()}-version={dep_version}\n") | ||
1134 | |||
1135 | def verify_dependencies(self): | ||
1136 | for dep, depinfo in self.release_info.get("dependencies", {}).items(): | ||
1137 | if "mingw" in self.release_info: | ||
1138 | mingw_matches = glob.glob(self.release_info["mingw"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) | ||
1139 | assert len(mingw_matches) == 1, f"Exactly one archive matches mingw {dep} dependency: {mingw_matches}" | ||
1140 | if "dmg" in self.release_info: | ||
1141 | dmg_matches = glob.glob(self.release_info["dmg"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) | ||
1142 | assert len(dmg_matches) == 1, f"Exactly one archive matches dmg {dep} dependency: {dmg_matches}" | ||
1143 | if "msvc" in self.release_info: | ||
1144 | msvc_matches = glob.glob(self.release_info["msvc"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) | ||
1145 | assert len(msvc_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {msvc_matches}" | ||
1146 | if "android" in self.release_info: | ||
1147 | android_matches = glob.glob(self.release_info["android"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) | ||
1148 | assert len(android_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {android_matches}" | ||
1149 | |||
1150 | @staticmethod | ||
1151 | def _arch_to_vs_platform(arch: str, configuration: str="Release") -> VsArchPlatformConfig: | ||
1152 | ARCH_TO_VS_PLATFORM = { | ||
1153 | "x86": VsArchPlatformConfig(arch="x86", platform="Win32", configuration=configuration), | ||
1154 | "x64": VsArchPlatformConfig(arch="x64", platform="x64", configuration=configuration), | ||
1155 | "arm64": VsArchPlatformConfig(arch="arm64", platform="ARM64", configuration=configuration), | ||
1156 | } | ||
1157 | return ARCH_TO_VS_PLATFORM[arch] | ||
1158 | |||
1159 | def build_msvc(self): | ||
1160 | with self.section_printer.group("Find Visual Studio"): | ||
1161 | vs = VisualStudio(executer=self.executer) | ||
1162 | for arch in self.release_info["msvc"].get("msbuild", {}).get("archs", []): | ||
1163 | self._build_msvc_msbuild(arch_platform=self._arch_to_vs_platform(arch=arch), vs=vs) | ||
1164 | if "cmake" in self.release_info["msvc"]: | ||
1165 | deps_path = self.root / "msvc-deps" | ||
1166 | shutil.rmtree(deps_path, ignore_errors=True) | ||
1167 | dep_roots = [] | ||
1168 | for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items(): | ||
1169 | dep_extract_path = deps_path / f"extract-{dep}" | ||
1170 | msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] | ||
1171 | with zipfile.ZipFile(msvc_zip, "r") as zf: | ||
1172 | zf.extractall(dep_extract_path) | ||
1173 | contents_msvc_zip = glob.glob(str(dep_extract_path / "*")) | ||
1174 | assert len(contents_msvc_zip) == 1, f"There must be exactly one root item in the root directory of {dep}" | ||
1175 | dep_roots.append(contents_msvc_zip[0]) | ||
1176 | |||
1177 | for arch in self.release_info["msvc"].get("cmake", {}).get("archs", []): | ||
1178 | self._build_msvc_cmake(arch_platform=self._arch_to_vs_platform(arch=arch), dep_roots=dep_roots) | ||
1179 | with self.section_printer.group("Create SDL VC development zip"): | ||
1180 | self._build_msvc_devel() | ||
1181 | |||
1182 | def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio): | ||
1183 | platform_context = self.get_context(arch_platform.extra_context()) | ||
1184 | for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items(): | ||
1185 | msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] | ||
1186 | |||
1187 | src_globs = [configure_text(instr["src"], context=platform_context) for instr in depinfo["copy"]] | ||
1188 | with zipfile.ZipFile(msvc_zip, "r") as zf: | ||
1189 | for member in zf.namelist(): | ||
1190 | member_path = "/".join(Path(member).parts[1:]) | ||
1191 | for src_i, src_glob in enumerate(src_globs): | ||
1192 | if fnmatch.fnmatch(member_path, src_glob): | ||
1193 | dst = (self.root / configure_text(depinfo["copy"][src_i]["dst"], context=platform_context)).resolve() / Path(member_path).name | ||
1194 | zip_data = zf.read(member) | ||
1195 | if dst.exists(): | ||
1196 | identical = False | ||
1197 | if dst.is_file(): | ||
1198 | orig_bytes = dst.read_bytes() | ||
1199 | if orig_bytes == zip_data: | ||
1200 | identical = True | ||
1201 | if not identical: | ||
1202 | logger.warning("Extracting dependency %s, will cause %s to be overwritten", dep, dst) | ||
1203 | if not self.overwrite: | ||
1204 | raise RuntimeError("Run with --overwrite to allow overwriting") | ||
1205 | logger.debug("Extracting %s -> %s", member, dst) | ||
1206 | |||
1207 | dst.parent.mkdir(exist_ok=True, parents=True) | ||
1208 | dst.write_bytes(zip_data) | ||
1209 | |||
1210 | prebuilt_paths = set(self.root / full_prebuilt_path for prebuilt_path in self.release_info["msvc"]["msbuild"].get("prebuilt", []) for full_prebuilt_path in glob.glob(configure_text(prebuilt_path, context=platform_context), root_dir=self.root)) | ||
1211 | msbuild_paths = set(self.root / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["msbuild"]["files-lib"], self.release_info["msvc"]["msbuild"]["files-devel"]) for files_list in file_mapping.values() for f in files_list) | ||
1212 | assert prebuilt_paths.issubset(msbuild_paths), f"msvc.msbuild.prebuilt must be a subset of (msvc.msbuild.files-lib, msvc.msbuild.files-devel)" | ||
1213 | built_paths = msbuild_paths.difference(prebuilt_paths) | ||
1214 | logger.info("MSbuild builds these files, to be included in the package: %s", built_paths) | ||
1215 | if not self.fast: | ||
1216 | for b in built_paths: | ||
1217 | b.unlink(missing_ok=True) | ||
1218 | |||
1219 | rel_projects: list[str] = self.release_info["msvc"]["msbuild"]["projects"] | ||
1220 | projects = list(self.root / p for p in rel_projects) | ||
1221 | |||
1222 | directory_build_props_src_relpath = self.release_info["msvc"]["msbuild"].get("directory-build-props") | ||
1223 | for project in projects: | ||
1224 | dir_b_props = project.parent / "Directory.Build.props" | ||
1225 | dir_b_props.unlink(missing_ok = True) | ||
1226 | if directory_build_props_src_relpath: | ||
1227 | src = self.root / directory_build_props_src_relpath | ||
1228 | logger.debug("Copying %s -> %s", src, dir_b_props) | ||
1229 | shutil.copy(src=src, dst=dir_b_props) | ||
1230 | |||
1231 | with self.section_printer.group(f"Build {arch_platform.arch} VS binary"): | ||
1232 | vs.build(arch_platform=arch_platform, projects=projects) | ||
1233 | |||
1234 | if self.dry: | ||
1235 | for b in built_paths: | ||
1236 | b.parent.mkdir(parents=True, exist_ok=True) | ||
1237 | b.touch() | ||
1238 | |||
1239 | for b in built_paths: | ||
1240 | assert b.is_file(), f"{b} has not been created" | ||
1241 | b.parent.mkdir(parents=True, exist_ok=True) | ||
1242 | b.touch() | ||
1243 | |||
1244 | zip_path = self.dist_path / f"{self.project}-{self.version}-win32-{arch_platform.arch}.zip" | ||
1245 | zip_path.unlink(missing_ok=True) | ||
1246 | |||
1247 | logger.info("Collecting files...") | ||
1248 | archive_file_tree = ArchiveFileTree() | ||
1249 | archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["msbuild"]["files-lib"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) | ||
1250 | archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) | ||
1251 | |||
1252 | logger.info("Writing to %s", zip_path) | ||
1253 | with Archiver(zip_path=zip_path) as archiver: | ||
1254 | arc_root = f"" | ||
1255 | archive_file_tree.add_to_archiver(archive_base=arc_root, archiver=archiver) | ||
1256 | archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) | ||
1257 | self.artifacts[f"VC-{arch_platform.arch}"] = zip_path | ||
1258 | |||
1259 | for p in built_paths: | ||
1260 | assert p.is_file(), f"{p} should exist" | ||
1261 | |||
1262 | def _arch_platform_to_build_path(self, arch_platform: VsArchPlatformConfig) -> Path: | ||
1263 | return self.root / f"build-vs-{arch_platform.arch}" | ||
1264 | |||
1265 | def _arch_platform_to_install_path(self, arch_platform: VsArchPlatformConfig) -> Path: | ||
1266 | return self._arch_platform_to_build_path(arch_platform) / "prefix" | ||
1267 | |||
1268 | def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list[Path]): | ||
1269 | build_path = self._arch_platform_to_build_path(arch_platform) | ||
1270 | install_path = self._arch_platform_to_install_path(arch_platform) | ||
1271 | platform_context = self.get_context(extra_context=arch_platform.extra_context()) | ||
1272 | |||
1273 | build_type = "Release" | ||
1274 | extra_context = { | ||
1275 | "ARCH": arch_platform.arch, | ||
1276 | "PLATFORM": arch_platform.platform, | ||
1277 | } | ||
1278 | |||
1279 | built_paths = set(install_path / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["cmake"]["files-lib"], self.release_info["msvc"]["cmake"]["files-devel"]) for files_list in file_mapping.values() for f in files_list) | ||
1280 | logger.info("CMake builds these files, to be included in the package: %s", built_paths) | ||
1281 | if not self.fast: | ||
1282 | for b in built_paths: | ||
1283 | b.unlink(missing_ok=True) | ||
1284 | |||
1285 | shutil.rmtree(install_path, ignore_errors=True) | ||
1286 | build_path.mkdir(parents=True, exist_ok=True) | ||
1287 | with self.section_printer.group(f"Configure VC CMake project for {arch_platform.arch}"): | ||
1288 | self.executer.run([ | ||
1289 | "cmake", "-S", str(self.root), "-B", str(build_path), | ||
1290 | "-A", arch_platform.platform, | ||
1291 | "-DCMAKE_INSTALL_BINDIR=bin", | ||
1292 | "-DCMAKE_INSTALL_DATAROOTDIR=share", | ||
1293 | "-DCMAKE_INSTALL_INCLUDEDIR=include", | ||
1294 | "-DCMAKE_INSTALL_LIBDIR=lib", | ||
1295 | f"-DCMAKE_BUILD_TYPE={build_type}", | ||
1296 | f"-DCMAKE_INSTALL_PREFIX={install_path}", | ||
1297 | # MSVC debug information format flags are selected by an abstraction | ||
1298 | "-DCMAKE_POLICY_DEFAULT_CMP0141=NEW", | ||
1299 | # MSVC debug information format | ||
1300 | "-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase", | ||
1301 | # Linker flags for executables | ||
1302 | "-DCMAKE_EXE_LINKER_FLAGS=-INCREMENTAL:NO -DEBUG -OPT:REF -OPT:ICF", | ||
1303 | # Linker flag for shared libraries | ||
1304 | "-DCMAKE_SHARED_LINKER_FLAGS=-INCREMENTAL:NO -DEBUG -OPT:REF -OPT:ICF", | ||
1305 | # MSVC runtime library flags are selected by an abstraction | ||
1306 | "-DCMAKE_POLICY_DEFAULT_CMP0091=NEW", | ||
1307 | # Use statically linked runtime (-MT) (ideally, should be "MultiThreaded$<$<CONFIG:Debug>:Debug>") | ||
1308 | "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", | ||
1309 | f"-DCMAKE_PREFIX_PATH={';'.join(str(s) for s in dep_roots)}", | ||
1310 | ] + self.release_info["msvc"]["cmake"]["args"] + ([] if self.fast else ["--fresh"])) | ||
1311 | |||
1312 | with self.section_printer.group(f"Build VC CMake project for {arch_platform.arch}"): | ||
1313 | self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type]) | ||
1314 | with self.section_printer.group(f"Install VC CMake project for {arch_platform.arch}"): | ||
1315 | self.executer.run(["cmake", "--install", str(build_path), "--config", build_type]) | ||
1316 | |||
1317 | if self.dry: | ||
1318 | for b in built_paths: | ||
1319 | b.parent.mkdir(parents=True, exist_ok=True) | ||
1320 | b.touch() | ||
1321 | |||
1322 | zip_path = self.dist_path / f"{self.project}-{self.version}-win32-{arch_platform.arch}.zip" | ||
1323 | zip_path.unlink(missing_ok=True) | ||
1324 | |||
1325 | logger.info("Collecting files...") | ||
1326 | archive_file_tree = ArchiveFileTree() | ||
1327 | archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["cmake"]["files-lib"], file_mapping_root=install_path, context=platform_context, time=self.arc_time) | ||
1328 | archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=self.get_context(extra_context=extra_context), time=self.arc_time) | ||
1329 | |||
1330 | logger.info("Creating %s", zip_path) | ||
1331 | with Archiver(zip_path=zip_path) as archiver: | ||
1332 | arc_root = f"" | ||
1333 | archive_file_tree.add_to_archiver(archive_base=arc_root, archiver=archiver) | ||
1334 | archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) | ||
1335 | |||
1336 | for p in built_paths: | ||
1337 | assert p.is_file(), f"{p} should exist" | ||
1338 | |||
1339 | def _build_msvc_devel(self) -> None: | ||
1340 | zip_path = self.dist_path / f"{self.project}-devel-{self.version}-VC.zip" | ||
1341 | arc_root = f"{self.project}-{self.version}" | ||
1342 | |||
1343 | def copy_files_devel(ctx): | ||
1344 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["files-devel"], file_mapping_root=self.root, context=ctx, time=self.arc_time) | ||
1345 | |||
1346 | |||
1347 | logger.info("Collecting files...") | ||
1348 | archive_file_tree = ArchiveFileTree() | ||
1349 | if "msbuild" in self.release_info["msvc"]: | ||
1350 | for arch in self.release_info["msvc"]["msbuild"]["archs"]: | ||
1351 | arch_platform = self._arch_to_vs_platform(arch=arch) | ||
1352 | platform_context = self.get_context(arch_platform.extra_context()) | ||
1353 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["msbuild"]["files-devel"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) | ||
1354 | copy_files_devel(ctx=platform_context) | ||
1355 | if "cmake" in self.release_info["msvc"]: | ||
1356 | for arch in self.release_info["msvc"]["cmake"]["archs"]: | ||
1357 | arch_platform = self._arch_to_vs_platform(arch=arch) | ||
1358 | platform_context = self.get_context(arch_platform.extra_context()) | ||
1359 | archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["cmake"]["files-devel"], file_mapping_root=self._arch_platform_to_install_path(arch_platform), context=platform_context, time=self.arc_time) | ||
1360 | copy_files_devel(ctx=platform_context) | ||
1361 | |||
1362 | with Archiver(zip_path=zip_path) as archiver: | ||
1363 | archive_file_tree.add_to_archiver(archive_base="", archiver=archiver) | ||
1364 | archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) | ||
1365 | self.artifacts["VC-devel"] = zip_path | ||
1366 | |||
1367 | @classmethod | ||
1368 | def extract_sdl_version(cls, root: Path, release_info: dict) -> str: | ||
1369 | with open(root / release_info["version"]["file"], "r") as f: | ||
1370 | text = f.read() | ||
1371 | major = next(re.finditer(release_info["version"]["re_major"], text, flags=re.M)).group(1) | ||
1372 | minor = next(re.finditer(release_info["version"]["re_minor"], text, flags=re.M)).group(1) | ||
1373 | micro = next(re.finditer(release_info["version"]["re_micro"], text, flags=re.M)).group(1) | ||
1374 | return f"{major}.{minor}.{micro}" | ||
1375 | |||
1376 | |||
1377 | def main(argv=None) -> int: | ||
1378 | if sys.version_info < (3, 11): | ||
1379 | logger.error("This script needs at least python 3.11") | ||
1380 | return 1 | ||
1381 | |||
1382 | parser = argparse.ArgumentParser(allow_abbrev=False, description="Create SDL release artifacts") | ||
1383 | parser.add_argument("--root", metavar="DIR", type=Path, default=Path(__file__).absolute().parents[1], help="Root of project") | ||
1384 | parser.add_argument("--release-info", metavar="JSON", dest="path_release_info", type=Path, default=Path(__file__).absolute().parent / "release-info.json", help="Path of release-info.json") | ||
1385 | parser.add_argument("--dependency-folder", metavar="FOLDER", dest="deps_path", type=Path, default="deps", help="Directory containing pre-built archives of dependencies (will be removed when downloading archives)") | ||
1386 | parser.add_argument("--out", "-o", metavar="DIR", dest="dist_path", type=Path, default="dist", help="Output directory") | ||
1387 | parser.add_argument("--github", action="store_true", help="Script is running on a GitHub runner") | ||
1388 | parser.add_argument("--commit", default="HEAD", help="Git commit/tag of which a release should be created") | ||
1389 | parser.add_argument("--actions", choices=["download", "source", "android", "mingw", "msvc", "dmg"], required=True, nargs="+", dest="actions", help="What to do?") | ||
1390 | parser.set_defaults(loglevel=logging.INFO) | ||
1391 | parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year") | ||
1392 | parser.add_argument('--android-api', dest="android_api", help="Android API version") | ||
1393 | parser.add_argument('--android-home', dest="android_home", default=os.environ.get("ANDROID_HOME"), help="Android Home folder") | ||
1394 | parser.add_argument('--android-ndk-home', dest="android_ndk_home", default=os.environ.get("ANDROID_NDK_HOME"), help="Android NDK Home folder") | ||
1395 | parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator") | ||
1396 | parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help="Print script debug information") | ||
1397 | parser.add_argument('--dry-run', action='store_true', dest="dry", help="Don't execute anything") | ||
1398 | parser.add_argument('--force', action='store_true', dest="force", help="Ignore a non-clean git tree") | ||
1399 | parser.add_argument('--overwrite', action='store_true', dest="overwrite", help="Allow potentially overwriting other projects") | ||
1400 | parser.add_argument('--fast', action='store_true', dest="fast", help="Don't do a rebuild") | ||
1401 | |||
1402 | args = parser.parse_args(argv) | ||
1403 | logging.basicConfig(level=args.loglevel, format='[%(levelname)s] %(message)s') | ||
1404 | args.deps_path = args.deps_path.absolute() | ||
1405 | args.dist_path = args.dist_path.absolute() | ||
1406 | args.root = args.root.absolute() | ||
1407 | args.dist_path = args.dist_path.absolute() | ||
1408 | if args.dry: | ||
1409 | args.dist_path = args.dist_path / "dry" | ||
1410 | |||
1411 | if args.github: | ||
1412 | section_printer: SectionPrinter = GitHubSectionPrinter() | ||
1413 | else: | ||
1414 | section_printer = SectionPrinter() | ||
1415 | |||
1416 | if args.github and "GITHUB_OUTPUT" not in os.environ: | ||
1417 | os.environ["GITHUB_OUTPUT"] = "/tmp/github_output.txt" | ||
1418 | |||
1419 | executer = Executer(root=args.root, dry=args.dry) | ||
1420 | |||
1421 | root_git_hash_path = args.root / GIT_HASH_FILENAME | ||
1422 | root_is_maybe_archive = root_git_hash_path.is_file() | ||
1423 | if root_is_maybe_archive: | ||
1424 | logger.warning("%s detected: Building from archive", GIT_HASH_FILENAME) | ||
1425 | archive_commit = root_git_hash_path.read_text().strip() | ||
1426 | if args.commit != archive_commit: | ||
1427 | logger.warning("Commit argument is %s, but archive commit is %s. Using %s.", args.commit, archive_commit, archive_commit) | ||
1428 | args.commit = archive_commit | ||
1429 | revision = (args.root / REVISION_TXT).read_text().strip() | ||
1430 | else: | ||
1431 | args.commit = executer.check_output(["git", "rev-parse", args.commit], dry_out="e5812a9fd2cda317b503325a702ba3c1c37861d9").strip() | ||
1432 | revision = executer.check_output(["git", "describe", "--always", "--tags", "--long", args.commit], dry_out="preview-3.1.3-96-g9512f2144").strip() | ||
1433 | logger.info("Using commit %s", args.commit) | ||
1434 | |||
1435 | try: | ||
1436 | with args.path_release_info.open() as f: | ||
1437 | release_info = json.load(f) | ||
1438 | except FileNotFoundError: | ||
1439 | logger.error(f"Could not find {args.path_release_info}") | ||
1440 | |||
1441 | releaser = Releaser( | ||
1442 | release_info=release_info, | ||
1443 | commit=args.commit, | ||
1444 | revision=revision, | ||
1445 | root=args.root, | ||
1446 | dist_path=args.dist_path, | ||
1447 | executer=executer, | ||
1448 | section_printer=section_printer, | ||
1449 | cmake_generator=args.cmake_generator, | ||
1450 | deps_path=args.deps_path, | ||
1451 | overwrite=args.overwrite, | ||
1452 | github=args.github, | ||
1453 | fast=args.fast, | ||
1454 | ) | ||
1455 | |||
1456 | if root_is_maybe_archive: | ||
1457 | logger.warning("Building from archive. Skipping clean git tree check.") | ||
1458 | else: | ||
1459 | porcelain_status = executer.check_output(["git", "status", "--ignored", "--porcelain"], dry_out="\n").strip() | ||
1460 | if porcelain_status: | ||
1461 | print(porcelain_status) | ||
1462 | logger.warning("The tree is dirty! Do not publish any generated artifacts!") | ||
1463 | if not args.force: | ||
1464 | raise Exception("The git repo contains modified and/or non-committed files. Run with --force to ignore.") | ||
1465 | |||
1466 | if args.fast: | ||
1467 | logger.warning("Doing fast build! Do not publish generated artifacts!") | ||
1468 | |||
1469 | with section_printer.group("Arguments"): | ||
1470 | print(f"project = {releaser.project}") | ||
1471 | print(f"version = {releaser.version}") | ||
1472 | print(f"revision = {revision}") | ||
1473 | print(f"commit = {args.commit}") | ||
1474 | print(f"out = {args.dist_path}") | ||
1475 | print(f"actions = {args.actions}") | ||
1476 | print(f"dry = {args.dry}") | ||
1477 | print(f"force = {args.force}") | ||
1478 | print(f"overwrite = {args.overwrite}") | ||
1479 | print(f"cmake_generator = {args.cmake_generator}") | ||
1480 | |||
1481 | releaser.prepare() | ||
1482 | |||
1483 | if "download" in args.actions: | ||
1484 | releaser.download_dependencies() | ||
1485 | |||
1486 | if set(args.actions).intersection({"msvc", "mingw", "android"}): | ||
1487 | print("Verifying presence of dependencies (run 'download' action to download) ...") | ||
1488 | releaser.verify_dependencies() | ||
1489 | print("... done") | ||
1490 | |||
1491 | if "source" in args.actions: | ||
1492 | if root_is_maybe_archive: | ||
1493 | raise Exception("Cannot build source archive from source archive") | ||
1494 | with section_printer.group("Create source archives"): | ||
1495 | releaser.create_source_archives() | ||
1496 | |||
1497 | if "dmg" in args.actions: | ||
1498 | if platform.system() != "Darwin" and not args.dry: | ||
1499 | parser.error("framework artifact(s) can only be built on Darwin") | ||
1500 | |||
1501 | releaser.create_dmg() | ||
1502 | |||
1503 | if "msvc" in args.actions: | ||
1504 | if platform.system() != "Windows" and not args.dry: | ||
1505 | parser.error("msvc artifact(s) can only be built on Windows") | ||
1506 | releaser.build_msvc() | ||
1507 | |||
1508 | if "mingw" in args.actions: | ||
1509 | releaser.create_mingw_archives() | ||
1510 | |||
1511 | if "android" in args.actions: | ||
1512 | if args.android_home is None or not Path(args.android_home).is_dir(): | ||
1513 | parser.error("Invalid $ANDROID_HOME or --android-home: must be a directory containing the Android SDK") | ||
1514 | if args.android_ndk_home is None or not Path(args.android_ndk_home).is_dir(): | ||
1515 | parser.error("Invalid $ANDROID_NDK_HOME or --android_ndk_home: must be a directory containing the Android NDK") | ||
1516 | if args.android_api is None: | ||
1517 | with section_printer.group("Detect Android APIS"): | ||
1518 | args.android_api = releaser._detect_android_api(android_home=args.android_home) | ||
1519 | else: | ||
1520 | try: | ||
1521 | android_api_ints = tuple(int(v) for v in args.android_api.split(".")) | ||
1522 | match len(android_api_ints): | ||
1523 | case 1: android_api_name = f"android-{android_api_ints[0]}" | ||
1524 | case 2: android_api_name = f"android-{android_api_ints[0]}-ext-{android_api_ints[1]}" | ||
1525 | case _: raise ValueError | ||
1526 | except ValueError: | ||
1527 | logger.error("Invalid --android-api, must be a 'X' or 'X.Y' version") | ||
1528 | args.android_api = AndroidApiVersion(ints=android_api_ints, name=android_api_name) | ||
1529 | if args.android_api is None: | ||
1530 | parser.error("Invalid --android-api, and/or could not be detected") | ||
1531 | android_api_path = Path(args.android_home) / f"platforms/{args.android_api.name}" | ||
1532 | if not android_api_path.is_dir(): | ||
1533 | parser.error(f"Android API directory does not exist ({android_api_path})") | ||
1534 | with section_printer.group("Android arguments"): | ||
1535 | print(f"android_home = {args.android_home}") | ||
1536 | print(f"android_ndk_home = {args.android_ndk_home}") | ||
1537 | print(f"android_api = {args.android_api}") | ||
1538 | releaser.create_android_archives( | ||
1539 | android_api=args.android_api.ints[0], | ||
1540 | android_home=args.android_home, | ||
1541 | android_ndk_home=args.android_ndk_home, | ||
1542 | ) | ||
1543 | with section_printer.group("Summary"): | ||
1544 | print(f"artifacts = {releaser.artifacts}") | ||
1545 | |||
1546 | if args.github: | ||
1547 | with open(os.environ["GITHUB_OUTPUT"], "a") as f: | ||
1548 | f.write(f"project={releaser.project}\n") | ||
1549 | f.write(f"version={releaser.version}\n") | ||
1550 | for k, v in releaser.artifacts.items(): | ||
1551 | f.write(f"{k}={v.name}\n") | ||
1552 | return 0 | ||
1553 | |||
1554 | |||
1555 | if __name__ == "__main__": | ||
1556 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl b/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl new file mode 100755 index 0000000..c255ea3 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/build-web-examples.pl | |||
@@ -0,0 +1,420 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | # Simple DirectMedia Layer | ||
4 | # Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
5 | # | ||
6 | # This software is provided 'as-is', without any express or implied | ||
7 | # warranty. In no event will the authors be held liable for any damages | ||
8 | # arising from the use of this software. | ||
9 | # | ||
10 | # Permission is granted to anyone to use this software for any purpose, | ||
11 | # including commercial applications, and to alter it and redistribute it | ||
12 | # freely, subject to the following restrictions: | ||
13 | # | ||
14 | # 1. The origin of this software must not be misrepresented; you must not | ||
15 | # claim that you wrote the original software. If you use this software | ||
16 | # in a product, an acknowledgment in the product documentation would be | ||
17 | # appreciated but is not required. | ||
18 | # 2. Altered source versions must be plainly marked as such, and must not be | ||
19 | # misrepresented as being the original software. | ||
20 | # 3. This notice may not be removed or altered from any source distribution. | ||
21 | |||
22 | use warnings; | ||
23 | use strict; | ||
24 | use File::Basename; | ||
25 | use File::Copy; | ||
26 | use Cwd qw(abs_path); | ||
27 | use IPC::Open2; | ||
28 | |||
29 | my $examples_dir = abs_path(dirname(__FILE__) . "/../examples"); | ||
30 | my $project = undef; | ||
31 | my $emsdk_dir = undef; | ||
32 | my $compile_dir = undef; | ||
33 | my $cmake_flags = undef; | ||
34 | my $output_dir = undef; | ||
35 | |||
36 | sub usage { | ||
37 | die("USAGE: $0 <project_name> <emsdk_dir> <compiler_output_directory> <cmake_flags> <html_output_directory>\n\n"); | ||
38 | } | ||
39 | |||
40 | sub do_system { | ||
41 | my $cmd = shift; | ||
42 | $cmd = "exec /bin/bash -c \"$cmd\""; | ||
43 | print("$cmd\n"); | ||
44 | return system($cmd); | ||
45 | } | ||
46 | |||
47 | sub do_mkdir { | ||
48 | my $d = shift; | ||
49 | if ( ! -d $d ) { | ||
50 | print("mkdir '$d'\n"); | ||
51 | mkdir($d) or die("Couldn't mkdir('$d'): $!\n"); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | sub do_copy { | ||
56 | my $src = shift; | ||
57 | my $dst = shift; | ||
58 | print("cp '$src' '$dst'\n"); | ||
59 | copy($src, $dst) or die("Failed to copy '$src' to '$dst': $!\n"); | ||
60 | } | ||
61 | |||
62 | sub build_latest { | ||
63 | # Try to build just the latest without re-running cmake, since that is SLOW. | ||
64 | print("Building latest version of $project ...\n"); | ||
65 | if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && cd '$compile_dir' && ninja") != 0) { | ||
66 | # Build failed? Try nuking the build dir and running CMake from scratch. | ||
67 | print("\n\nBuilding latest version of $project FROM SCRATCH ...\n"); | ||
68 | if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && rm -rf '$compile_dir' && mkdir '$compile_dir' && cd '$compile_dir' && emcmake cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel $cmake_flags '$examples_dir/..' && ninja") != 0) { | ||
69 | die("Failed to build latest version of $project!\n"); # oh well. | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | sub get_category_description { | ||
75 | my $category = shift; | ||
76 | my $retval = ucfirst($category); | ||
77 | |||
78 | if (open(my $fh, '<', "$examples_dir/$category/description.txt")) { | ||
79 | $retval = <$fh>; | ||
80 | chomp($retval); | ||
81 | close($fh); | ||
82 | } | ||
83 | |||
84 | return $retval; | ||
85 | } | ||
86 | |||
87 | sub get_categories { | ||
88 | my @categories = (); | ||
89 | |||
90 | if (open(my $fh, '<', "$examples_dir/categories.txt")) { | ||
91 | while (<$fh>) { | ||
92 | chomp; | ||
93 | s/\A\s+//; | ||
94 | s/\s+\Z//; | ||
95 | next if $_ eq ''; | ||
96 | next if /\A\#/; | ||
97 | push @categories, $_; | ||
98 | } | ||
99 | close($fh); | ||
100 | } else { | ||
101 | opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n"); | ||
102 | foreach my $dir (sort readdir $dh) { | ||
103 | next if ($dir eq '.') || ($dir eq '..'); # obviously skip current and parent entries. | ||
104 | next if not -d "$examples_dir/$dir"; # only care about subdirectories. | ||
105 | push @categories, $dir; | ||
106 | } | ||
107 | closedir($dh); | ||
108 | } | ||
109 | |||
110 | return @categories; | ||
111 | } | ||
112 | |||
113 | sub get_examples_for_category { | ||
114 | my $category = shift; | ||
115 | |||
116 | my @examples = (); | ||
117 | |||
118 | opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n"); | ||
119 | foreach my $dir (sort readdir $dh) { | ||
120 | next if ($dir eq '.') || ($dir eq '..'); # obviously skip current and parent entries. | ||
121 | next if not -d "$examples_dir/$category/$dir"; # only care about subdirectories. | ||
122 | |||
123 | push @examples, $dir; | ||
124 | } | ||
125 | closedir($dh); | ||
126 | |||
127 | return @examples; | ||
128 | } | ||
129 | |||
130 | sub handle_example_dir { | ||
131 | my $category = shift; | ||
132 | my $example = shift; | ||
133 | |||
134 | my @files = (); | ||
135 | my $files_str = ''; | ||
136 | opendir(my $dh, "$examples_dir/$category/$example") or die("Couldn't opendir '$examples_dir/$category/$example': $!\n"); | ||
137 | my $spc = ''; | ||
138 | while (readdir($dh)) { | ||
139 | my $path = "$examples_dir/$category/$example/$_"; | ||
140 | next if not -f $path; # only care about files. | ||
141 | push @files, $path if /\.[ch]\Z/; # add .c and .h files to source code. | ||
142 | if (/\.c\Z/) { # only care about .c files for compiling. | ||
143 | $files_str .= "$spc$path"; | ||
144 | $spc = ' '; | ||
145 | } | ||
146 | } | ||
147 | closedir($dh); | ||
148 | |||
149 | my $dst = "$output_dir/$category/$example"; | ||
150 | |||
151 | print("Building $category/$example ...\n"); | ||
152 | |||
153 | my $basefname = "$example"; | ||
154 | $basefname =~ s/\A\d+\-//; | ||
155 | $basefname = "$category-$basefname"; | ||
156 | my $jsfname = "$basefname.js"; | ||
157 | my $wasmfname = "$basefname.wasm"; | ||
158 | my $thumbnailfname = 'thumbnail.png'; | ||
159 | my $onmouseoverfname = 'onmouseover.webp'; | ||
160 | my $jssrc = "$compile_dir/examples/$jsfname"; | ||
161 | my $wasmsrc = "$compile_dir/examples/$wasmfname"; | ||
162 | my $thumbnailsrc = "$examples_dir/$category/$example/$thumbnailfname"; | ||
163 | my $onmouseoversrc = "$examples_dir/$category/$example/$onmouseoverfname"; | ||
164 | my $jsdst = "$dst/$jsfname"; | ||
165 | my $wasmdst = "$dst/$wasmfname"; | ||
166 | my $thumbnaildst = "$dst/$thumbnailfname"; | ||
167 | my $onmouseoverdst = "$dst/$onmouseoverfname"; | ||
168 | |||
169 | my $description = ''; | ||
170 | my $has_paragraph = 0; | ||
171 | if (open(my $readmetxth, '<', "$examples_dir/$category/$example/README.txt")) { | ||
172 | while (<$readmetxth>) { | ||
173 | chomp; | ||
174 | s/\A\s+//; | ||
175 | s/\s+\Z//; | ||
176 | if (($_ eq '') && ($description ne '')) { | ||
177 | $has_paragraph = 1; | ||
178 | } else { | ||
179 | if ($has_paragraph) { | ||
180 | $description .= "\n<br/>\n<br/>\n"; | ||
181 | $has_paragraph = 0; | ||
182 | } | ||
183 | $description .= "$_ "; | ||
184 | } | ||
185 | } | ||
186 | close($readmetxth); | ||
187 | $description =~ s/\s+\Z//; | ||
188 | } | ||
189 | |||
190 | do_mkdir($dst); | ||
191 | do_copy($jssrc, $jsdst); | ||
192 | do_copy($wasmsrc, $wasmdst); | ||
193 | do_copy($thumbnailsrc, $thumbnaildst) if ( -f $thumbnailsrc ); | ||
194 | do_copy($onmouseoversrc, $onmouseoverdst) if ( -f $onmouseoversrc ); | ||
195 | |||
196 | my $highlight_cmd = "highlight '--outdir=$dst' --style-outfile=highlight.css --fragment --enclose-pre --stdout --syntax=c '--plug-in=$examples_dir/highlight-plugin.lua'"; | ||
197 | print("$highlight_cmd\n"); | ||
198 | my $pid = open2(my $child_out, my $child_in, $highlight_cmd); | ||
199 | |||
200 | my $htmlified_source_code = ''; | ||
201 | foreach (sort(@files)) { | ||
202 | my $path = $_; | ||
203 | open my $srccode, '<', $path or die("Couldn't open '$path': $!\n"); | ||
204 | my $fname = "$path"; | ||
205 | $fname =~ s/\A.*\///; | ||
206 | print $child_in "/* $fname ... */\n\n"; | ||
207 | while (<$srccode>) { | ||
208 | print $child_in $_; | ||
209 | } | ||
210 | print $child_in "\n\n\n"; | ||
211 | close($srccode); | ||
212 | } | ||
213 | |||
214 | close($child_in); | ||
215 | |||
216 | while (<$child_out>) { | ||
217 | $htmlified_source_code .= $_; | ||
218 | } | ||
219 | close($child_out); | ||
220 | |||
221 | waitpid($pid, 0); | ||
222 | |||
223 | my $other_examples_html = "<ul>"; | ||
224 | foreach my $example (get_examples_for_category($category)) { | ||
225 | $other_examples_html .= "<li><a href='/$project/$category/$example'>$category/$example</a></li>"; | ||
226 | } | ||
227 | $other_examples_html .= "</ul>"; | ||
228 | |||
229 | my $category_description = get_category_description($category); | ||
230 | my $preview_image = get_example_thumbnail($project, $category, $example); | ||
231 | |||
232 | my $html = ''; | ||
233 | open my $htmltemplate, '<', "$examples_dir/template.html" or die("Couldn't open '$examples_dir/template.html': $!\n"); | ||
234 | while (<$htmltemplate>) { | ||
235 | s/\@project_name\@/$project/g; | ||
236 | s/\@category_name\@/$category/g; | ||
237 | s/\@category_description\@/$category_description/g; | ||
238 | s/\@example_name\@/$example/g; | ||
239 | s/\@javascript_file\@/$jsfname/g; | ||
240 | s/\@htmlified_source_code\@/$htmlified_source_code/g; | ||
241 | s/\@description\@/$description/g; | ||
242 | s/\@preview_image\@/$preview_image/g; | ||
243 | s/\@other_examples_html\@/$other_examples_html/g; | ||
244 | $html .= $_; | ||
245 | } | ||
246 | close($htmltemplate); | ||
247 | |||
248 | open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n"); | ||
249 | print $htmloutput $html; | ||
250 | close($htmloutput); | ||
251 | } | ||
252 | |||
253 | sub get_example_thumbnail { | ||
254 | my $project = shift; | ||
255 | my $category = shift; | ||
256 | my $example = shift; | ||
257 | |||
258 | if ( -f "$examples_dir/$category/$example/thumbnail.png" ) { | ||
259 | return "/$project/$category/$example/thumbnail.png"; | ||
260 | } elsif ( -f "$examples_dir/$category/thumbnail.png" ) { | ||
261 | return "/$project/$category/thumbnail.png"; | ||
262 | } | ||
263 | |||
264 | return "/$project/thumbnail.png"; | ||
265 | } | ||
266 | |||
267 | sub generate_example_thumbnail { | ||
268 | my $project = shift; | ||
269 | my $category = shift; | ||
270 | my $example = shift; | ||
271 | |||
272 | my $example_no_num = "$example"; | ||
273 | $example_no_num =~ s/\A\d+\-//; | ||
274 | |||
275 | my $example_image_url = get_example_thumbnail($project, $category, $example); | ||
276 | |||
277 | my $example_mouseover_html = ''; | ||
278 | if ( -f "$examples_dir/$category/$example/onmouseover.webp" ) { | ||
279 | $example_mouseover_html = "onmouseover=\"this.src='/$project/$category/$example/onmouseover.webp'\" onmouseout=\"this.src='$example_image_url';\""; | ||
280 | } elsif ( -f "$examples_dir/$category/onmouseover.webp" ) { | ||
281 | $example_mouseover_html = "onmouseover=\"this.src='/$project/$category/onmouseover.webp'\" onmouseout=\"this.src='$example_image_url';\""; | ||
282 | } | ||
283 | |||
284 | return " | ||
285 | <a href='/$project/$category/$example'> | ||
286 | <div> | ||
287 | <img src='$example_image_url' $example_mouseover_html /> | ||
288 | <div>$example_no_num</div> | ||
289 | </div> | ||
290 | </a>" | ||
291 | ; | ||
292 | } | ||
293 | |||
294 | sub generate_example_thumbnails_for_category { | ||
295 | my $project = shift; | ||
296 | my $category = shift; | ||
297 | my @examples = get_examples_for_category($category); | ||
298 | my $retval = ''; | ||
299 | foreach my $example (@examples) { | ||
300 | $retval .= generate_example_thumbnail($project, $category, $example); | ||
301 | } | ||
302 | return $retval; | ||
303 | } | ||
304 | |||
305 | sub handle_category_dir { | ||
306 | my $category = shift; | ||
307 | |||
308 | print("Category $category ...\n"); | ||
309 | |||
310 | do_mkdir("$output_dir/$category"); | ||
311 | |||
312 | opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n"); | ||
313 | |||
314 | while (readdir($dh)) { | ||
315 | next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries. | ||
316 | next if not -d "$examples_dir/$category/$_"; # only care about subdirectories. | ||
317 | handle_example_dir($category, $_); | ||
318 | } | ||
319 | |||
320 | closedir($dh); | ||
321 | |||
322 | my $examples_list_html = generate_example_thumbnails_for_category($project, $category); | ||
323 | |||
324 | my $dst = "$output_dir/$category"; | ||
325 | |||
326 | do_copy("$examples_dir/$category/thumbnail.png", "$dst/thumbnail.png") if ( -f "$examples_dir/$category/thumbnail.png" ); | ||
327 | do_copy("$examples_dir/$category/onmouseover.webp", "$dst/onmouseover.webp") if ( -f "$examples_dir/$category/onmouseover.webp" ); | ||
328 | |||
329 | my $category_description = get_category_description($category); | ||
330 | my $preview_image = "/$project/thumbnail.png"; | ||
331 | if ( -f "$examples_dir/$category/thumbnail.png" ) { | ||
332 | $preview_image = "/$project/$category/thumbnail.png"; | ||
333 | } | ||
334 | |||
335 | # write category page | ||
336 | my $html = ''; | ||
337 | open my $htmltemplate, '<', "$examples_dir/template-category.html" or die("Couldn't open '$examples_dir/template-category.html': $!\n"); | ||
338 | while (<$htmltemplate>) { | ||
339 | s/\@project_name\@/$project/g; | ||
340 | s/\@category_name\@/$category/g; | ||
341 | s/\@category_description\@/$category_description/g; | ||
342 | s/\@examples_list_html\@/$examples_list_html/g; | ||
343 | s/\@preview_image\@/$preview_image/g; | ||
344 | $html .= $_; | ||
345 | } | ||
346 | close($htmltemplate); | ||
347 | |||
348 | open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n"); | ||
349 | print $htmloutput $html; | ||
350 | close($htmloutput); | ||
351 | } | ||
352 | |||
353 | |||
354 | # Mainline! | ||
355 | |||
356 | foreach (@ARGV) { | ||
357 | $project = $_, next if not defined $project; | ||
358 | $emsdk_dir = $_, next if not defined $emsdk_dir; | ||
359 | $compile_dir = $_, next if not defined $compile_dir; | ||
360 | $cmake_flags = $_, next if not defined $cmake_flags; | ||
361 | $output_dir = $_, next if not defined $output_dir; | ||
362 | usage(); # too many arguments. | ||
363 | } | ||
364 | |||
365 | usage() if not defined $output_dir; | ||
366 | |||
367 | print("Examples dir: $examples_dir\n"); | ||
368 | print("emsdk dir: $emsdk_dir\n"); | ||
369 | print("Compile dir: $compile_dir\n"); | ||
370 | print("CMake flags: $cmake_flags\n"); | ||
371 | print("Output dir: $output_dir\n"); | ||
372 | |||
373 | do_system("rm -rf '$output_dir'"); | ||
374 | do_mkdir($output_dir); | ||
375 | |||
376 | build_latest(); | ||
377 | |||
378 | do_copy("$examples_dir/template.css", "$output_dir/examples.css"); | ||
379 | do_copy("$examples_dir/template-placeholder.png", "$output_dir/thumbnail.png"); | ||
380 | |||
381 | opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n"); | ||
382 | |||
383 | while (readdir($dh)) { | ||
384 | next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries. | ||
385 | next if not -d "$examples_dir/$_"; # only care about subdirectories. | ||
386 | # !!! FIXME: this needs to generate a preview page for all the categories. | ||
387 | handle_category_dir($_); | ||
388 | } | ||
389 | |||
390 | closedir($dh); | ||
391 | |||
392 | # write homepage | ||
393 | my $homepage_list_html = ""; | ||
394 | foreach my $category (get_categories()) { | ||
395 | my $category_description = get_category_description($category); | ||
396 | $homepage_list_html .= "<h2>$category_description</h2>"; | ||
397 | $homepage_list_html .= "<div class='list'>"; | ||
398 | $homepage_list_html .= generate_example_thumbnails_for_category($project, $category); | ||
399 | $homepage_list_html .= "</div>"; | ||
400 | } | ||
401 | |||
402 | my $preview_image = "/$project/thumbnail.png"; | ||
403 | |||
404 | my $dst = "$output_dir/"; | ||
405 | my $html = ''; | ||
406 | open my $htmltemplate, '<', "$examples_dir/template-homepage.html" or die("Couldn't open '$examples_dir/template-category.html': $!\n"); | ||
407 | while (<$htmltemplate>) { | ||
408 | s/\@project_name\@/$project/g; | ||
409 | s/\@homepage_list_html\@/$homepage_list_html/g; | ||
410 | s/\@preview_image\@/$preview_image/g; | ||
411 | $html .= $_; | ||
412 | } | ||
413 | close($htmltemplate); | ||
414 | |||
415 | open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n"); | ||
416 | print $htmloutput $html; | ||
417 | close($htmloutput); | ||
418 | |||
419 | print("All examples built successfully!\n"); | ||
420 | exit(0); # success! | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/casefolding.txt b/src/contrib/SDL-3.2.20/build-scripts/casefolding.txt new file mode 100644 index 0000000..69c5c64 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/casefolding.txt | |||
@@ -0,0 +1,1627 @@ | |||
1 | # CaseFolding-15.1.0.txt | ||
2 | # Date: 2023-05-12, 21:53:10 GMT | ||
3 | # © 2023 Unicode®, Inc. | ||
4 | # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. | ||
5 | # For terms of use, see https://www.unicode.org/terms_of_use.html | ||
6 | # | ||
7 | # Unicode Character Database | ||
8 | # For documentation, see https://www.unicode.org/reports/tr44/ | ||
9 | # | ||
10 | # Case Folding Properties | ||
11 | # | ||
12 | # This file is a supplement to the UnicodeData file. | ||
13 | # It provides a case folding mapping generated from the Unicode Character Database. | ||
14 | # If all characters are mapped according to the full mapping below, then | ||
15 | # case differences (according to UnicodeData.txt and SpecialCasing.txt) | ||
16 | # are eliminated. | ||
17 | # | ||
18 | # The data supports both implementations that require simple case foldings | ||
19 | # (where string lengths don't change), and implementations that allow full case folding | ||
20 | # (where string lengths may grow). Note that where they can be supported, the | ||
21 | # full case foldings are superior: for example, they allow "MASSE" and "Maße" to match. | ||
22 | # | ||
23 | # All code points not listed in this file map to themselves. | ||
24 | # | ||
25 | # NOTE: case folding does not preserve normalization formats! | ||
26 | # | ||
27 | # For information on case folding, including how to have case folding | ||
28 | # preserve normalization formats, see Section 3.13 Default Case Algorithms in | ||
29 | # The Unicode Standard. | ||
30 | # | ||
31 | # ================================================================================ | ||
32 | # Format | ||
33 | # ================================================================================ | ||
34 | # The entries in this file are in the following machine-readable format: | ||
35 | # | ||
36 | # <code>; <status>; <mapping>; # <name> | ||
37 | # | ||
38 | # The status field is: | ||
39 | # C: common case folding, common mappings shared by both simple and full mappings. | ||
40 | # F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. | ||
41 | # S: simple case folding, mappings to single characters where different from F. | ||
42 | # T: special case for uppercase I and dotted uppercase I | ||
43 | # - For non-Turkic languages, this mapping is normally not used. | ||
44 | # - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. | ||
45 | # Note that the Turkic mappings do not maintain canonical equivalence without additional processing. | ||
46 | # See the discussions of case mapping in the Unicode Standard for more information. | ||
47 | # | ||
48 | # Usage: | ||
49 | # A. To do a simple case folding, use the mappings with status C + S. | ||
50 | # B. To do a full case folding, use the mappings with status C + F. | ||
51 | # | ||
52 | # The mappings with status T can be used or omitted depending on the desired case-folding | ||
53 | # behavior. (The default option is to exclude them.) | ||
54 | # | ||
55 | # ================================================================= | ||
56 | |||
57 | # Property: Case_Folding | ||
58 | |||
59 | # All code points not explicitly listed for Case_Folding | ||
60 | # have the value C for the status field, and the code point itself for the mapping field. | ||
61 | |||
62 | # ================================================================= | ||
63 | 0041; C; 0061; # LATIN CAPITAL LETTER A | ||
64 | 0042; C; 0062; # LATIN CAPITAL LETTER B | ||
65 | 0043; C; 0063; # LATIN CAPITAL LETTER C | ||
66 | 0044; C; 0064; # LATIN CAPITAL LETTER D | ||
67 | 0045; C; 0065; # LATIN CAPITAL LETTER E | ||
68 | 0046; C; 0066; # LATIN CAPITAL LETTER F | ||
69 | 0047; C; 0067; # LATIN CAPITAL LETTER G | ||
70 | 0048; C; 0068; # LATIN CAPITAL LETTER H | ||
71 | 0049; C; 0069; # LATIN CAPITAL LETTER I | ||
72 | 0049; T; 0131; # LATIN CAPITAL LETTER I | ||
73 | 004A; C; 006A; # LATIN CAPITAL LETTER J | ||
74 | 004B; C; 006B; # LATIN CAPITAL LETTER K | ||
75 | 004C; C; 006C; # LATIN CAPITAL LETTER L | ||
76 | 004D; C; 006D; # LATIN CAPITAL LETTER M | ||
77 | 004E; C; 006E; # LATIN CAPITAL LETTER N | ||
78 | 004F; C; 006F; # LATIN CAPITAL LETTER O | ||
79 | 0050; C; 0070; # LATIN CAPITAL LETTER P | ||
80 | 0051; C; 0071; # LATIN CAPITAL LETTER Q | ||
81 | 0052; C; 0072; # LATIN CAPITAL LETTER R | ||
82 | 0053; C; 0073; # LATIN CAPITAL LETTER S | ||
83 | 0054; C; 0074; # LATIN CAPITAL LETTER T | ||
84 | 0055; C; 0075; # LATIN CAPITAL LETTER U | ||
85 | 0056; C; 0076; # LATIN CAPITAL LETTER V | ||
86 | 0057; C; 0077; # LATIN CAPITAL LETTER W | ||
87 | 0058; C; 0078; # LATIN CAPITAL LETTER X | ||
88 | 0059; C; 0079; # LATIN CAPITAL LETTER Y | ||
89 | 005A; C; 007A; # LATIN CAPITAL LETTER Z | ||
90 | 00B5; C; 03BC; # MICRO SIGN | ||
91 | 00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE | ||
92 | 00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE | ||
93 | 00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX | ||
94 | 00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE | ||
95 | 00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS | ||
96 | 00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE | ||
97 | 00C6; C; 00E6; # LATIN CAPITAL LETTER AE | ||
98 | 00C7; C; 00E7; # LATIN CAPITAL LETTER C WITH CEDILLA | ||
99 | 00C8; C; 00E8; # LATIN CAPITAL LETTER E WITH GRAVE | ||
100 | 00C9; C; 00E9; # LATIN CAPITAL LETTER E WITH ACUTE | ||
101 | 00CA; C; 00EA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX | ||
102 | 00CB; C; 00EB; # LATIN CAPITAL LETTER E WITH DIAERESIS | ||
103 | 00CC; C; 00EC; # LATIN CAPITAL LETTER I WITH GRAVE | ||
104 | 00CD; C; 00ED; # LATIN CAPITAL LETTER I WITH ACUTE | ||
105 | 00CE; C; 00EE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX | ||
106 | 00CF; C; 00EF; # LATIN CAPITAL LETTER I WITH DIAERESIS | ||
107 | 00D0; C; 00F0; # LATIN CAPITAL LETTER ETH | ||
108 | 00D1; C; 00F1; # LATIN CAPITAL LETTER N WITH TILDE | ||
109 | 00D2; C; 00F2; # LATIN CAPITAL LETTER O WITH GRAVE | ||
110 | 00D3; C; 00F3; # LATIN CAPITAL LETTER O WITH ACUTE | ||
111 | 00D4; C; 00F4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX | ||
112 | 00D5; C; 00F5; # LATIN CAPITAL LETTER O WITH TILDE | ||
113 | 00D6; C; 00F6; # LATIN CAPITAL LETTER O WITH DIAERESIS | ||
114 | 00D8; C; 00F8; # LATIN CAPITAL LETTER O WITH STROKE | ||
115 | 00D9; C; 00F9; # LATIN CAPITAL LETTER U WITH GRAVE | ||
116 | 00DA; C; 00FA; # LATIN CAPITAL LETTER U WITH ACUTE | ||
117 | 00DB; C; 00FB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX | ||
118 | 00DC; C; 00FC; # LATIN CAPITAL LETTER U WITH DIAERESIS | ||
119 | 00DD; C; 00FD; # LATIN CAPITAL LETTER Y WITH ACUTE | ||
120 | 00DE; C; 00FE; # LATIN CAPITAL LETTER THORN | ||
121 | 00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S | ||
122 | 0100; C; 0101; # LATIN CAPITAL LETTER A WITH MACRON | ||
123 | 0102; C; 0103; # LATIN CAPITAL LETTER A WITH BREVE | ||
124 | 0104; C; 0105; # LATIN CAPITAL LETTER A WITH OGONEK | ||
125 | 0106; C; 0107; # LATIN CAPITAL LETTER C WITH ACUTE | ||
126 | 0108; C; 0109; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX | ||
127 | 010A; C; 010B; # LATIN CAPITAL LETTER C WITH DOT ABOVE | ||
128 | 010C; C; 010D; # LATIN CAPITAL LETTER C WITH CARON | ||
129 | 010E; C; 010F; # LATIN CAPITAL LETTER D WITH CARON | ||
130 | 0110; C; 0111; # LATIN CAPITAL LETTER D WITH STROKE | ||
131 | 0112; C; 0113; # LATIN CAPITAL LETTER E WITH MACRON | ||
132 | 0114; C; 0115; # LATIN CAPITAL LETTER E WITH BREVE | ||
133 | 0116; C; 0117; # LATIN CAPITAL LETTER E WITH DOT ABOVE | ||
134 | 0118; C; 0119; # LATIN CAPITAL LETTER E WITH OGONEK | ||
135 | 011A; C; 011B; # LATIN CAPITAL LETTER E WITH CARON | ||
136 | 011C; C; 011D; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX | ||
137 | 011E; C; 011F; # LATIN CAPITAL LETTER G WITH BREVE | ||
138 | 0120; C; 0121; # LATIN CAPITAL LETTER G WITH DOT ABOVE | ||
139 | 0122; C; 0123; # LATIN CAPITAL LETTER G WITH CEDILLA | ||
140 | 0124; C; 0125; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX | ||
141 | 0126; C; 0127; # LATIN CAPITAL LETTER H WITH STROKE | ||
142 | 0128; C; 0129; # LATIN CAPITAL LETTER I WITH TILDE | ||
143 | 012A; C; 012B; # LATIN CAPITAL LETTER I WITH MACRON | ||
144 | 012C; C; 012D; # LATIN CAPITAL LETTER I WITH BREVE | ||
145 | 012E; C; 012F; # LATIN CAPITAL LETTER I WITH OGONEK | ||
146 | 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE | ||
147 | 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE | ||
148 | 0132; C; 0133; # LATIN CAPITAL LIGATURE IJ | ||
149 | 0134; C; 0135; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX | ||
150 | 0136; C; 0137; # LATIN CAPITAL LETTER K WITH CEDILLA | ||
151 | 0139; C; 013A; # LATIN CAPITAL LETTER L WITH ACUTE | ||
152 | 013B; C; 013C; # LATIN CAPITAL LETTER L WITH CEDILLA | ||
153 | 013D; C; 013E; # LATIN CAPITAL LETTER L WITH CARON | ||
154 | 013F; C; 0140; # LATIN CAPITAL LETTER L WITH MIDDLE DOT | ||
155 | 0141; C; 0142; # LATIN CAPITAL LETTER L WITH STROKE | ||
156 | 0143; C; 0144; # LATIN CAPITAL LETTER N WITH ACUTE | ||
157 | 0145; C; 0146; # LATIN CAPITAL LETTER N WITH CEDILLA | ||
158 | 0147; C; 0148; # LATIN CAPITAL LETTER N WITH CARON | ||
159 | 0149; F; 02BC 006E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE | ||
160 | 014A; C; 014B; # LATIN CAPITAL LETTER ENG | ||
161 | 014C; C; 014D; # LATIN CAPITAL LETTER O WITH MACRON | ||
162 | 014E; C; 014F; # LATIN CAPITAL LETTER O WITH BREVE | ||
163 | 0150; C; 0151; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE | ||
164 | 0152; C; 0153; # LATIN CAPITAL LIGATURE OE | ||
165 | 0154; C; 0155; # LATIN CAPITAL LETTER R WITH ACUTE | ||
166 | 0156; C; 0157; # LATIN CAPITAL LETTER R WITH CEDILLA | ||
167 | 0158; C; 0159; # LATIN CAPITAL LETTER R WITH CARON | ||
168 | 015A; C; 015B; # LATIN CAPITAL LETTER S WITH ACUTE | ||
169 | 015C; C; 015D; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX | ||
170 | 015E; C; 015F; # LATIN CAPITAL LETTER S WITH CEDILLA | ||
171 | 0160; C; 0161; # LATIN CAPITAL LETTER S WITH CARON | ||
172 | 0162; C; 0163; # LATIN CAPITAL LETTER T WITH CEDILLA | ||
173 | 0164; C; 0165; # LATIN CAPITAL LETTER T WITH CARON | ||
174 | 0166; C; 0167; # LATIN CAPITAL LETTER T WITH STROKE | ||
175 | 0168; C; 0169; # LATIN CAPITAL LETTER U WITH TILDE | ||
176 | 016A; C; 016B; # LATIN CAPITAL LETTER U WITH MACRON | ||
177 | 016C; C; 016D; # LATIN CAPITAL LETTER U WITH BREVE | ||
178 | 016E; C; 016F; # LATIN CAPITAL LETTER U WITH RING ABOVE | ||
179 | 0170; C; 0171; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE | ||
180 | 0172; C; 0173; # LATIN CAPITAL LETTER U WITH OGONEK | ||
181 | 0174; C; 0175; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX | ||
182 | 0176; C; 0177; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX | ||
183 | 0178; C; 00FF; # LATIN CAPITAL LETTER Y WITH DIAERESIS | ||
184 | 0179; C; 017A; # LATIN CAPITAL LETTER Z WITH ACUTE | ||
185 | 017B; C; 017C; # LATIN CAPITAL LETTER Z WITH DOT ABOVE | ||
186 | 017D; C; 017E; # LATIN CAPITAL LETTER Z WITH CARON | ||
187 | 017F; C; 0073; # LATIN SMALL LETTER LONG S | ||
188 | 0181; C; 0253; # LATIN CAPITAL LETTER B WITH HOOK | ||
189 | 0182; C; 0183; # LATIN CAPITAL LETTER B WITH TOPBAR | ||
190 | 0184; C; 0185; # LATIN CAPITAL LETTER TONE SIX | ||
191 | 0186; C; 0254; # LATIN CAPITAL LETTER OPEN O | ||
192 | 0187; C; 0188; # LATIN CAPITAL LETTER C WITH HOOK | ||
193 | 0189; C; 0256; # LATIN CAPITAL LETTER AFRICAN D | ||
194 | 018A; C; 0257; # LATIN CAPITAL LETTER D WITH HOOK | ||
195 | 018B; C; 018C; # LATIN CAPITAL LETTER D WITH TOPBAR | ||
196 | 018E; C; 01DD; # LATIN CAPITAL LETTER REVERSED E | ||
197 | 018F; C; 0259; # LATIN CAPITAL LETTER SCHWA | ||
198 | 0190; C; 025B; # LATIN CAPITAL LETTER OPEN E | ||
199 | 0191; C; 0192; # LATIN CAPITAL LETTER F WITH HOOK | ||
200 | 0193; C; 0260; # LATIN CAPITAL LETTER G WITH HOOK | ||
201 | 0194; C; 0263; # LATIN CAPITAL LETTER GAMMA | ||
202 | 0196; C; 0269; # LATIN CAPITAL LETTER IOTA | ||
203 | 0197; C; 0268; # LATIN CAPITAL LETTER I WITH STROKE | ||
204 | 0198; C; 0199; # LATIN CAPITAL LETTER K WITH HOOK | ||
205 | 019C; C; 026F; # LATIN CAPITAL LETTER TURNED M | ||
206 | 019D; C; 0272; # LATIN CAPITAL LETTER N WITH LEFT HOOK | ||
207 | 019F; C; 0275; # LATIN CAPITAL LETTER O WITH MIDDLE TILDE | ||
208 | 01A0; C; 01A1; # LATIN CAPITAL LETTER O WITH HORN | ||
209 | 01A2; C; 01A3; # LATIN CAPITAL LETTER OI | ||
210 | 01A4; C; 01A5; # LATIN CAPITAL LETTER P WITH HOOK | ||
211 | 01A6; C; 0280; # LATIN LETTER YR | ||
212 | 01A7; C; 01A8; # LATIN CAPITAL LETTER TONE TWO | ||
213 | 01A9; C; 0283; # LATIN CAPITAL LETTER ESH | ||
214 | 01AC; C; 01AD; # LATIN CAPITAL LETTER T WITH HOOK | ||
215 | 01AE; C; 0288; # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK | ||
216 | 01AF; C; 01B0; # LATIN CAPITAL LETTER U WITH HORN | ||
217 | 01B1; C; 028A; # LATIN CAPITAL LETTER UPSILON | ||
218 | 01B2; C; 028B; # LATIN CAPITAL LETTER V WITH HOOK | ||
219 | 01B3; C; 01B4; # LATIN CAPITAL LETTER Y WITH HOOK | ||
220 | 01B5; C; 01B6; # LATIN CAPITAL LETTER Z WITH STROKE | ||
221 | 01B7; C; 0292; # LATIN CAPITAL LETTER EZH | ||
222 | 01B8; C; 01B9; # LATIN CAPITAL LETTER EZH REVERSED | ||
223 | 01BC; C; 01BD; # LATIN CAPITAL LETTER TONE FIVE | ||
224 | 01C4; C; 01C6; # LATIN CAPITAL LETTER DZ WITH CARON | ||
225 | 01C5; C; 01C6; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON | ||
226 | 01C7; C; 01C9; # LATIN CAPITAL LETTER LJ | ||
227 | 01C8; C; 01C9; # LATIN CAPITAL LETTER L WITH SMALL LETTER J | ||
228 | 01CA; C; 01CC; # LATIN CAPITAL LETTER NJ | ||
229 | 01CB; C; 01CC; # LATIN CAPITAL LETTER N WITH SMALL LETTER J | ||
230 | 01CD; C; 01CE; # LATIN CAPITAL LETTER A WITH CARON | ||
231 | 01CF; C; 01D0; # LATIN CAPITAL LETTER I WITH CARON | ||
232 | 01D1; C; 01D2; # LATIN CAPITAL LETTER O WITH CARON | ||
233 | 01D3; C; 01D4; # LATIN CAPITAL LETTER U WITH CARON | ||
234 | 01D5; C; 01D6; # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON | ||
235 | 01D7; C; 01D8; # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE | ||
236 | 01D9; C; 01DA; # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON | ||
237 | 01DB; C; 01DC; # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE | ||
238 | 01DE; C; 01DF; # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON | ||
239 | 01E0; C; 01E1; # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON | ||
240 | 01E2; C; 01E3; # LATIN CAPITAL LETTER AE WITH MACRON | ||
241 | 01E4; C; 01E5; # LATIN CAPITAL LETTER G WITH STROKE | ||
242 | 01E6; C; 01E7; # LATIN CAPITAL LETTER G WITH CARON | ||
243 | 01E8; C; 01E9; # LATIN CAPITAL LETTER K WITH CARON | ||
244 | 01EA; C; 01EB; # LATIN CAPITAL LETTER O WITH OGONEK | ||
245 | 01EC; C; 01ED; # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON | ||
246 | 01EE; C; 01EF; # LATIN CAPITAL LETTER EZH WITH CARON | ||
247 | 01F0; F; 006A 030C; # LATIN SMALL LETTER J WITH CARON | ||
248 | 01F1; C; 01F3; # LATIN CAPITAL LETTER DZ | ||
249 | 01F2; C; 01F3; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z | ||
250 | 01F4; C; 01F5; # LATIN CAPITAL LETTER G WITH ACUTE | ||
251 | 01F6; C; 0195; # LATIN CAPITAL LETTER HWAIR | ||
252 | 01F7; C; 01BF; # LATIN CAPITAL LETTER WYNN | ||
253 | 01F8; C; 01F9; # LATIN CAPITAL LETTER N WITH GRAVE | ||
254 | 01FA; C; 01FB; # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE | ||
255 | 01FC; C; 01FD; # LATIN CAPITAL LETTER AE WITH ACUTE | ||
256 | 01FE; C; 01FF; # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE | ||
257 | 0200; C; 0201; # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE | ||
258 | 0202; C; 0203; # LATIN CAPITAL LETTER A WITH INVERTED BREVE | ||
259 | 0204; C; 0205; # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE | ||
260 | 0206; C; 0207; # LATIN CAPITAL LETTER E WITH INVERTED BREVE | ||
261 | 0208; C; 0209; # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE | ||
262 | 020A; C; 020B; # LATIN CAPITAL LETTER I WITH INVERTED BREVE | ||
263 | 020C; C; 020D; # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE | ||
264 | 020E; C; 020F; # LATIN CAPITAL LETTER O WITH INVERTED BREVE | ||
265 | 0210; C; 0211; # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE | ||
266 | 0212; C; 0213; # LATIN CAPITAL LETTER R WITH INVERTED BREVE | ||
267 | 0214; C; 0215; # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE | ||
268 | 0216; C; 0217; # LATIN CAPITAL LETTER U WITH INVERTED BREVE | ||
269 | 0218; C; 0219; # LATIN CAPITAL LETTER S WITH COMMA BELOW | ||
270 | 021A; C; 021B; # LATIN CAPITAL LETTER T WITH COMMA BELOW | ||
271 | 021C; C; 021D; # LATIN CAPITAL LETTER YOGH | ||
272 | 021E; C; 021F; # LATIN CAPITAL LETTER H WITH CARON | ||
273 | 0220; C; 019E; # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG | ||
274 | 0222; C; 0223; # LATIN CAPITAL LETTER OU | ||
275 | 0224; C; 0225; # LATIN CAPITAL LETTER Z WITH HOOK | ||
276 | 0226; C; 0227; # LATIN CAPITAL LETTER A WITH DOT ABOVE | ||
277 | 0228; C; 0229; # LATIN CAPITAL LETTER E WITH CEDILLA | ||
278 | 022A; C; 022B; # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON | ||
279 | 022C; C; 022D; # LATIN CAPITAL LETTER O WITH TILDE AND MACRON | ||
280 | 022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE | ||
281 | 0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON | ||
282 | 0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON | ||
283 | 023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE | ||
284 | 023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE | ||
285 | 023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR | ||
286 | 023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE | ||
287 | 0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP | ||
288 | 0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE | ||
289 | 0244; C; 0289; # LATIN CAPITAL LETTER U BAR | ||
290 | 0245; C; 028C; # LATIN CAPITAL LETTER TURNED V | ||
291 | 0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE | ||
292 | 0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE | ||
293 | 024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL | ||
294 | 024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE | ||
295 | 024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE | ||
296 | 0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI | ||
297 | 0370; C; 0371; # GREEK CAPITAL LETTER HETA | ||
298 | 0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI | ||
299 | 0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA | ||
300 | 037F; C; 03F3; # GREEK CAPITAL LETTER YOT | ||
301 | 0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS | ||
302 | 0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS | ||
303 | 0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS | ||
304 | 038A; C; 03AF; # GREEK CAPITAL LETTER IOTA WITH TONOS | ||
305 | 038C; C; 03CC; # GREEK CAPITAL LETTER OMICRON WITH TONOS | ||
306 | 038E; C; 03CD; # GREEK CAPITAL LETTER UPSILON WITH TONOS | ||
307 | 038F; C; 03CE; # GREEK CAPITAL LETTER OMEGA WITH TONOS | ||
308 | 0390; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS | ||
309 | 0391; C; 03B1; # GREEK CAPITAL LETTER ALPHA | ||
310 | 0392; C; 03B2; # GREEK CAPITAL LETTER BETA | ||
311 | 0393; C; 03B3; # GREEK CAPITAL LETTER GAMMA | ||
312 | 0394; C; 03B4; # GREEK CAPITAL LETTER DELTA | ||
313 | 0395; C; 03B5; # GREEK CAPITAL LETTER EPSILON | ||
314 | 0396; C; 03B6; # GREEK CAPITAL LETTER ZETA | ||
315 | 0397; C; 03B7; # GREEK CAPITAL LETTER ETA | ||
316 | 0398; C; 03B8; # GREEK CAPITAL LETTER THETA | ||
317 | 0399; C; 03B9; # GREEK CAPITAL LETTER IOTA | ||
318 | 039A; C; 03BA; # GREEK CAPITAL LETTER KAPPA | ||
319 | 039B; C; 03BB; # GREEK CAPITAL LETTER LAMDA | ||
320 | 039C; C; 03BC; # GREEK CAPITAL LETTER MU | ||
321 | 039D; C; 03BD; # GREEK CAPITAL LETTER NU | ||
322 | 039E; C; 03BE; # GREEK CAPITAL LETTER XI | ||
323 | 039F; C; 03BF; # GREEK CAPITAL LETTER OMICRON | ||
324 | 03A0; C; 03C0; # GREEK CAPITAL LETTER PI | ||
325 | 03A1; C; 03C1; # GREEK CAPITAL LETTER RHO | ||
326 | 03A3; C; 03C3; # GREEK CAPITAL LETTER SIGMA | ||
327 | 03A4; C; 03C4; # GREEK CAPITAL LETTER TAU | ||
328 | 03A5; C; 03C5; # GREEK CAPITAL LETTER UPSILON | ||
329 | 03A6; C; 03C6; # GREEK CAPITAL LETTER PHI | ||
330 | 03A7; C; 03C7; # GREEK CAPITAL LETTER CHI | ||
331 | 03A8; C; 03C8; # GREEK CAPITAL LETTER PSI | ||
332 | 03A9; C; 03C9; # GREEK CAPITAL LETTER OMEGA | ||
333 | 03AA; C; 03CA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA | ||
334 | 03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA | ||
335 | 03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS | ||
336 | 03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA | ||
337 | 03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL | ||
338 | 03D0; C; 03B2; # GREEK BETA SYMBOL | ||
339 | 03D1; C; 03B8; # GREEK THETA SYMBOL | ||
340 | 03D5; C; 03C6; # GREEK PHI SYMBOL | ||
341 | 03D6; C; 03C0; # GREEK PI SYMBOL | ||
342 | 03D8; C; 03D9; # GREEK LETTER ARCHAIC KOPPA | ||
343 | 03DA; C; 03DB; # GREEK LETTER STIGMA | ||
344 | 03DC; C; 03DD; # GREEK LETTER DIGAMMA | ||
345 | 03DE; C; 03DF; # GREEK LETTER KOPPA | ||
346 | 03E0; C; 03E1; # GREEK LETTER SAMPI | ||
347 | 03E2; C; 03E3; # COPTIC CAPITAL LETTER SHEI | ||
348 | 03E4; C; 03E5; # COPTIC CAPITAL LETTER FEI | ||
349 | 03E6; C; 03E7; # COPTIC CAPITAL LETTER KHEI | ||
350 | 03E8; C; 03E9; # COPTIC CAPITAL LETTER HORI | ||
351 | 03EA; C; 03EB; # COPTIC CAPITAL LETTER GANGIA | ||
352 | 03EC; C; 03ED; # COPTIC CAPITAL LETTER SHIMA | ||
353 | 03EE; C; 03EF; # COPTIC CAPITAL LETTER DEI | ||
354 | 03F0; C; 03BA; # GREEK KAPPA SYMBOL | ||
355 | 03F1; C; 03C1; # GREEK RHO SYMBOL | ||
356 | 03F4; C; 03B8; # GREEK CAPITAL THETA SYMBOL | ||
357 | 03F5; C; 03B5; # GREEK LUNATE EPSILON SYMBOL | ||
358 | 03F7; C; 03F8; # GREEK CAPITAL LETTER SHO | ||
359 | 03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL | ||
360 | 03FA; C; 03FB; # GREEK CAPITAL LETTER SAN | ||
361 | 03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL | ||
362 | 03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL | ||
363 | 03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL | ||
364 | 0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE | ||
365 | 0401; C; 0451; # CYRILLIC CAPITAL LETTER IO | ||
366 | 0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE | ||
367 | 0403; C; 0453; # CYRILLIC CAPITAL LETTER GJE | ||
368 | 0404; C; 0454; # CYRILLIC CAPITAL LETTER UKRAINIAN IE | ||
369 | 0405; C; 0455; # CYRILLIC CAPITAL LETTER DZE | ||
370 | 0406; C; 0456; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I | ||
371 | 0407; C; 0457; # CYRILLIC CAPITAL LETTER YI | ||
372 | 0408; C; 0458; # CYRILLIC CAPITAL LETTER JE | ||
373 | 0409; C; 0459; # CYRILLIC CAPITAL LETTER LJE | ||
374 | 040A; C; 045A; # CYRILLIC CAPITAL LETTER NJE | ||
375 | 040B; C; 045B; # CYRILLIC CAPITAL LETTER TSHE | ||
376 | 040C; C; 045C; # CYRILLIC CAPITAL LETTER KJE | ||
377 | 040D; C; 045D; # CYRILLIC CAPITAL LETTER I WITH GRAVE | ||
378 | 040E; C; 045E; # CYRILLIC CAPITAL LETTER SHORT U | ||
379 | 040F; C; 045F; # CYRILLIC CAPITAL LETTER DZHE | ||
380 | 0410; C; 0430; # CYRILLIC CAPITAL LETTER A | ||
381 | 0411; C; 0431; # CYRILLIC CAPITAL LETTER BE | ||
382 | 0412; C; 0432; # CYRILLIC CAPITAL LETTER VE | ||
383 | 0413; C; 0433; # CYRILLIC CAPITAL LETTER GHE | ||
384 | 0414; C; 0434; # CYRILLIC CAPITAL LETTER DE | ||
385 | 0415; C; 0435; # CYRILLIC CAPITAL LETTER IE | ||
386 | 0416; C; 0436; # CYRILLIC CAPITAL LETTER ZHE | ||
387 | 0417; C; 0437; # CYRILLIC CAPITAL LETTER ZE | ||
388 | 0418; C; 0438; # CYRILLIC CAPITAL LETTER I | ||
389 | 0419; C; 0439; # CYRILLIC CAPITAL LETTER SHORT I | ||
390 | 041A; C; 043A; # CYRILLIC CAPITAL LETTER KA | ||
391 | 041B; C; 043B; # CYRILLIC CAPITAL LETTER EL | ||
392 | 041C; C; 043C; # CYRILLIC CAPITAL LETTER EM | ||
393 | 041D; C; 043D; # CYRILLIC CAPITAL LETTER EN | ||
394 | 041E; C; 043E; # CYRILLIC CAPITAL LETTER O | ||
395 | 041F; C; 043F; # CYRILLIC CAPITAL LETTER PE | ||
396 | 0420; C; 0440; # CYRILLIC CAPITAL LETTER ER | ||
397 | 0421; C; 0441; # CYRILLIC CAPITAL LETTER ES | ||
398 | 0422; C; 0442; # CYRILLIC CAPITAL LETTER TE | ||
399 | 0423; C; 0443; # CYRILLIC CAPITAL LETTER U | ||
400 | 0424; C; 0444; # CYRILLIC CAPITAL LETTER EF | ||
401 | 0425; C; 0445; # CYRILLIC CAPITAL LETTER HA | ||
402 | 0426; C; 0446; # CYRILLIC CAPITAL LETTER TSE | ||
403 | 0427; C; 0447; # CYRILLIC CAPITAL LETTER CHE | ||
404 | 0428; C; 0448; # CYRILLIC CAPITAL LETTER SHA | ||
405 | 0429; C; 0449; # CYRILLIC CAPITAL LETTER SHCHA | ||
406 | 042A; C; 044A; # CYRILLIC CAPITAL LETTER HARD SIGN | ||
407 | 042B; C; 044B; # CYRILLIC CAPITAL LETTER YERU | ||
408 | 042C; C; 044C; # CYRILLIC CAPITAL LETTER SOFT SIGN | ||
409 | 042D; C; 044D; # CYRILLIC CAPITAL LETTER E | ||
410 | 042E; C; 044E; # CYRILLIC CAPITAL LETTER YU | ||
411 | 042F; C; 044F; # CYRILLIC CAPITAL LETTER YA | ||
412 | 0460; C; 0461; # CYRILLIC CAPITAL LETTER OMEGA | ||
413 | 0462; C; 0463; # CYRILLIC CAPITAL LETTER YAT | ||
414 | 0464; C; 0465; # CYRILLIC CAPITAL LETTER IOTIFIED E | ||
415 | 0466; C; 0467; # CYRILLIC CAPITAL LETTER LITTLE YUS | ||
416 | 0468; C; 0469; # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS | ||
417 | 046A; C; 046B; # CYRILLIC CAPITAL LETTER BIG YUS | ||
418 | 046C; C; 046D; # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS | ||
419 | 046E; C; 046F; # CYRILLIC CAPITAL LETTER KSI | ||
420 | 0470; C; 0471; # CYRILLIC CAPITAL LETTER PSI | ||
421 | 0472; C; 0473; # CYRILLIC CAPITAL LETTER FITA | ||
422 | 0474; C; 0475; # CYRILLIC CAPITAL LETTER IZHITSA | ||
423 | 0476; C; 0477; # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT | ||
424 | 0478; C; 0479; # CYRILLIC CAPITAL LETTER UK | ||
425 | 047A; C; 047B; # CYRILLIC CAPITAL LETTER ROUND OMEGA | ||
426 | 047C; C; 047D; # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO | ||
427 | 047E; C; 047F; # CYRILLIC CAPITAL LETTER OT | ||
428 | 0480; C; 0481; # CYRILLIC CAPITAL LETTER KOPPA | ||
429 | 048A; C; 048B; # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL | ||
430 | 048C; C; 048D; # CYRILLIC CAPITAL LETTER SEMISOFT SIGN | ||
431 | 048E; C; 048F; # CYRILLIC CAPITAL LETTER ER WITH TICK | ||
432 | 0490; C; 0491; # CYRILLIC CAPITAL LETTER GHE WITH UPTURN | ||
433 | 0492; C; 0493; # CYRILLIC CAPITAL LETTER GHE WITH STROKE | ||
434 | 0494; C; 0495; # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK | ||
435 | 0496; C; 0497; # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER | ||
436 | 0498; C; 0499; # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER | ||
437 | 049A; C; 049B; # CYRILLIC CAPITAL LETTER KA WITH DESCENDER | ||
438 | 049C; C; 049D; # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE | ||
439 | 049E; C; 049F; # CYRILLIC CAPITAL LETTER KA WITH STROKE | ||
440 | 04A0; C; 04A1; # CYRILLIC CAPITAL LETTER BASHKIR KA | ||
441 | 04A2; C; 04A3; # CYRILLIC CAPITAL LETTER EN WITH DESCENDER | ||
442 | 04A4; C; 04A5; # CYRILLIC CAPITAL LIGATURE EN GHE | ||
443 | 04A6; C; 04A7; # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK | ||
444 | 04A8; C; 04A9; # CYRILLIC CAPITAL LETTER ABKHASIAN HA | ||
445 | 04AA; C; 04AB; # CYRILLIC CAPITAL LETTER ES WITH DESCENDER | ||
446 | 04AC; C; 04AD; # CYRILLIC CAPITAL LETTER TE WITH DESCENDER | ||
447 | 04AE; C; 04AF; # CYRILLIC CAPITAL LETTER STRAIGHT U | ||
448 | 04B0; C; 04B1; # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE | ||
449 | 04B2; C; 04B3; # CYRILLIC CAPITAL LETTER HA WITH DESCENDER | ||
450 | 04B4; C; 04B5; # CYRILLIC CAPITAL LIGATURE TE TSE | ||
451 | 04B6; C; 04B7; # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER | ||
452 | 04B8; C; 04B9; # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE | ||
453 | 04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA | ||
454 | 04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE | ||
455 | 04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER | ||
456 | 04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA | ||
457 | 04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE | ||
458 | 04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK | ||
459 | 04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL | ||
460 | 04C7; C; 04C8; # CYRILLIC CAPITAL LETTER EN WITH HOOK | ||
461 | 04C9; C; 04CA; # CYRILLIC CAPITAL LETTER EN WITH TAIL | ||
462 | 04CB; C; 04CC; # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE | ||
463 | 04CD; C; 04CE; # CYRILLIC CAPITAL LETTER EM WITH TAIL | ||
464 | 04D0; C; 04D1; # CYRILLIC CAPITAL LETTER A WITH BREVE | ||
465 | 04D2; C; 04D3; # CYRILLIC CAPITAL LETTER A WITH DIAERESIS | ||
466 | 04D4; C; 04D5; # CYRILLIC CAPITAL LIGATURE A IE | ||
467 | 04D6; C; 04D7; # CYRILLIC CAPITAL LETTER IE WITH BREVE | ||
468 | 04D8; C; 04D9; # CYRILLIC CAPITAL LETTER SCHWA | ||
469 | 04DA; C; 04DB; # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS | ||
470 | 04DC; C; 04DD; # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS | ||
471 | 04DE; C; 04DF; # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS | ||
472 | 04E0; C; 04E1; # CYRILLIC CAPITAL LETTER ABKHASIAN DZE | ||
473 | 04E2; C; 04E3; # CYRILLIC CAPITAL LETTER I WITH MACRON | ||
474 | 04E4; C; 04E5; # CYRILLIC CAPITAL LETTER I WITH DIAERESIS | ||
475 | 04E6; C; 04E7; # CYRILLIC CAPITAL LETTER O WITH DIAERESIS | ||
476 | 04E8; C; 04E9; # CYRILLIC CAPITAL LETTER BARRED O | ||
477 | 04EA; C; 04EB; # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS | ||
478 | 04EC; C; 04ED; # CYRILLIC CAPITAL LETTER E WITH DIAERESIS | ||
479 | 04EE; C; 04EF; # CYRILLIC CAPITAL LETTER U WITH MACRON | ||
480 | 04F0; C; 04F1; # CYRILLIC CAPITAL LETTER U WITH DIAERESIS | ||
481 | 04F2; C; 04F3; # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE | ||
482 | 04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS | ||
483 | 04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER | ||
484 | 04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS | ||
485 | 04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK | ||
486 | 04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK | ||
487 | 04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE | ||
488 | 0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE | ||
489 | 0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE | ||
490 | 0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE | ||
491 | 0506; C; 0507; # CYRILLIC CAPITAL LETTER KOMI DZJE | ||
492 | 0508; C; 0509; # CYRILLIC CAPITAL LETTER KOMI LJE | ||
493 | 050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE | ||
494 | 050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE | ||
495 | 050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE | ||
496 | 0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE | ||
497 | 0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK | ||
498 | 0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA | ||
499 | 0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA | ||
500 | 0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE | ||
501 | 051A; C; 051B; # CYRILLIC CAPITAL LETTER QA | ||
502 | 051C; C; 051D; # CYRILLIC CAPITAL LETTER WE | ||
503 | 051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA | ||
504 | 0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK | ||
505 | 0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK | ||
506 | 0524; C; 0525; # CYRILLIC CAPITAL LETTER PE WITH DESCENDER | ||
507 | 0526; C; 0527; # CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER | ||
508 | 0528; C; 0529; # CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK | ||
509 | 052A; C; 052B; # CYRILLIC CAPITAL LETTER DZZHE | ||
510 | 052C; C; 052D; # CYRILLIC CAPITAL LETTER DCHE | ||
511 | 052E; C; 052F; # CYRILLIC CAPITAL LETTER EL WITH DESCENDER | ||
512 | 0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB | ||
513 | 0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN | ||
514 | 0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM | ||
515 | 0534; C; 0564; # ARMENIAN CAPITAL LETTER DA | ||
516 | 0535; C; 0565; # ARMENIAN CAPITAL LETTER ECH | ||
517 | 0536; C; 0566; # ARMENIAN CAPITAL LETTER ZA | ||
518 | 0537; C; 0567; # ARMENIAN CAPITAL LETTER EH | ||
519 | 0538; C; 0568; # ARMENIAN CAPITAL LETTER ET | ||
520 | 0539; C; 0569; # ARMENIAN CAPITAL LETTER TO | ||
521 | 053A; C; 056A; # ARMENIAN CAPITAL LETTER ZHE | ||
522 | 053B; C; 056B; # ARMENIAN CAPITAL LETTER INI | ||
523 | 053C; C; 056C; # ARMENIAN CAPITAL LETTER LIWN | ||
524 | 053D; C; 056D; # ARMENIAN CAPITAL LETTER XEH | ||
525 | 053E; C; 056E; # ARMENIAN CAPITAL LETTER CA | ||
526 | 053F; C; 056F; # ARMENIAN CAPITAL LETTER KEN | ||
527 | 0540; C; 0570; # ARMENIAN CAPITAL LETTER HO | ||
528 | 0541; C; 0571; # ARMENIAN CAPITAL LETTER JA | ||
529 | 0542; C; 0572; # ARMENIAN CAPITAL LETTER GHAD | ||
530 | 0543; C; 0573; # ARMENIAN CAPITAL LETTER CHEH | ||
531 | 0544; C; 0574; # ARMENIAN CAPITAL LETTER MEN | ||
532 | 0545; C; 0575; # ARMENIAN CAPITAL LETTER YI | ||
533 | 0546; C; 0576; # ARMENIAN CAPITAL LETTER NOW | ||
534 | 0547; C; 0577; # ARMENIAN CAPITAL LETTER SHA | ||
535 | 0548; C; 0578; # ARMENIAN CAPITAL LETTER VO | ||
536 | 0549; C; 0579; # ARMENIAN CAPITAL LETTER CHA | ||
537 | 054A; C; 057A; # ARMENIAN CAPITAL LETTER PEH | ||
538 | 054B; C; 057B; # ARMENIAN CAPITAL LETTER JHEH | ||
539 | 054C; C; 057C; # ARMENIAN CAPITAL LETTER RA | ||
540 | 054D; C; 057D; # ARMENIAN CAPITAL LETTER SEH | ||
541 | 054E; C; 057E; # ARMENIAN CAPITAL LETTER VEW | ||
542 | 054F; C; 057F; # ARMENIAN CAPITAL LETTER TIWN | ||
543 | 0550; C; 0580; # ARMENIAN CAPITAL LETTER REH | ||
544 | 0551; C; 0581; # ARMENIAN CAPITAL LETTER CO | ||
545 | 0552; C; 0582; # ARMENIAN CAPITAL LETTER YIWN | ||
546 | 0553; C; 0583; # ARMENIAN CAPITAL LETTER PIWR | ||
547 | 0554; C; 0584; # ARMENIAN CAPITAL LETTER KEH | ||
548 | 0555; C; 0585; # ARMENIAN CAPITAL LETTER OH | ||
549 | 0556; C; 0586; # ARMENIAN CAPITAL LETTER FEH | ||
550 | 0587; F; 0565 0582; # ARMENIAN SMALL LIGATURE ECH YIWN | ||
551 | 10A0; C; 2D00; # GEORGIAN CAPITAL LETTER AN | ||
552 | 10A1; C; 2D01; # GEORGIAN CAPITAL LETTER BAN | ||
553 | 10A2; C; 2D02; # GEORGIAN CAPITAL LETTER GAN | ||
554 | 10A3; C; 2D03; # GEORGIAN CAPITAL LETTER DON | ||
555 | 10A4; C; 2D04; # GEORGIAN CAPITAL LETTER EN | ||
556 | 10A5; C; 2D05; # GEORGIAN CAPITAL LETTER VIN | ||
557 | 10A6; C; 2D06; # GEORGIAN CAPITAL LETTER ZEN | ||
558 | 10A7; C; 2D07; # GEORGIAN CAPITAL LETTER TAN | ||
559 | 10A8; C; 2D08; # GEORGIAN CAPITAL LETTER IN | ||
560 | 10A9; C; 2D09; # GEORGIAN CAPITAL LETTER KAN | ||
561 | 10AA; C; 2D0A; # GEORGIAN CAPITAL LETTER LAS | ||
562 | 10AB; C; 2D0B; # GEORGIAN CAPITAL LETTER MAN | ||
563 | 10AC; C; 2D0C; # GEORGIAN CAPITAL LETTER NAR | ||
564 | 10AD; C; 2D0D; # GEORGIAN CAPITAL LETTER ON | ||
565 | 10AE; C; 2D0E; # GEORGIAN CAPITAL LETTER PAR | ||
566 | 10AF; C; 2D0F; # GEORGIAN CAPITAL LETTER ZHAR | ||
567 | 10B0; C; 2D10; # GEORGIAN CAPITAL LETTER RAE | ||
568 | 10B1; C; 2D11; # GEORGIAN CAPITAL LETTER SAN | ||
569 | 10B2; C; 2D12; # GEORGIAN CAPITAL LETTER TAR | ||
570 | 10B3; C; 2D13; # GEORGIAN CAPITAL LETTER UN | ||
571 | 10B4; C; 2D14; # GEORGIAN CAPITAL LETTER PHAR | ||
572 | 10B5; C; 2D15; # GEORGIAN CAPITAL LETTER KHAR | ||
573 | 10B6; C; 2D16; # GEORGIAN CAPITAL LETTER GHAN | ||
574 | 10B7; C; 2D17; # GEORGIAN CAPITAL LETTER QAR | ||
575 | 10B8; C; 2D18; # GEORGIAN CAPITAL LETTER SHIN | ||
576 | 10B9; C; 2D19; # GEORGIAN CAPITAL LETTER CHIN | ||
577 | 10BA; C; 2D1A; # GEORGIAN CAPITAL LETTER CAN | ||
578 | 10BB; C; 2D1B; # GEORGIAN CAPITAL LETTER JIL | ||
579 | 10BC; C; 2D1C; # GEORGIAN CAPITAL LETTER CIL | ||
580 | 10BD; C; 2D1D; # GEORGIAN CAPITAL LETTER CHAR | ||
581 | 10BE; C; 2D1E; # GEORGIAN CAPITAL LETTER XAN | ||
582 | 10BF; C; 2D1F; # GEORGIAN CAPITAL LETTER JHAN | ||
583 | 10C0; C; 2D20; # GEORGIAN CAPITAL LETTER HAE | ||
584 | 10C1; C; 2D21; # GEORGIAN CAPITAL LETTER HE | ||
585 | 10C2; C; 2D22; # GEORGIAN CAPITAL LETTER HIE | ||
586 | 10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE | ||
587 | 10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR | ||
588 | 10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE | ||
589 | 10C7; C; 2D27; # GEORGIAN CAPITAL LETTER YN | ||
590 | 10CD; C; 2D2D; # GEORGIAN CAPITAL LETTER AEN | ||
591 | 13F8; C; 13F0; # CHEROKEE SMALL LETTER YE | ||
592 | 13F9; C; 13F1; # CHEROKEE SMALL LETTER YI | ||
593 | 13FA; C; 13F2; # CHEROKEE SMALL LETTER YO | ||
594 | 13FB; C; 13F3; # CHEROKEE SMALL LETTER YU | ||
595 | 13FC; C; 13F4; # CHEROKEE SMALL LETTER YV | ||
596 | 13FD; C; 13F5; # CHEROKEE SMALL LETTER MV | ||
597 | 1C80; C; 0432; # CYRILLIC SMALL LETTER ROUNDED VE | ||
598 | 1C81; C; 0434; # CYRILLIC SMALL LETTER LONG-LEGGED DE | ||
599 | 1C82; C; 043E; # CYRILLIC SMALL LETTER NARROW O | ||
600 | 1C83; C; 0441; # CYRILLIC SMALL LETTER WIDE ES | ||
601 | 1C84; C; 0442; # CYRILLIC SMALL LETTER TALL TE | ||
602 | 1C85; C; 0442; # CYRILLIC SMALL LETTER THREE-LEGGED TE | ||
603 | 1C86; C; 044A; # CYRILLIC SMALL LETTER TALL HARD SIGN | ||
604 | 1C87; C; 0463; # CYRILLIC SMALL LETTER TALL YAT | ||
605 | 1C88; C; A64B; # CYRILLIC SMALL LETTER UNBLENDED UK | ||
606 | 1C90; C; 10D0; # GEORGIAN MTAVRULI CAPITAL LETTER AN | ||
607 | 1C91; C; 10D1; # GEORGIAN MTAVRULI CAPITAL LETTER BAN | ||
608 | 1C92; C; 10D2; # GEORGIAN MTAVRULI CAPITAL LETTER GAN | ||
609 | 1C93; C; 10D3; # GEORGIAN MTAVRULI CAPITAL LETTER DON | ||
610 | 1C94; C; 10D4; # GEORGIAN MTAVRULI CAPITAL LETTER EN | ||
611 | 1C95; C; 10D5; # GEORGIAN MTAVRULI CAPITAL LETTER VIN | ||
612 | 1C96; C; 10D6; # GEORGIAN MTAVRULI CAPITAL LETTER ZEN | ||
613 | 1C97; C; 10D7; # GEORGIAN MTAVRULI CAPITAL LETTER TAN | ||
614 | 1C98; C; 10D8; # GEORGIAN MTAVRULI CAPITAL LETTER IN | ||
615 | 1C99; C; 10D9; # GEORGIAN MTAVRULI CAPITAL LETTER KAN | ||
616 | 1C9A; C; 10DA; # GEORGIAN MTAVRULI CAPITAL LETTER LAS | ||
617 | 1C9B; C; 10DB; # GEORGIAN MTAVRULI CAPITAL LETTER MAN | ||
618 | 1C9C; C; 10DC; # GEORGIAN MTAVRULI CAPITAL LETTER NAR | ||
619 | 1C9D; C; 10DD; # GEORGIAN MTAVRULI CAPITAL LETTER ON | ||
620 | 1C9E; C; 10DE; # GEORGIAN MTAVRULI CAPITAL LETTER PAR | ||
621 | 1C9F; C; 10DF; # GEORGIAN MTAVRULI CAPITAL LETTER ZHAR | ||
622 | 1CA0; C; 10E0; # GEORGIAN MTAVRULI CAPITAL LETTER RAE | ||
623 | 1CA1; C; 10E1; # GEORGIAN MTAVRULI CAPITAL LETTER SAN | ||
624 | 1CA2; C; 10E2; # GEORGIAN MTAVRULI CAPITAL LETTER TAR | ||
625 | 1CA3; C; 10E3; # GEORGIAN MTAVRULI CAPITAL LETTER UN | ||
626 | 1CA4; C; 10E4; # GEORGIAN MTAVRULI CAPITAL LETTER PHAR | ||
627 | 1CA5; C; 10E5; # GEORGIAN MTAVRULI CAPITAL LETTER KHAR | ||
628 | 1CA6; C; 10E6; # GEORGIAN MTAVRULI CAPITAL LETTER GHAN | ||
629 | 1CA7; C; 10E7; # GEORGIAN MTAVRULI CAPITAL LETTER QAR | ||
630 | 1CA8; C; 10E8; # GEORGIAN MTAVRULI CAPITAL LETTER SHIN | ||
631 | 1CA9; C; 10E9; # GEORGIAN MTAVRULI CAPITAL LETTER CHIN | ||
632 | 1CAA; C; 10EA; # GEORGIAN MTAVRULI CAPITAL LETTER CAN | ||
633 | 1CAB; C; 10EB; # GEORGIAN MTAVRULI CAPITAL LETTER JIL | ||
634 | 1CAC; C; 10EC; # GEORGIAN MTAVRULI CAPITAL LETTER CIL | ||
635 | 1CAD; C; 10ED; # GEORGIAN MTAVRULI CAPITAL LETTER CHAR | ||
636 | 1CAE; C; 10EE; # GEORGIAN MTAVRULI CAPITAL LETTER XAN | ||
637 | 1CAF; C; 10EF; # GEORGIAN MTAVRULI CAPITAL LETTER JHAN | ||
638 | 1CB0; C; 10F0; # GEORGIAN MTAVRULI CAPITAL LETTER HAE | ||
639 | 1CB1; C; 10F1; # GEORGIAN MTAVRULI CAPITAL LETTER HE | ||
640 | 1CB2; C; 10F2; # GEORGIAN MTAVRULI CAPITAL LETTER HIE | ||
641 | 1CB3; C; 10F3; # GEORGIAN MTAVRULI CAPITAL LETTER WE | ||
642 | 1CB4; C; 10F4; # GEORGIAN MTAVRULI CAPITAL LETTER HAR | ||
643 | 1CB5; C; 10F5; # GEORGIAN MTAVRULI CAPITAL LETTER HOE | ||
644 | 1CB6; C; 10F6; # GEORGIAN MTAVRULI CAPITAL LETTER FI | ||
645 | 1CB7; C; 10F7; # GEORGIAN MTAVRULI CAPITAL LETTER YN | ||
646 | 1CB8; C; 10F8; # GEORGIAN MTAVRULI CAPITAL LETTER ELIFI | ||
647 | 1CB9; C; 10F9; # GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN | ||
648 | 1CBA; C; 10FA; # GEORGIAN MTAVRULI CAPITAL LETTER AIN | ||
649 | 1CBD; C; 10FD; # GEORGIAN MTAVRULI CAPITAL LETTER AEN | ||
650 | 1CBE; C; 10FE; # GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN | ||
651 | 1CBF; C; 10FF; # GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN | ||
652 | 1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW | ||
653 | 1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE | ||
654 | 1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW | ||
655 | 1E06; C; 1E07; # LATIN CAPITAL LETTER B WITH LINE BELOW | ||
656 | 1E08; C; 1E09; # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE | ||
657 | 1E0A; C; 1E0B; # LATIN CAPITAL LETTER D WITH DOT ABOVE | ||
658 | 1E0C; C; 1E0D; # LATIN CAPITAL LETTER D WITH DOT BELOW | ||
659 | 1E0E; C; 1E0F; # LATIN CAPITAL LETTER D WITH LINE BELOW | ||
660 | 1E10; C; 1E11; # LATIN CAPITAL LETTER D WITH CEDILLA | ||
661 | 1E12; C; 1E13; # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW | ||
662 | 1E14; C; 1E15; # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE | ||
663 | 1E16; C; 1E17; # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE | ||
664 | 1E18; C; 1E19; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW | ||
665 | 1E1A; C; 1E1B; # LATIN CAPITAL LETTER E WITH TILDE BELOW | ||
666 | 1E1C; C; 1E1D; # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE | ||
667 | 1E1E; C; 1E1F; # LATIN CAPITAL LETTER F WITH DOT ABOVE | ||
668 | 1E20; C; 1E21; # LATIN CAPITAL LETTER G WITH MACRON | ||
669 | 1E22; C; 1E23; # LATIN CAPITAL LETTER H WITH DOT ABOVE | ||
670 | 1E24; C; 1E25; # LATIN CAPITAL LETTER H WITH DOT BELOW | ||
671 | 1E26; C; 1E27; # LATIN CAPITAL LETTER H WITH DIAERESIS | ||
672 | 1E28; C; 1E29; # LATIN CAPITAL LETTER H WITH CEDILLA | ||
673 | 1E2A; C; 1E2B; # LATIN CAPITAL LETTER H WITH BREVE BELOW | ||
674 | 1E2C; C; 1E2D; # LATIN CAPITAL LETTER I WITH TILDE BELOW | ||
675 | 1E2E; C; 1E2F; # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE | ||
676 | 1E30; C; 1E31; # LATIN CAPITAL LETTER K WITH ACUTE | ||
677 | 1E32; C; 1E33; # LATIN CAPITAL LETTER K WITH DOT BELOW | ||
678 | 1E34; C; 1E35; # LATIN CAPITAL LETTER K WITH LINE BELOW | ||
679 | 1E36; C; 1E37; # LATIN CAPITAL LETTER L WITH DOT BELOW | ||
680 | 1E38; C; 1E39; # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON | ||
681 | 1E3A; C; 1E3B; # LATIN CAPITAL LETTER L WITH LINE BELOW | ||
682 | 1E3C; C; 1E3D; # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW | ||
683 | 1E3E; C; 1E3F; # LATIN CAPITAL LETTER M WITH ACUTE | ||
684 | 1E40; C; 1E41; # LATIN CAPITAL LETTER M WITH DOT ABOVE | ||
685 | 1E42; C; 1E43; # LATIN CAPITAL LETTER M WITH DOT BELOW | ||
686 | 1E44; C; 1E45; # LATIN CAPITAL LETTER N WITH DOT ABOVE | ||
687 | 1E46; C; 1E47; # LATIN CAPITAL LETTER N WITH DOT BELOW | ||
688 | 1E48; C; 1E49; # LATIN CAPITAL LETTER N WITH LINE BELOW | ||
689 | 1E4A; C; 1E4B; # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW | ||
690 | 1E4C; C; 1E4D; # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE | ||
691 | 1E4E; C; 1E4F; # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS | ||
692 | 1E50; C; 1E51; # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE | ||
693 | 1E52; C; 1E53; # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE | ||
694 | 1E54; C; 1E55; # LATIN CAPITAL LETTER P WITH ACUTE | ||
695 | 1E56; C; 1E57; # LATIN CAPITAL LETTER P WITH DOT ABOVE | ||
696 | 1E58; C; 1E59; # LATIN CAPITAL LETTER R WITH DOT ABOVE | ||
697 | 1E5A; C; 1E5B; # LATIN CAPITAL LETTER R WITH DOT BELOW | ||
698 | 1E5C; C; 1E5D; # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON | ||
699 | 1E5E; C; 1E5F; # LATIN CAPITAL LETTER R WITH LINE BELOW | ||
700 | 1E60; C; 1E61; # LATIN CAPITAL LETTER S WITH DOT ABOVE | ||
701 | 1E62; C; 1E63; # LATIN CAPITAL LETTER S WITH DOT BELOW | ||
702 | 1E64; C; 1E65; # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE | ||
703 | 1E66; C; 1E67; # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE | ||
704 | 1E68; C; 1E69; # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE | ||
705 | 1E6A; C; 1E6B; # LATIN CAPITAL LETTER T WITH DOT ABOVE | ||
706 | 1E6C; C; 1E6D; # LATIN CAPITAL LETTER T WITH DOT BELOW | ||
707 | 1E6E; C; 1E6F; # LATIN CAPITAL LETTER T WITH LINE BELOW | ||
708 | 1E70; C; 1E71; # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW | ||
709 | 1E72; C; 1E73; # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW | ||
710 | 1E74; C; 1E75; # LATIN CAPITAL LETTER U WITH TILDE BELOW | ||
711 | 1E76; C; 1E77; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW | ||
712 | 1E78; C; 1E79; # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE | ||
713 | 1E7A; C; 1E7B; # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS | ||
714 | 1E7C; C; 1E7D; # LATIN CAPITAL LETTER V WITH TILDE | ||
715 | 1E7E; C; 1E7F; # LATIN CAPITAL LETTER V WITH DOT BELOW | ||
716 | 1E80; C; 1E81; # LATIN CAPITAL LETTER W WITH GRAVE | ||
717 | 1E82; C; 1E83; # LATIN CAPITAL LETTER W WITH ACUTE | ||
718 | 1E84; C; 1E85; # LATIN CAPITAL LETTER W WITH DIAERESIS | ||
719 | 1E86; C; 1E87; # LATIN CAPITAL LETTER W WITH DOT ABOVE | ||
720 | 1E88; C; 1E89; # LATIN CAPITAL LETTER W WITH DOT BELOW | ||
721 | 1E8A; C; 1E8B; # LATIN CAPITAL LETTER X WITH DOT ABOVE | ||
722 | 1E8C; C; 1E8D; # LATIN CAPITAL LETTER X WITH DIAERESIS | ||
723 | 1E8E; C; 1E8F; # LATIN CAPITAL LETTER Y WITH DOT ABOVE | ||
724 | 1E90; C; 1E91; # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX | ||
725 | 1E92; C; 1E93; # LATIN CAPITAL LETTER Z WITH DOT BELOW | ||
726 | 1E94; C; 1E95; # LATIN CAPITAL LETTER Z WITH LINE BELOW | ||
727 | 1E96; F; 0068 0331; # LATIN SMALL LETTER H WITH LINE BELOW | ||
728 | 1E97; F; 0074 0308; # LATIN SMALL LETTER T WITH DIAERESIS | ||
729 | 1E98; F; 0077 030A; # LATIN SMALL LETTER W WITH RING ABOVE | ||
730 | 1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE | ||
731 | 1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING | ||
732 | 1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE | ||
733 | 1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S | ||
734 | 1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S | ||
735 | 1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW | ||
736 | 1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE | ||
737 | 1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE | ||
738 | 1EA6; C; 1EA7; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE | ||
739 | 1EA8; C; 1EA9; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE | ||
740 | 1EAA; C; 1EAB; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE | ||
741 | 1EAC; C; 1EAD; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW | ||
742 | 1EAE; C; 1EAF; # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE | ||
743 | 1EB0; C; 1EB1; # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE | ||
744 | 1EB2; C; 1EB3; # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE | ||
745 | 1EB4; C; 1EB5; # LATIN CAPITAL LETTER A WITH BREVE AND TILDE | ||
746 | 1EB6; C; 1EB7; # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW | ||
747 | 1EB8; C; 1EB9; # LATIN CAPITAL LETTER E WITH DOT BELOW | ||
748 | 1EBA; C; 1EBB; # LATIN CAPITAL LETTER E WITH HOOK ABOVE | ||
749 | 1EBC; C; 1EBD; # LATIN CAPITAL LETTER E WITH TILDE | ||
750 | 1EBE; C; 1EBF; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE | ||
751 | 1EC0; C; 1EC1; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE | ||
752 | 1EC2; C; 1EC3; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE | ||
753 | 1EC4; C; 1EC5; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE | ||
754 | 1EC6; C; 1EC7; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW | ||
755 | 1EC8; C; 1EC9; # LATIN CAPITAL LETTER I WITH HOOK ABOVE | ||
756 | 1ECA; C; 1ECB; # LATIN CAPITAL LETTER I WITH DOT BELOW | ||
757 | 1ECC; C; 1ECD; # LATIN CAPITAL LETTER O WITH DOT BELOW | ||
758 | 1ECE; C; 1ECF; # LATIN CAPITAL LETTER O WITH HOOK ABOVE | ||
759 | 1ED0; C; 1ED1; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE | ||
760 | 1ED2; C; 1ED3; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE | ||
761 | 1ED4; C; 1ED5; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE | ||
762 | 1ED6; C; 1ED7; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE | ||
763 | 1ED8; C; 1ED9; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW | ||
764 | 1EDA; C; 1EDB; # LATIN CAPITAL LETTER O WITH HORN AND ACUTE | ||
765 | 1EDC; C; 1EDD; # LATIN CAPITAL LETTER O WITH HORN AND GRAVE | ||
766 | 1EDE; C; 1EDF; # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE | ||
767 | 1EE0; C; 1EE1; # LATIN CAPITAL LETTER O WITH HORN AND TILDE | ||
768 | 1EE2; C; 1EE3; # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW | ||
769 | 1EE4; C; 1EE5; # LATIN CAPITAL LETTER U WITH DOT BELOW | ||
770 | 1EE6; C; 1EE7; # LATIN CAPITAL LETTER U WITH HOOK ABOVE | ||
771 | 1EE8; C; 1EE9; # LATIN CAPITAL LETTER U WITH HORN AND ACUTE | ||
772 | 1EEA; C; 1EEB; # LATIN CAPITAL LETTER U WITH HORN AND GRAVE | ||
773 | 1EEC; C; 1EED; # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE | ||
774 | 1EEE; C; 1EEF; # LATIN CAPITAL LETTER U WITH HORN AND TILDE | ||
775 | 1EF0; C; 1EF1; # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW | ||
776 | 1EF2; C; 1EF3; # LATIN CAPITAL LETTER Y WITH GRAVE | ||
777 | 1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW | ||
778 | 1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE | ||
779 | 1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE | ||
780 | 1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL | ||
781 | 1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V | ||
782 | 1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP | ||
783 | 1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI | ||
784 | 1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA | ||
785 | 1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA | ||
786 | 1F0B; C; 1F03; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA | ||
787 | 1F0C; C; 1F04; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA | ||
788 | 1F0D; C; 1F05; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA | ||
789 | 1F0E; C; 1F06; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI | ||
790 | 1F0F; C; 1F07; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI | ||
791 | 1F18; C; 1F10; # GREEK CAPITAL LETTER EPSILON WITH PSILI | ||
792 | 1F19; C; 1F11; # GREEK CAPITAL LETTER EPSILON WITH DASIA | ||
793 | 1F1A; C; 1F12; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA | ||
794 | 1F1B; C; 1F13; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA | ||
795 | 1F1C; C; 1F14; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA | ||
796 | 1F1D; C; 1F15; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA | ||
797 | 1F28; C; 1F20; # GREEK CAPITAL LETTER ETA WITH PSILI | ||
798 | 1F29; C; 1F21; # GREEK CAPITAL LETTER ETA WITH DASIA | ||
799 | 1F2A; C; 1F22; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA | ||
800 | 1F2B; C; 1F23; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA | ||
801 | 1F2C; C; 1F24; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA | ||
802 | 1F2D; C; 1F25; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA | ||
803 | 1F2E; C; 1F26; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI | ||
804 | 1F2F; C; 1F27; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI | ||
805 | 1F38; C; 1F30; # GREEK CAPITAL LETTER IOTA WITH PSILI | ||
806 | 1F39; C; 1F31; # GREEK CAPITAL LETTER IOTA WITH DASIA | ||
807 | 1F3A; C; 1F32; # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA | ||
808 | 1F3B; C; 1F33; # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA | ||
809 | 1F3C; C; 1F34; # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA | ||
810 | 1F3D; C; 1F35; # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA | ||
811 | 1F3E; C; 1F36; # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI | ||
812 | 1F3F; C; 1F37; # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI | ||
813 | 1F48; C; 1F40; # GREEK CAPITAL LETTER OMICRON WITH PSILI | ||
814 | 1F49; C; 1F41; # GREEK CAPITAL LETTER OMICRON WITH DASIA | ||
815 | 1F4A; C; 1F42; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA | ||
816 | 1F4B; C; 1F43; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA | ||
817 | 1F4C; C; 1F44; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA | ||
818 | 1F4D; C; 1F45; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA | ||
819 | 1F50; F; 03C5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI | ||
820 | 1F52; F; 03C5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA | ||
821 | 1F54; F; 03C5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA | ||
822 | 1F56; F; 03C5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI | ||
823 | 1F59; C; 1F51; # GREEK CAPITAL LETTER UPSILON WITH DASIA | ||
824 | 1F5B; C; 1F53; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA | ||
825 | 1F5D; C; 1F55; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA | ||
826 | 1F5F; C; 1F57; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI | ||
827 | 1F68; C; 1F60; # GREEK CAPITAL LETTER OMEGA WITH PSILI | ||
828 | 1F69; C; 1F61; # GREEK CAPITAL LETTER OMEGA WITH DASIA | ||
829 | 1F6A; C; 1F62; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA | ||
830 | 1F6B; C; 1F63; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA | ||
831 | 1F6C; C; 1F64; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA | ||
832 | 1F6D; C; 1F65; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA | ||
833 | 1F6E; C; 1F66; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI | ||
834 | 1F6F; C; 1F67; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI | ||
835 | 1F80; F; 1F00 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI | ||
836 | 1F81; F; 1F01 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI | ||
837 | 1F82; F; 1F02 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI | ||
838 | 1F83; F; 1F03 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI | ||
839 | 1F84; F; 1F04 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI | ||
840 | 1F85; F; 1F05 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI | ||
841 | 1F86; F; 1F06 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI | ||
842 | 1F87; F; 1F07 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI | ||
843 | 1F88; F; 1F00 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI | ||
844 | 1F88; S; 1F80; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI | ||
845 | 1F89; F; 1F01 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI | ||
846 | 1F89; S; 1F81; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI | ||
847 | 1F8A; F; 1F02 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
848 | 1F8A; S; 1F82; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
849 | 1F8B; F; 1F03 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
850 | 1F8B; S; 1F83; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
851 | 1F8C; F; 1F04 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
852 | 1F8C; S; 1F84; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
853 | 1F8D; F; 1F05 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
854 | 1F8D; S; 1F85; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
855 | 1F8E; F; 1F06 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
856 | 1F8E; S; 1F86; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
857 | 1F8F; F; 1F07 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
858 | 1F8F; S; 1F87; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
859 | 1F90; F; 1F20 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI | ||
860 | 1F91; F; 1F21 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI | ||
861 | 1F92; F; 1F22 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI | ||
862 | 1F93; F; 1F23 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI | ||
863 | 1F94; F; 1F24 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI | ||
864 | 1F95; F; 1F25 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI | ||
865 | 1F96; F; 1F26 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI | ||
866 | 1F97; F; 1F27 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI | ||
867 | 1F98; F; 1F20 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI | ||
868 | 1F98; S; 1F90; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI | ||
869 | 1F99; F; 1F21 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI | ||
870 | 1F99; S; 1F91; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI | ||
871 | 1F9A; F; 1F22 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
872 | 1F9A; S; 1F92; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
873 | 1F9B; F; 1F23 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
874 | 1F9B; S; 1F93; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
875 | 1F9C; F; 1F24 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
876 | 1F9C; S; 1F94; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
877 | 1F9D; F; 1F25 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
878 | 1F9D; S; 1F95; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
879 | 1F9E; F; 1F26 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
880 | 1F9E; S; 1F96; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
881 | 1F9F; F; 1F27 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
882 | 1F9F; S; 1F97; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
883 | 1FA0; F; 1F60 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI | ||
884 | 1FA1; F; 1F61 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI | ||
885 | 1FA2; F; 1F62 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI | ||
886 | 1FA3; F; 1F63 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI | ||
887 | 1FA4; F; 1F64 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI | ||
888 | 1FA5; F; 1F65 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI | ||
889 | 1FA6; F; 1F66 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI | ||
890 | 1FA7; F; 1F67 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI | ||
891 | 1FA8; F; 1F60 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI | ||
892 | 1FA8; S; 1FA0; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI | ||
893 | 1FA9; F; 1F61 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI | ||
894 | 1FA9; S; 1FA1; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI | ||
895 | 1FAA; F; 1F62 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
896 | 1FAA; S; 1FA2; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI | ||
897 | 1FAB; F; 1F63 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
898 | 1FAB; S; 1FA3; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI | ||
899 | 1FAC; F; 1F64 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
900 | 1FAC; S; 1FA4; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI | ||
901 | 1FAD; F; 1F65 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
902 | 1FAD; S; 1FA5; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI | ||
903 | 1FAE; F; 1F66 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
904 | 1FAE; S; 1FA6; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI | ||
905 | 1FAF; F; 1F67 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
906 | 1FAF; S; 1FA7; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI | ||
907 | 1FB2; F; 1F70 03B9; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI | ||
908 | 1FB3; F; 03B1 03B9; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI | ||
909 | 1FB4; F; 03AC 03B9; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI | ||
910 | 1FB6; F; 03B1 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI | ||
911 | 1FB7; F; 03B1 0342 03B9; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI | ||
912 | 1FB8; C; 1FB0; # GREEK CAPITAL LETTER ALPHA WITH VRACHY | ||
913 | 1FB9; C; 1FB1; # GREEK CAPITAL LETTER ALPHA WITH MACRON | ||
914 | 1FBA; C; 1F70; # GREEK CAPITAL LETTER ALPHA WITH VARIA | ||
915 | 1FBB; C; 1F71; # GREEK CAPITAL LETTER ALPHA WITH OXIA | ||
916 | 1FBC; F; 03B1 03B9; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI | ||
917 | 1FBC; S; 1FB3; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI | ||
918 | 1FBE; C; 03B9; # GREEK PROSGEGRAMMENI | ||
919 | 1FC2; F; 1F74 03B9; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI | ||
920 | 1FC3; F; 03B7 03B9; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI | ||
921 | 1FC4; F; 03AE 03B9; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI | ||
922 | 1FC6; F; 03B7 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI | ||
923 | 1FC7; F; 03B7 0342 03B9; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI | ||
924 | 1FC8; C; 1F72; # GREEK CAPITAL LETTER EPSILON WITH VARIA | ||
925 | 1FC9; C; 1F73; # GREEK CAPITAL LETTER EPSILON WITH OXIA | ||
926 | 1FCA; C; 1F74; # GREEK CAPITAL LETTER ETA WITH VARIA | ||
927 | 1FCB; C; 1F75; # GREEK CAPITAL LETTER ETA WITH OXIA | ||
928 | 1FCC; F; 03B7 03B9; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI | ||
929 | 1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI | ||
930 | 1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA | ||
931 | 1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA | ||
932 | 1FD3; S; 0390; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA | ||
933 | 1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI | ||
934 | 1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI | ||
935 | 1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY | ||
936 | 1FD9; C; 1FD1; # GREEK CAPITAL LETTER IOTA WITH MACRON | ||
937 | 1FDA; C; 1F76; # GREEK CAPITAL LETTER IOTA WITH VARIA | ||
938 | 1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA | ||
939 | 1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA | ||
940 | 1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA | ||
941 | 1FE3; S; 03B0; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA | ||
942 | 1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI | ||
943 | 1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI | ||
944 | 1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI | ||
945 | 1FE8; C; 1FE0; # GREEK CAPITAL LETTER UPSILON WITH VRACHY | ||
946 | 1FE9; C; 1FE1; # GREEK CAPITAL LETTER UPSILON WITH MACRON | ||
947 | 1FEA; C; 1F7A; # GREEK CAPITAL LETTER UPSILON WITH VARIA | ||
948 | 1FEB; C; 1F7B; # GREEK CAPITAL LETTER UPSILON WITH OXIA | ||
949 | 1FEC; C; 1FE5; # GREEK CAPITAL LETTER RHO WITH DASIA | ||
950 | 1FF2; F; 1F7C 03B9; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI | ||
951 | 1FF3; F; 03C9 03B9; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI | ||
952 | 1FF4; F; 03CE 03B9; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI | ||
953 | 1FF6; F; 03C9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI | ||
954 | 1FF7; F; 03C9 0342 03B9; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI | ||
955 | 1FF8; C; 1F78; # GREEK CAPITAL LETTER OMICRON WITH VARIA | ||
956 | 1FF9; C; 1F79; # GREEK CAPITAL LETTER OMICRON WITH OXIA | ||
957 | 1FFA; C; 1F7C; # GREEK CAPITAL LETTER OMEGA WITH VARIA | ||
958 | 1FFB; C; 1F7D; # GREEK CAPITAL LETTER OMEGA WITH OXIA | ||
959 | 1FFC; F; 03C9 03B9; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI | ||
960 | 1FFC; S; 1FF3; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI | ||
961 | 2126; C; 03C9; # OHM SIGN | ||
962 | 212A; C; 006B; # KELVIN SIGN | ||
963 | 212B; C; 00E5; # ANGSTROM SIGN | ||
964 | 2132; C; 214E; # TURNED CAPITAL F | ||
965 | 2160; C; 2170; # ROMAN NUMERAL ONE | ||
966 | 2161; C; 2171; # ROMAN NUMERAL TWO | ||
967 | 2162; C; 2172; # ROMAN NUMERAL THREE | ||
968 | 2163; C; 2173; # ROMAN NUMERAL FOUR | ||
969 | 2164; C; 2174; # ROMAN NUMERAL FIVE | ||
970 | 2165; C; 2175; # ROMAN NUMERAL SIX | ||
971 | 2166; C; 2176; # ROMAN NUMERAL SEVEN | ||
972 | 2167; C; 2177; # ROMAN NUMERAL EIGHT | ||
973 | 2168; C; 2178; # ROMAN NUMERAL NINE | ||
974 | 2169; C; 2179; # ROMAN NUMERAL TEN | ||
975 | 216A; C; 217A; # ROMAN NUMERAL ELEVEN | ||
976 | 216B; C; 217B; # ROMAN NUMERAL TWELVE | ||
977 | 216C; C; 217C; # ROMAN NUMERAL FIFTY | ||
978 | 216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED | ||
979 | 216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED | ||
980 | 216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND | ||
981 | 2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED | ||
982 | 24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A | ||
983 | 24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B | ||
984 | 24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C | ||
985 | 24B9; C; 24D3; # CIRCLED LATIN CAPITAL LETTER D | ||
986 | 24BA; C; 24D4; # CIRCLED LATIN CAPITAL LETTER E | ||
987 | 24BB; C; 24D5; # CIRCLED LATIN CAPITAL LETTER F | ||
988 | 24BC; C; 24D6; # CIRCLED LATIN CAPITAL LETTER G | ||
989 | 24BD; C; 24D7; # CIRCLED LATIN CAPITAL LETTER H | ||
990 | 24BE; C; 24D8; # CIRCLED LATIN CAPITAL LETTER I | ||
991 | 24BF; C; 24D9; # CIRCLED LATIN CAPITAL LETTER J | ||
992 | 24C0; C; 24DA; # CIRCLED LATIN CAPITAL LETTER K | ||
993 | 24C1; C; 24DB; # CIRCLED LATIN CAPITAL LETTER L | ||
994 | 24C2; C; 24DC; # CIRCLED LATIN CAPITAL LETTER M | ||
995 | 24C3; C; 24DD; # CIRCLED LATIN CAPITAL LETTER N | ||
996 | 24C4; C; 24DE; # CIRCLED LATIN CAPITAL LETTER O | ||
997 | 24C5; C; 24DF; # CIRCLED LATIN CAPITAL LETTER P | ||
998 | 24C6; C; 24E0; # CIRCLED LATIN CAPITAL LETTER Q | ||
999 | 24C7; C; 24E1; # CIRCLED LATIN CAPITAL LETTER R | ||
1000 | 24C8; C; 24E2; # CIRCLED LATIN CAPITAL LETTER S | ||
1001 | 24C9; C; 24E3; # CIRCLED LATIN CAPITAL LETTER T | ||
1002 | 24CA; C; 24E4; # CIRCLED LATIN CAPITAL LETTER U | ||
1003 | 24CB; C; 24E5; # CIRCLED LATIN CAPITAL LETTER V | ||
1004 | 24CC; C; 24E6; # CIRCLED LATIN CAPITAL LETTER W | ||
1005 | 24CD; C; 24E7; # CIRCLED LATIN CAPITAL LETTER X | ||
1006 | 24CE; C; 24E8; # CIRCLED LATIN CAPITAL LETTER Y | ||
1007 | 24CF; C; 24E9; # CIRCLED LATIN CAPITAL LETTER Z | ||
1008 | 2C00; C; 2C30; # GLAGOLITIC CAPITAL LETTER AZU | ||
1009 | 2C01; C; 2C31; # GLAGOLITIC CAPITAL LETTER BUKY | ||
1010 | 2C02; C; 2C32; # GLAGOLITIC CAPITAL LETTER VEDE | ||
1011 | 2C03; C; 2C33; # GLAGOLITIC CAPITAL LETTER GLAGOLI | ||
1012 | 2C04; C; 2C34; # GLAGOLITIC CAPITAL LETTER DOBRO | ||
1013 | 2C05; C; 2C35; # GLAGOLITIC CAPITAL LETTER YESTU | ||
1014 | 2C06; C; 2C36; # GLAGOLITIC CAPITAL LETTER ZHIVETE | ||
1015 | 2C07; C; 2C37; # GLAGOLITIC CAPITAL LETTER DZELO | ||
1016 | 2C08; C; 2C38; # GLAGOLITIC CAPITAL LETTER ZEMLJA | ||
1017 | 2C09; C; 2C39; # GLAGOLITIC CAPITAL LETTER IZHE | ||
1018 | 2C0A; C; 2C3A; # GLAGOLITIC CAPITAL LETTER INITIAL IZHE | ||
1019 | 2C0B; C; 2C3B; # GLAGOLITIC CAPITAL LETTER I | ||
1020 | 2C0C; C; 2C3C; # GLAGOLITIC CAPITAL LETTER DJERVI | ||
1021 | 2C0D; C; 2C3D; # GLAGOLITIC CAPITAL LETTER KAKO | ||
1022 | 2C0E; C; 2C3E; # GLAGOLITIC CAPITAL LETTER LJUDIJE | ||
1023 | 2C0F; C; 2C3F; # GLAGOLITIC CAPITAL LETTER MYSLITE | ||
1024 | 2C10; C; 2C40; # GLAGOLITIC CAPITAL LETTER NASHI | ||
1025 | 2C11; C; 2C41; # GLAGOLITIC CAPITAL LETTER ONU | ||
1026 | 2C12; C; 2C42; # GLAGOLITIC CAPITAL LETTER POKOJI | ||
1027 | 2C13; C; 2C43; # GLAGOLITIC CAPITAL LETTER RITSI | ||
1028 | 2C14; C; 2C44; # GLAGOLITIC CAPITAL LETTER SLOVO | ||
1029 | 2C15; C; 2C45; # GLAGOLITIC CAPITAL LETTER TVRIDO | ||
1030 | 2C16; C; 2C46; # GLAGOLITIC CAPITAL LETTER UKU | ||
1031 | 2C17; C; 2C47; # GLAGOLITIC CAPITAL LETTER FRITU | ||
1032 | 2C18; C; 2C48; # GLAGOLITIC CAPITAL LETTER HERU | ||
1033 | 2C19; C; 2C49; # GLAGOLITIC CAPITAL LETTER OTU | ||
1034 | 2C1A; C; 2C4A; # GLAGOLITIC CAPITAL LETTER PE | ||
1035 | 2C1B; C; 2C4B; # GLAGOLITIC CAPITAL LETTER SHTA | ||
1036 | 2C1C; C; 2C4C; # GLAGOLITIC CAPITAL LETTER TSI | ||
1037 | 2C1D; C; 2C4D; # GLAGOLITIC CAPITAL LETTER CHRIVI | ||
1038 | 2C1E; C; 2C4E; # GLAGOLITIC CAPITAL LETTER SHA | ||
1039 | 2C1F; C; 2C4F; # GLAGOLITIC CAPITAL LETTER YERU | ||
1040 | 2C20; C; 2C50; # GLAGOLITIC CAPITAL LETTER YERI | ||
1041 | 2C21; C; 2C51; # GLAGOLITIC CAPITAL LETTER YATI | ||
1042 | 2C22; C; 2C52; # GLAGOLITIC CAPITAL LETTER SPIDERY HA | ||
1043 | 2C23; C; 2C53; # GLAGOLITIC CAPITAL LETTER YU | ||
1044 | 2C24; C; 2C54; # GLAGOLITIC CAPITAL LETTER SMALL YUS | ||
1045 | 2C25; C; 2C55; # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL | ||
1046 | 2C26; C; 2C56; # GLAGOLITIC CAPITAL LETTER YO | ||
1047 | 2C27; C; 2C57; # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS | ||
1048 | 2C28; C; 2C58; # GLAGOLITIC CAPITAL LETTER BIG YUS | ||
1049 | 2C29; C; 2C59; # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS | ||
1050 | 2C2A; C; 2C5A; # GLAGOLITIC CAPITAL LETTER FITA | ||
1051 | 2C2B; C; 2C5B; # GLAGOLITIC CAPITAL LETTER IZHITSA | ||
1052 | 2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC | ||
1053 | 2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A | ||
1054 | 2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE | ||
1055 | 2C2F; C; 2C5F; # GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI | ||
1056 | 2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR | ||
1057 | 2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE | ||
1058 | 2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE | ||
1059 | 2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL | ||
1060 | 2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER | ||
1061 | 2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER | ||
1062 | 2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER | ||
1063 | 2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA | ||
1064 | 2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK | ||
1065 | 2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A | ||
1066 | 2C70; C; 0252; # LATIN CAPITAL LETTER TURNED ALPHA | ||
1067 | 2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK | ||
1068 | 2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H | ||
1069 | 2C7E; C; 023F; # LATIN CAPITAL LETTER S WITH SWASH TAIL | ||
1070 | 2C7F; C; 0240; # LATIN CAPITAL LETTER Z WITH SWASH TAIL | ||
1071 | 2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA | ||
1072 | 2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA | ||
1073 | 2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA | ||
1074 | 2C86; C; 2C87; # COPTIC CAPITAL LETTER DALDA | ||
1075 | 2C88; C; 2C89; # COPTIC CAPITAL LETTER EIE | ||
1076 | 2C8A; C; 2C8B; # COPTIC CAPITAL LETTER SOU | ||
1077 | 2C8C; C; 2C8D; # COPTIC CAPITAL LETTER ZATA | ||
1078 | 2C8E; C; 2C8F; # COPTIC CAPITAL LETTER HATE | ||
1079 | 2C90; C; 2C91; # COPTIC CAPITAL LETTER THETHE | ||
1080 | 2C92; C; 2C93; # COPTIC CAPITAL LETTER IAUDA | ||
1081 | 2C94; C; 2C95; # COPTIC CAPITAL LETTER KAPA | ||
1082 | 2C96; C; 2C97; # COPTIC CAPITAL LETTER LAULA | ||
1083 | 2C98; C; 2C99; # COPTIC CAPITAL LETTER MI | ||
1084 | 2C9A; C; 2C9B; # COPTIC CAPITAL LETTER NI | ||
1085 | 2C9C; C; 2C9D; # COPTIC CAPITAL LETTER KSI | ||
1086 | 2C9E; C; 2C9F; # COPTIC CAPITAL LETTER O | ||
1087 | 2CA0; C; 2CA1; # COPTIC CAPITAL LETTER PI | ||
1088 | 2CA2; C; 2CA3; # COPTIC CAPITAL LETTER RO | ||
1089 | 2CA4; C; 2CA5; # COPTIC CAPITAL LETTER SIMA | ||
1090 | 2CA6; C; 2CA7; # COPTIC CAPITAL LETTER TAU | ||
1091 | 2CA8; C; 2CA9; # COPTIC CAPITAL LETTER UA | ||
1092 | 2CAA; C; 2CAB; # COPTIC CAPITAL LETTER FI | ||
1093 | 2CAC; C; 2CAD; # COPTIC CAPITAL LETTER KHI | ||
1094 | 2CAE; C; 2CAF; # COPTIC CAPITAL LETTER PSI | ||
1095 | 2CB0; C; 2CB1; # COPTIC CAPITAL LETTER OOU | ||
1096 | 2CB2; C; 2CB3; # COPTIC CAPITAL LETTER DIALECT-P ALEF | ||
1097 | 2CB4; C; 2CB5; # COPTIC CAPITAL LETTER OLD COPTIC AIN | ||
1098 | 2CB6; C; 2CB7; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE | ||
1099 | 2CB8; C; 2CB9; # COPTIC CAPITAL LETTER DIALECT-P KAPA | ||
1100 | 2CBA; C; 2CBB; # COPTIC CAPITAL LETTER DIALECT-P NI | ||
1101 | 2CBC; C; 2CBD; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI | ||
1102 | 2CBE; C; 2CBF; # COPTIC CAPITAL LETTER OLD COPTIC OOU | ||
1103 | 2CC0; C; 2CC1; # COPTIC CAPITAL LETTER SAMPI | ||
1104 | 2CC2; C; 2CC3; # COPTIC CAPITAL LETTER CROSSED SHEI | ||
1105 | 2CC4; C; 2CC5; # COPTIC CAPITAL LETTER OLD COPTIC SHEI | ||
1106 | 2CC6; C; 2CC7; # COPTIC CAPITAL LETTER OLD COPTIC ESH | ||
1107 | 2CC8; C; 2CC9; # COPTIC CAPITAL LETTER AKHMIMIC KHEI | ||
1108 | 2CCA; C; 2CCB; # COPTIC CAPITAL LETTER DIALECT-P HORI | ||
1109 | 2CCC; C; 2CCD; # COPTIC CAPITAL LETTER OLD COPTIC HORI | ||
1110 | 2CCE; C; 2CCF; # COPTIC CAPITAL LETTER OLD COPTIC HA | ||
1111 | 2CD0; C; 2CD1; # COPTIC CAPITAL LETTER L-SHAPED HA | ||
1112 | 2CD2; C; 2CD3; # COPTIC CAPITAL LETTER OLD COPTIC HEI | ||
1113 | 2CD4; C; 2CD5; # COPTIC CAPITAL LETTER OLD COPTIC HAT | ||
1114 | 2CD6; C; 2CD7; # COPTIC CAPITAL LETTER OLD COPTIC GANGIA | ||
1115 | 2CD8; C; 2CD9; # COPTIC CAPITAL LETTER OLD COPTIC DJA | ||
1116 | 2CDA; C; 2CDB; # COPTIC CAPITAL LETTER OLD COPTIC SHIMA | ||
1117 | 2CDC; C; 2CDD; # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA | ||
1118 | 2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI | ||
1119 | 2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI | ||
1120 | 2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU | ||
1121 | 2CEB; C; 2CEC; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI | ||
1122 | 2CED; C; 2CEE; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA | ||
1123 | 2CF2; C; 2CF3; # COPTIC CAPITAL LETTER BOHAIRIC KHEI | ||
1124 | A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA | ||
1125 | A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO | ||
1126 | A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE | ||
1127 | A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA | ||
1128 | A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV | ||
1129 | A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK | ||
1130 | A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA | ||
1131 | A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER | ||
1132 | A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER | ||
1133 | A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT | ||
1134 | A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU | ||
1135 | A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A | ||
1136 | A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS | ||
1137 | A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS | ||
1138 | A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS | ||
1139 | A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN | ||
1140 | A660; C; A661; # CYRILLIC CAPITAL LETTER REVERSED TSE | ||
1141 | A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE | ||
1142 | A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL | ||
1143 | A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM | ||
1144 | A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O | ||
1145 | A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O | ||
1146 | A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O | ||
1147 | A680; C; A681; # CYRILLIC CAPITAL LETTER DWE | ||
1148 | A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE | ||
1149 | A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE | ||
1150 | A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE | ||
1151 | A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE | ||
1152 | A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK | ||
1153 | A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE | ||
1154 | A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE | ||
1155 | A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE | ||
1156 | A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE | ||
1157 | A694; C; A695; # CYRILLIC CAPITAL LETTER HWE | ||
1158 | A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE | ||
1159 | A698; C; A699; # CYRILLIC CAPITAL LETTER DOUBLE O | ||
1160 | A69A; C; A69B; # CYRILLIC CAPITAL LETTER CROSSED O | ||
1161 | A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF | ||
1162 | A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN | ||
1163 | A726; C; A727; # LATIN CAPITAL LETTER HENG | ||
1164 | A728; C; A729; # LATIN CAPITAL LETTER TZ | ||
1165 | A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO | ||
1166 | A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO | ||
1167 | A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA | ||
1168 | A732; C; A733; # LATIN CAPITAL LETTER AA | ||
1169 | A734; C; A735; # LATIN CAPITAL LETTER AO | ||
1170 | A736; C; A737; # LATIN CAPITAL LETTER AU | ||
1171 | A738; C; A739; # LATIN CAPITAL LETTER AV | ||
1172 | A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR | ||
1173 | A73C; C; A73D; # LATIN CAPITAL LETTER AY | ||
1174 | A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT | ||
1175 | A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE | ||
1176 | A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE | ||
1177 | A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE | ||
1178 | A746; C; A747; # LATIN CAPITAL LETTER BROKEN L | ||
1179 | A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE | ||
1180 | A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY | ||
1181 | A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP | ||
1182 | A74E; C; A74F; # LATIN CAPITAL LETTER OO | ||
1183 | A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER | ||
1184 | A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH | ||
1185 | A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL | ||
1186 | A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER | ||
1187 | A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE | ||
1188 | A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA | ||
1189 | A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA | ||
1190 | A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE | ||
1191 | A760; C; A761; # LATIN CAPITAL LETTER VY | ||
1192 | A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z | ||
1193 | A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE | ||
1194 | A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER | ||
1195 | A768; C; A769; # LATIN CAPITAL LETTER VEND | ||
1196 | A76A; C; A76B; # LATIN CAPITAL LETTER ET | ||
1197 | A76C; C; A76D; # LATIN CAPITAL LETTER IS | ||
1198 | A76E; C; A76F; # LATIN CAPITAL LETTER CON | ||
1199 | A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D | ||
1200 | A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F | ||
1201 | A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G | ||
1202 | A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G | ||
1203 | A780; C; A781; # LATIN CAPITAL LETTER TURNED L | ||
1204 | A782; C; A783; # LATIN CAPITAL LETTER INSULAR R | ||
1205 | A784; C; A785; # LATIN CAPITAL LETTER INSULAR S | ||
1206 | A786; C; A787; # LATIN CAPITAL LETTER INSULAR T | ||
1207 | A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO | ||
1208 | A78D; C; 0265; # LATIN CAPITAL LETTER TURNED H | ||
1209 | A790; C; A791; # LATIN CAPITAL LETTER N WITH DESCENDER | ||
1210 | A792; C; A793; # LATIN CAPITAL LETTER C WITH BAR | ||
1211 | A796; C; A797; # LATIN CAPITAL LETTER B WITH FLOURISH | ||
1212 | A798; C; A799; # LATIN CAPITAL LETTER F WITH STROKE | ||
1213 | A79A; C; A79B; # LATIN CAPITAL LETTER VOLAPUK AE | ||
1214 | A79C; C; A79D; # LATIN CAPITAL LETTER VOLAPUK OE | ||
1215 | A79E; C; A79F; # LATIN CAPITAL LETTER VOLAPUK UE | ||
1216 | A7A0; C; A7A1; # LATIN CAPITAL LETTER G WITH OBLIQUE STROKE | ||
1217 | A7A2; C; A7A3; # LATIN CAPITAL LETTER K WITH OBLIQUE STROKE | ||
1218 | A7A4; C; A7A5; # LATIN CAPITAL LETTER N WITH OBLIQUE STROKE | ||
1219 | A7A6; C; A7A7; # LATIN CAPITAL LETTER R WITH OBLIQUE STROKE | ||
1220 | A7A8; C; A7A9; # LATIN CAPITAL LETTER S WITH OBLIQUE STROKE | ||
1221 | A7AA; C; 0266; # LATIN CAPITAL LETTER H WITH HOOK | ||
1222 | A7AB; C; 025C; # LATIN CAPITAL LETTER REVERSED OPEN E | ||
1223 | A7AC; C; 0261; # LATIN CAPITAL LETTER SCRIPT G | ||
1224 | A7AD; C; 026C; # LATIN CAPITAL LETTER L WITH BELT | ||
1225 | A7AE; C; 026A; # LATIN CAPITAL LETTER SMALL CAPITAL I | ||
1226 | A7B0; C; 029E; # LATIN CAPITAL LETTER TURNED K | ||
1227 | A7B1; C; 0287; # LATIN CAPITAL LETTER TURNED T | ||
1228 | A7B2; C; 029D; # LATIN CAPITAL LETTER J WITH CROSSED-TAIL | ||
1229 | A7B3; C; AB53; # LATIN CAPITAL LETTER CHI | ||
1230 | A7B4; C; A7B5; # LATIN CAPITAL LETTER BETA | ||
1231 | A7B6; C; A7B7; # LATIN CAPITAL LETTER OMEGA | ||
1232 | A7B8; C; A7B9; # LATIN CAPITAL LETTER U WITH STROKE | ||
1233 | A7BA; C; A7BB; # LATIN CAPITAL LETTER GLOTTAL A | ||
1234 | A7BC; C; A7BD; # LATIN CAPITAL LETTER GLOTTAL I | ||
1235 | A7BE; C; A7BF; # LATIN CAPITAL LETTER GLOTTAL U | ||
1236 | A7C0; C; A7C1; # LATIN CAPITAL LETTER OLD POLISH O | ||
1237 | A7C2; C; A7C3; # LATIN CAPITAL LETTER ANGLICANA W | ||
1238 | A7C4; C; A794; # LATIN CAPITAL LETTER C WITH PALATAL HOOK | ||
1239 | A7C5; C; 0282; # LATIN CAPITAL LETTER S WITH HOOK | ||
1240 | A7C6; C; 1D8E; # LATIN CAPITAL LETTER Z WITH PALATAL HOOK | ||
1241 | A7C7; C; A7C8; # LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY | ||
1242 | A7C9; C; A7CA; # LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY | ||
1243 | A7D0; C; A7D1; # LATIN CAPITAL LETTER CLOSED INSULAR G | ||
1244 | A7D6; C; A7D7; # LATIN CAPITAL LETTER MIDDLE SCOTS S | ||
1245 | A7D8; C; A7D9; # LATIN CAPITAL LETTER SIGMOID S | ||
1246 | A7F5; C; A7F6; # LATIN CAPITAL LETTER REVERSED HALF H | ||
1247 | AB70; C; 13A0; # CHEROKEE SMALL LETTER A | ||
1248 | AB71; C; 13A1; # CHEROKEE SMALL LETTER E | ||
1249 | AB72; C; 13A2; # CHEROKEE SMALL LETTER I | ||
1250 | AB73; C; 13A3; # CHEROKEE SMALL LETTER O | ||
1251 | AB74; C; 13A4; # CHEROKEE SMALL LETTER U | ||
1252 | AB75; C; 13A5; # CHEROKEE SMALL LETTER V | ||
1253 | AB76; C; 13A6; # CHEROKEE SMALL LETTER GA | ||
1254 | AB77; C; 13A7; # CHEROKEE SMALL LETTER KA | ||
1255 | AB78; C; 13A8; # CHEROKEE SMALL LETTER GE | ||
1256 | AB79; C; 13A9; # CHEROKEE SMALL LETTER GI | ||
1257 | AB7A; C; 13AA; # CHEROKEE SMALL LETTER GO | ||
1258 | AB7B; C; 13AB; # CHEROKEE SMALL LETTER GU | ||
1259 | AB7C; C; 13AC; # CHEROKEE SMALL LETTER GV | ||
1260 | AB7D; C; 13AD; # CHEROKEE SMALL LETTER HA | ||
1261 | AB7E; C; 13AE; # CHEROKEE SMALL LETTER HE | ||
1262 | AB7F; C; 13AF; # CHEROKEE SMALL LETTER HI | ||
1263 | AB80; C; 13B0; # CHEROKEE SMALL LETTER HO | ||
1264 | AB81; C; 13B1; # CHEROKEE SMALL LETTER HU | ||
1265 | AB82; C; 13B2; # CHEROKEE SMALL LETTER HV | ||
1266 | AB83; C; 13B3; # CHEROKEE SMALL LETTER LA | ||
1267 | AB84; C; 13B4; # CHEROKEE SMALL LETTER LE | ||
1268 | AB85; C; 13B5; # CHEROKEE SMALL LETTER LI | ||
1269 | AB86; C; 13B6; # CHEROKEE SMALL LETTER LO | ||
1270 | AB87; C; 13B7; # CHEROKEE SMALL LETTER LU | ||
1271 | AB88; C; 13B8; # CHEROKEE SMALL LETTER LV | ||
1272 | AB89; C; 13B9; # CHEROKEE SMALL LETTER MA | ||
1273 | AB8A; C; 13BA; # CHEROKEE SMALL LETTER ME | ||
1274 | AB8B; C; 13BB; # CHEROKEE SMALL LETTER MI | ||
1275 | AB8C; C; 13BC; # CHEROKEE SMALL LETTER MO | ||
1276 | AB8D; C; 13BD; # CHEROKEE SMALL LETTER MU | ||
1277 | AB8E; C; 13BE; # CHEROKEE SMALL LETTER NA | ||
1278 | AB8F; C; 13BF; # CHEROKEE SMALL LETTER HNA | ||
1279 | AB90; C; 13C0; # CHEROKEE SMALL LETTER NAH | ||
1280 | AB91; C; 13C1; # CHEROKEE SMALL LETTER NE | ||
1281 | AB92; C; 13C2; # CHEROKEE SMALL LETTER NI | ||
1282 | AB93; C; 13C3; # CHEROKEE SMALL LETTER NO | ||
1283 | AB94; C; 13C4; # CHEROKEE SMALL LETTER NU | ||
1284 | AB95; C; 13C5; # CHEROKEE SMALL LETTER NV | ||
1285 | AB96; C; 13C6; # CHEROKEE SMALL LETTER QUA | ||
1286 | AB97; C; 13C7; # CHEROKEE SMALL LETTER QUE | ||
1287 | AB98; C; 13C8; # CHEROKEE SMALL LETTER QUI | ||
1288 | AB99; C; 13C9; # CHEROKEE SMALL LETTER QUO | ||
1289 | AB9A; C; 13CA; # CHEROKEE SMALL LETTER QUU | ||
1290 | AB9B; C; 13CB; # CHEROKEE SMALL LETTER QUV | ||
1291 | AB9C; C; 13CC; # CHEROKEE SMALL LETTER SA | ||
1292 | AB9D; C; 13CD; # CHEROKEE SMALL LETTER S | ||
1293 | AB9E; C; 13CE; # CHEROKEE SMALL LETTER SE | ||
1294 | AB9F; C; 13CF; # CHEROKEE SMALL LETTER SI | ||
1295 | ABA0; C; 13D0; # CHEROKEE SMALL LETTER SO | ||
1296 | ABA1; C; 13D1; # CHEROKEE SMALL LETTER SU | ||
1297 | ABA2; C; 13D2; # CHEROKEE SMALL LETTER SV | ||
1298 | ABA3; C; 13D3; # CHEROKEE SMALL LETTER DA | ||
1299 | ABA4; C; 13D4; # CHEROKEE SMALL LETTER TA | ||
1300 | ABA5; C; 13D5; # CHEROKEE SMALL LETTER DE | ||
1301 | ABA6; C; 13D6; # CHEROKEE SMALL LETTER TE | ||
1302 | ABA7; C; 13D7; # CHEROKEE SMALL LETTER DI | ||
1303 | ABA8; C; 13D8; # CHEROKEE SMALL LETTER TI | ||
1304 | ABA9; C; 13D9; # CHEROKEE SMALL LETTER DO | ||
1305 | ABAA; C; 13DA; # CHEROKEE SMALL LETTER DU | ||
1306 | ABAB; C; 13DB; # CHEROKEE SMALL LETTER DV | ||
1307 | ABAC; C; 13DC; # CHEROKEE SMALL LETTER DLA | ||
1308 | ABAD; C; 13DD; # CHEROKEE SMALL LETTER TLA | ||
1309 | ABAE; C; 13DE; # CHEROKEE SMALL LETTER TLE | ||
1310 | ABAF; C; 13DF; # CHEROKEE SMALL LETTER TLI | ||
1311 | ABB0; C; 13E0; # CHEROKEE SMALL LETTER TLO | ||
1312 | ABB1; C; 13E1; # CHEROKEE SMALL LETTER TLU | ||
1313 | ABB2; C; 13E2; # CHEROKEE SMALL LETTER TLV | ||
1314 | ABB3; C; 13E3; # CHEROKEE SMALL LETTER TSA | ||
1315 | ABB4; C; 13E4; # CHEROKEE SMALL LETTER TSE | ||
1316 | ABB5; C; 13E5; # CHEROKEE SMALL LETTER TSI | ||
1317 | ABB6; C; 13E6; # CHEROKEE SMALL LETTER TSO | ||
1318 | ABB7; C; 13E7; # CHEROKEE SMALL LETTER TSU | ||
1319 | ABB8; C; 13E8; # CHEROKEE SMALL LETTER TSV | ||
1320 | ABB9; C; 13E9; # CHEROKEE SMALL LETTER WA | ||
1321 | ABBA; C; 13EA; # CHEROKEE SMALL LETTER WE | ||
1322 | ABBB; C; 13EB; # CHEROKEE SMALL LETTER WI | ||
1323 | ABBC; C; 13EC; # CHEROKEE SMALL LETTER WO | ||
1324 | ABBD; C; 13ED; # CHEROKEE SMALL LETTER WU | ||
1325 | ABBE; C; 13EE; # CHEROKEE SMALL LETTER WV | ||
1326 | ABBF; C; 13EF; # CHEROKEE SMALL LETTER YA | ||
1327 | FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF | ||
1328 | FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI | ||
1329 | FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL | ||
1330 | FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI | ||
1331 | FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL | ||
1332 | FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T | ||
1333 | FB05; S; FB06; # LATIN SMALL LIGATURE LONG S T | ||
1334 | FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST | ||
1335 | FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW | ||
1336 | FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH | ||
1337 | FB15; F; 0574 056B; # ARMENIAN SMALL LIGATURE MEN INI | ||
1338 | FB16; F; 057E 0576; # ARMENIAN SMALL LIGATURE VEW NOW | ||
1339 | FB17; F; 0574 056D; # ARMENIAN SMALL LIGATURE MEN XEH | ||
1340 | FF21; C; FF41; # FULLWIDTH LATIN CAPITAL LETTER A | ||
1341 | FF22; C; FF42; # FULLWIDTH LATIN CAPITAL LETTER B | ||
1342 | FF23; C; FF43; # FULLWIDTH LATIN CAPITAL LETTER C | ||
1343 | FF24; C; FF44; # FULLWIDTH LATIN CAPITAL LETTER D | ||
1344 | FF25; C; FF45; # FULLWIDTH LATIN CAPITAL LETTER E | ||
1345 | FF26; C; FF46; # FULLWIDTH LATIN CAPITAL LETTER F | ||
1346 | FF27; C; FF47; # FULLWIDTH LATIN CAPITAL LETTER G | ||
1347 | FF28; C; FF48; # FULLWIDTH LATIN CAPITAL LETTER H | ||
1348 | FF29; C; FF49; # FULLWIDTH LATIN CAPITAL LETTER I | ||
1349 | FF2A; C; FF4A; # FULLWIDTH LATIN CAPITAL LETTER J | ||
1350 | FF2B; C; FF4B; # FULLWIDTH LATIN CAPITAL LETTER K | ||
1351 | FF2C; C; FF4C; # FULLWIDTH LATIN CAPITAL LETTER L | ||
1352 | FF2D; C; FF4D; # FULLWIDTH LATIN CAPITAL LETTER M | ||
1353 | FF2E; C; FF4E; # FULLWIDTH LATIN CAPITAL LETTER N | ||
1354 | FF2F; C; FF4F; # FULLWIDTH LATIN CAPITAL LETTER O | ||
1355 | FF30; C; FF50; # FULLWIDTH LATIN CAPITAL LETTER P | ||
1356 | FF31; C; FF51; # FULLWIDTH LATIN CAPITAL LETTER Q | ||
1357 | FF32; C; FF52; # FULLWIDTH LATIN CAPITAL LETTER R | ||
1358 | FF33; C; FF53; # FULLWIDTH LATIN CAPITAL LETTER S | ||
1359 | FF34; C; FF54; # FULLWIDTH LATIN CAPITAL LETTER T | ||
1360 | FF35; C; FF55; # FULLWIDTH LATIN CAPITAL LETTER U | ||
1361 | FF36; C; FF56; # FULLWIDTH LATIN CAPITAL LETTER V | ||
1362 | FF37; C; FF57; # FULLWIDTH LATIN CAPITAL LETTER W | ||
1363 | FF38; C; FF58; # FULLWIDTH LATIN CAPITAL LETTER X | ||
1364 | FF39; C; FF59; # FULLWIDTH LATIN CAPITAL LETTER Y | ||
1365 | FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z | ||
1366 | 10400; C; 10428; # DESERET CAPITAL LETTER LONG I | ||
1367 | 10401; C; 10429; # DESERET CAPITAL LETTER LONG E | ||
1368 | 10402; C; 1042A; # DESERET CAPITAL LETTER LONG A | ||
1369 | 10403; C; 1042B; # DESERET CAPITAL LETTER LONG AH | ||
1370 | 10404; C; 1042C; # DESERET CAPITAL LETTER LONG O | ||
1371 | 10405; C; 1042D; # DESERET CAPITAL LETTER LONG OO | ||
1372 | 10406; C; 1042E; # DESERET CAPITAL LETTER SHORT I | ||
1373 | 10407; C; 1042F; # DESERET CAPITAL LETTER SHORT E | ||
1374 | 10408; C; 10430; # DESERET CAPITAL LETTER SHORT A | ||
1375 | 10409; C; 10431; # DESERET CAPITAL LETTER SHORT AH | ||
1376 | 1040A; C; 10432; # DESERET CAPITAL LETTER SHORT O | ||
1377 | 1040B; C; 10433; # DESERET CAPITAL LETTER SHORT OO | ||
1378 | 1040C; C; 10434; # DESERET CAPITAL LETTER AY | ||
1379 | 1040D; C; 10435; # DESERET CAPITAL LETTER OW | ||
1380 | 1040E; C; 10436; # DESERET CAPITAL LETTER WU | ||
1381 | 1040F; C; 10437; # DESERET CAPITAL LETTER YEE | ||
1382 | 10410; C; 10438; # DESERET CAPITAL LETTER H | ||
1383 | 10411; C; 10439; # DESERET CAPITAL LETTER PEE | ||
1384 | 10412; C; 1043A; # DESERET CAPITAL LETTER BEE | ||
1385 | 10413; C; 1043B; # DESERET CAPITAL LETTER TEE | ||
1386 | 10414; C; 1043C; # DESERET CAPITAL LETTER DEE | ||
1387 | 10415; C; 1043D; # DESERET CAPITAL LETTER CHEE | ||
1388 | 10416; C; 1043E; # DESERET CAPITAL LETTER JEE | ||
1389 | 10417; C; 1043F; # DESERET CAPITAL LETTER KAY | ||
1390 | 10418; C; 10440; # DESERET CAPITAL LETTER GAY | ||
1391 | 10419; C; 10441; # DESERET CAPITAL LETTER EF | ||
1392 | 1041A; C; 10442; # DESERET CAPITAL LETTER VEE | ||
1393 | 1041B; C; 10443; # DESERET CAPITAL LETTER ETH | ||
1394 | 1041C; C; 10444; # DESERET CAPITAL LETTER THEE | ||
1395 | 1041D; C; 10445; # DESERET CAPITAL LETTER ES | ||
1396 | 1041E; C; 10446; # DESERET CAPITAL LETTER ZEE | ||
1397 | 1041F; C; 10447; # DESERET CAPITAL LETTER ESH | ||
1398 | 10420; C; 10448; # DESERET CAPITAL LETTER ZHEE | ||
1399 | 10421; C; 10449; # DESERET CAPITAL LETTER ER | ||
1400 | 10422; C; 1044A; # DESERET CAPITAL LETTER EL | ||
1401 | 10423; C; 1044B; # DESERET CAPITAL LETTER EM | ||
1402 | 10424; C; 1044C; # DESERET CAPITAL LETTER EN | ||
1403 | 10425; C; 1044D; # DESERET CAPITAL LETTER ENG | ||
1404 | 10426; C; 1044E; # DESERET CAPITAL LETTER OI | ||
1405 | 10427; C; 1044F; # DESERET CAPITAL LETTER EW | ||
1406 | 104B0; C; 104D8; # OSAGE CAPITAL LETTER A | ||
1407 | 104B1; C; 104D9; # OSAGE CAPITAL LETTER AI | ||
1408 | 104B2; C; 104DA; # OSAGE CAPITAL LETTER AIN | ||
1409 | 104B3; C; 104DB; # OSAGE CAPITAL LETTER AH | ||
1410 | 104B4; C; 104DC; # OSAGE CAPITAL LETTER BRA | ||
1411 | 104B5; C; 104DD; # OSAGE CAPITAL LETTER CHA | ||
1412 | 104B6; C; 104DE; # OSAGE CAPITAL LETTER EHCHA | ||
1413 | 104B7; C; 104DF; # OSAGE CAPITAL LETTER E | ||
1414 | 104B8; C; 104E0; # OSAGE CAPITAL LETTER EIN | ||
1415 | 104B9; C; 104E1; # OSAGE CAPITAL LETTER HA | ||
1416 | 104BA; C; 104E2; # OSAGE CAPITAL LETTER HYA | ||
1417 | 104BB; C; 104E3; # OSAGE CAPITAL LETTER I | ||
1418 | 104BC; C; 104E4; # OSAGE CAPITAL LETTER KA | ||
1419 | 104BD; C; 104E5; # OSAGE CAPITAL LETTER EHKA | ||
1420 | 104BE; C; 104E6; # OSAGE CAPITAL LETTER KYA | ||
1421 | 104BF; C; 104E7; # OSAGE CAPITAL LETTER LA | ||
1422 | 104C0; C; 104E8; # OSAGE CAPITAL LETTER MA | ||
1423 | 104C1; C; 104E9; # OSAGE CAPITAL LETTER NA | ||
1424 | 104C2; C; 104EA; # OSAGE CAPITAL LETTER O | ||
1425 | 104C3; C; 104EB; # OSAGE CAPITAL LETTER OIN | ||
1426 | 104C4; C; 104EC; # OSAGE CAPITAL LETTER PA | ||
1427 | 104C5; C; 104ED; # OSAGE CAPITAL LETTER EHPA | ||
1428 | 104C6; C; 104EE; # OSAGE CAPITAL LETTER SA | ||
1429 | 104C7; C; 104EF; # OSAGE CAPITAL LETTER SHA | ||
1430 | 104C8; C; 104F0; # OSAGE CAPITAL LETTER TA | ||
1431 | 104C9; C; 104F1; # OSAGE CAPITAL LETTER EHTA | ||
1432 | 104CA; C; 104F2; # OSAGE CAPITAL LETTER TSA | ||
1433 | 104CB; C; 104F3; # OSAGE CAPITAL LETTER EHTSA | ||
1434 | 104CC; C; 104F4; # OSAGE CAPITAL LETTER TSHA | ||
1435 | 104CD; C; 104F5; # OSAGE CAPITAL LETTER DHA | ||
1436 | 104CE; C; 104F6; # OSAGE CAPITAL LETTER U | ||
1437 | 104CF; C; 104F7; # OSAGE CAPITAL LETTER WA | ||
1438 | 104D0; C; 104F8; # OSAGE CAPITAL LETTER KHA | ||
1439 | 104D1; C; 104F9; # OSAGE CAPITAL LETTER GHA | ||
1440 | 104D2; C; 104FA; # OSAGE CAPITAL LETTER ZA | ||
1441 | 104D3; C; 104FB; # OSAGE CAPITAL LETTER ZHA | ||
1442 | 10570; C; 10597; # VITHKUQI CAPITAL LETTER A | ||
1443 | 10571; C; 10598; # VITHKUQI CAPITAL LETTER BBE | ||
1444 | 10572; C; 10599; # VITHKUQI CAPITAL LETTER BE | ||
1445 | 10573; C; 1059A; # VITHKUQI CAPITAL LETTER CE | ||
1446 | 10574; C; 1059B; # VITHKUQI CAPITAL LETTER CHE | ||
1447 | 10575; C; 1059C; # VITHKUQI CAPITAL LETTER DE | ||
1448 | 10576; C; 1059D; # VITHKUQI CAPITAL LETTER DHE | ||
1449 | 10577; C; 1059E; # VITHKUQI CAPITAL LETTER EI | ||
1450 | 10578; C; 1059F; # VITHKUQI CAPITAL LETTER E | ||
1451 | 10579; C; 105A0; # VITHKUQI CAPITAL LETTER FE | ||
1452 | 1057A; C; 105A1; # VITHKUQI CAPITAL LETTER GA | ||
1453 | 1057C; C; 105A3; # VITHKUQI CAPITAL LETTER HA | ||
1454 | 1057D; C; 105A4; # VITHKUQI CAPITAL LETTER HHA | ||
1455 | 1057E; C; 105A5; # VITHKUQI CAPITAL LETTER I | ||
1456 | 1057F; C; 105A6; # VITHKUQI CAPITAL LETTER IJE | ||
1457 | 10580; C; 105A7; # VITHKUQI CAPITAL LETTER JE | ||
1458 | 10581; C; 105A8; # VITHKUQI CAPITAL LETTER KA | ||
1459 | 10582; C; 105A9; # VITHKUQI CAPITAL LETTER LA | ||
1460 | 10583; C; 105AA; # VITHKUQI CAPITAL LETTER LLA | ||
1461 | 10584; C; 105AB; # VITHKUQI CAPITAL LETTER ME | ||
1462 | 10585; C; 105AC; # VITHKUQI CAPITAL LETTER NE | ||
1463 | 10586; C; 105AD; # VITHKUQI CAPITAL LETTER NJE | ||
1464 | 10587; C; 105AE; # VITHKUQI CAPITAL LETTER O | ||
1465 | 10588; C; 105AF; # VITHKUQI CAPITAL LETTER PE | ||
1466 | 10589; C; 105B0; # VITHKUQI CAPITAL LETTER QA | ||
1467 | 1058A; C; 105B1; # VITHKUQI CAPITAL LETTER RE | ||
1468 | 1058C; C; 105B3; # VITHKUQI CAPITAL LETTER SE | ||
1469 | 1058D; C; 105B4; # VITHKUQI CAPITAL LETTER SHE | ||
1470 | 1058E; C; 105B5; # VITHKUQI CAPITAL LETTER TE | ||
1471 | 1058F; C; 105B6; # VITHKUQI CAPITAL LETTER THE | ||
1472 | 10590; C; 105B7; # VITHKUQI CAPITAL LETTER U | ||
1473 | 10591; C; 105B8; # VITHKUQI CAPITAL LETTER VE | ||
1474 | 10592; C; 105B9; # VITHKUQI CAPITAL LETTER XE | ||
1475 | 10594; C; 105BB; # VITHKUQI CAPITAL LETTER Y | ||
1476 | 10595; C; 105BC; # VITHKUQI CAPITAL LETTER ZE | ||
1477 | 10C80; C; 10CC0; # OLD HUNGARIAN CAPITAL LETTER A | ||
1478 | 10C81; C; 10CC1; # OLD HUNGARIAN CAPITAL LETTER AA | ||
1479 | 10C82; C; 10CC2; # OLD HUNGARIAN CAPITAL LETTER EB | ||
1480 | 10C83; C; 10CC3; # OLD HUNGARIAN CAPITAL LETTER AMB | ||
1481 | 10C84; C; 10CC4; # OLD HUNGARIAN CAPITAL LETTER EC | ||
1482 | 10C85; C; 10CC5; # OLD HUNGARIAN CAPITAL LETTER ENC | ||
1483 | 10C86; C; 10CC6; # OLD HUNGARIAN CAPITAL LETTER ECS | ||
1484 | 10C87; C; 10CC7; # OLD HUNGARIAN CAPITAL LETTER ED | ||
1485 | 10C88; C; 10CC8; # OLD HUNGARIAN CAPITAL LETTER AND | ||
1486 | 10C89; C; 10CC9; # OLD HUNGARIAN CAPITAL LETTER E | ||
1487 | 10C8A; C; 10CCA; # OLD HUNGARIAN CAPITAL LETTER CLOSE E | ||
1488 | 10C8B; C; 10CCB; # OLD HUNGARIAN CAPITAL LETTER EE | ||
1489 | 10C8C; C; 10CCC; # OLD HUNGARIAN CAPITAL LETTER EF | ||
1490 | 10C8D; C; 10CCD; # OLD HUNGARIAN CAPITAL LETTER EG | ||
1491 | 10C8E; C; 10CCE; # OLD HUNGARIAN CAPITAL LETTER EGY | ||
1492 | 10C8F; C; 10CCF; # OLD HUNGARIAN CAPITAL LETTER EH | ||
1493 | 10C90; C; 10CD0; # OLD HUNGARIAN CAPITAL LETTER I | ||
1494 | 10C91; C; 10CD1; # OLD HUNGARIAN CAPITAL LETTER II | ||
1495 | 10C92; C; 10CD2; # OLD HUNGARIAN CAPITAL LETTER EJ | ||
1496 | 10C93; C; 10CD3; # OLD HUNGARIAN CAPITAL LETTER EK | ||
1497 | 10C94; C; 10CD4; # OLD HUNGARIAN CAPITAL LETTER AK | ||
1498 | 10C95; C; 10CD5; # OLD HUNGARIAN CAPITAL LETTER UNK | ||
1499 | 10C96; C; 10CD6; # OLD HUNGARIAN CAPITAL LETTER EL | ||
1500 | 10C97; C; 10CD7; # OLD HUNGARIAN CAPITAL LETTER ELY | ||
1501 | 10C98; C; 10CD8; # OLD HUNGARIAN CAPITAL LETTER EM | ||
1502 | 10C99; C; 10CD9; # OLD HUNGARIAN CAPITAL LETTER EN | ||
1503 | 10C9A; C; 10CDA; # OLD HUNGARIAN CAPITAL LETTER ENY | ||
1504 | 10C9B; C; 10CDB; # OLD HUNGARIAN CAPITAL LETTER O | ||
1505 | 10C9C; C; 10CDC; # OLD HUNGARIAN CAPITAL LETTER OO | ||
1506 | 10C9D; C; 10CDD; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE | ||
1507 | 10C9E; C; 10CDE; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE | ||
1508 | 10C9F; C; 10CDF; # OLD HUNGARIAN CAPITAL LETTER OEE | ||
1509 | 10CA0; C; 10CE0; # OLD HUNGARIAN CAPITAL LETTER EP | ||
1510 | 10CA1; C; 10CE1; # OLD HUNGARIAN CAPITAL LETTER EMP | ||
1511 | 10CA2; C; 10CE2; # OLD HUNGARIAN CAPITAL LETTER ER | ||
1512 | 10CA3; C; 10CE3; # OLD HUNGARIAN CAPITAL LETTER SHORT ER | ||
1513 | 10CA4; C; 10CE4; # OLD HUNGARIAN CAPITAL LETTER ES | ||
1514 | 10CA5; C; 10CE5; # OLD HUNGARIAN CAPITAL LETTER ESZ | ||
1515 | 10CA6; C; 10CE6; # OLD HUNGARIAN CAPITAL LETTER ET | ||
1516 | 10CA7; C; 10CE7; # OLD HUNGARIAN CAPITAL LETTER ENT | ||
1517 | 10CA8; C; 10CE8; # OLD HUNGARIAN CAPITAL LETTER ETY | ||
1518 | 10CA9; C; 10CE9; # OLD HUNGARIAN CAPITAL LETTER ECH | ||
1519 | 10CAA; C; 10CEA; # OLD HUNGARIAN CAPITAL LETTER U | ||
1520 | 10CAB; C; 10CEB; # OLD HUNGARIAN CAPITAL LETTER UU | ||
1521 | 10CAC; C; 10CEC; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE | ||
1522 | 10CAD; C; 10CED; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE | ||
1523 | 10CAE; C; 10CEE; # OLD HUNGARIAN CAPITAL LETTER EV | ||
1524 | 10CAF; C; 10CEF; # OLD HUNGARIAN CAPITAL LETTER EZ | ||
1525 | 10CB0; C; 10CF0; # OLD HUNGARIAN CAPITAL LETTER EZS | ||
1526 | 10CB1; C; 10CF1; # OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN | ||
1527 | 10CB2; C; 10CF2; # OLD HUNGARIAN CAPITAL LETTER US | ||
1528 | 118A0; C; 118C0; # WARANG CITI CAPITAL LETTER NGAA | ||
1529 | 118A1; C; 118C1; # WARANG CITI CAPITAL LETTER A | ||
1530 | 118A2; C; 118C2; # WARANG CITI CAPITAL LETTER WI | ||
1531 | 118A3; C; 118C3; # WARANG CITI CAPITAL LETTER YU | ||
1532 | 118A4; C; 118C4; # WARANG CITI CAPITAL LETTER YA | ||
1533 | 118A5; C; 118C5; # WARANG CITI CAPITAL LETTER YO | ||
1534 | 118A6; C; 118C6; # WARANG CITI CAPITAL LETTER II | ||
1535 | 118A7; C; 118C7; # WARANG CITI CAPITAL LETTER UU | ||
1536 | 118A8; C; 118C8; # WARANG CITI CAPITAL LETTER E | ||
1537 | 118A9; C; 118C9; # WARANG CITI CAPITAL LETTER O | ||
1538 | 118AA; C; 118CA; # WARANG CITI CAPITAL LETTER ANG | ||
1539 | 118AB; C; 118CB; # WARANG CITI CAPITAL LETTER GA | ||
1540 | 118AC; C; 118CC; # WARANG CITI CAPITAL LETTER KO | ||
1541 | 118AD; C; 118CD; # WARANG CITI CAPITAL LETTER ENY | ||
1542 | 118AE; C; 118CE; # WARANG CITI CAPITAL LETTER YUJ | ||
1543 | 118AF; C; 118CF; # WARANG CITI CAPITAL LETTER UC | ||
1544 | 118B0; C; 118D0; # WARANG CITI CAPITAL LETTER ENN | ||
1545 | 118B1; C; 118D1; # WARANG CITI CAPITAL LETTER ODD | ||
1546 | 118B2; C; 118D2; # WARANG CITI CAPITAL LETTER TTE | ||
1547 | 118B3; C; 118D3; # WARANG CITI CAPITAL LETTER NUNG | ||
1548 | 118B4; C; 118D4; # WARANG CITI CAPITAL LETTER DA | ||
1549 | 118B5; C; 118D5; # WARANG CITI CAPITAL LETTER AT | ||
1550 | 118B6; C; 118D6; # WARANG CITI CAPITAL LETTER AM | ||
1551 | 118B7; C; 118D7; # WARANG CITI CAPITAL LETTER BU | ||
1552 | 118B8; C; 118D8; # WARANG CITI CAPITAL LETTER PU | ||
1553 | 118B9; C; 118D9; # WARANG CITI CAPITAL LETTER HIYO | ||
1554 | 118BA; C; 118DA; # WARANG CITI CAPITAL LETTER HOLO | ||
1555 | 118BB; C; 118DB; # WARANG CITI CAPITAL LETTER HORR | ||
1556 | 118BC; C; 118DC; # WARANG CITI CAPITAL LETTER HAR | ||
1557 | 118BD; C; 118DD; # WARANG CITI CAPITAL LETTER SSUU | ||
1558 | 118BE; C; 118DE; # WARANG CITI CAPITAL LETTER SII | ||
1559 | 118BF; C; 118DF; # WARANG CITI CAPITAL LETTER VIYO | ||
1560 | 16E40; C; 16E60; # MEDEFAIDRIN CAPITAL LETTER M | ||
1561 | 16E41; C; 16E61; # MEDEFAIDRIN CAPITAL LETTER S | ||
1562 | 16E42; C; 16E62; # MEDEFAIDRIN CAPITAL LETTER V | ||
1563 | 16E43; C; 16E63; # MEDEFAIDRIN CAPITAL LETTER W | ||
1564 | 16E44; C; 16E64; # MEDEFAIDRIN CAPITAL LETTER ATIU | ||
1565 | 16E45; C; 16E65; # MEDEFAIDRIN CAPITAL LETTER Z | ||
1566 | 16E46; C; 16E66; # MEDEFAIDRIN CAPITAL LETTER KP | ||
1567 | 16E47; C; 16E67; # MEDEFAIDRIN CAPITAL LETTER P | ||
1568 | 16E48; C; 16E68; # MEDEFAIDRIN CAPITAL LETTER T | ||
1569 | 16E49; C; 16E69; # MEDEFAIDRIN CAPITAL LETTER G | ||
1570 | 16E4A; C; 16E6A; # MEDEFAIDRIN CAPITAL LETTER F | ||
1571 | 16E4B; C; 16E6B; # MEDEFAIDRIN CAPITAL LETTER I | ||
1572 | 16E4C; C; 16E6C; # MEDEFAIDRIN CAPITAL LETTER K | ||
1573 | 16E4D; C; 16E6D; # MEDEFAIDRIN CAPITAL LETTER A | ||
1574 | 16E4E; C; 16E6E; # MEDEFAIDRIN CAPITAL LETTER J | ||
1575 | 16E4F; C; 16E6F; # MEDEFAIDRIN CAPITAL LETTER E | ||
1576 | 16E50; C; 16E70; # MEDEFAIDRIN CAPITAL LETTER B | ||
1577 | 16E51; C; 16E71; # MEDEFAIDRIN CAPITAL LETTER C | ||
1578 | 16E52; C; 16E72; # MEDEFAIDRIN CAPITAL LETTER U | ||
1579 | 16E53; C; 16E73; # MEDEFAIDRIN CAPITAL LETTER YU | ||
1580 | 16E54; C; 16E74; # MEDEFAIDRIN CAPITAL LETTER L | ||
1581 | 16E55; C; 16E75; # MEDEFAIDRIN CAPITAL LETTER Q | ||
1582 | 16E56; C; 16E76; # MEDEFAIDRIN CAPITAL LETTER HP | ||
1583 | 16E57; C; 16E77; # MEDEFAIDRIN CAPITAL LETTER NY | ||
1584 | 16E58; C; 16E78; # MEDEFAIDRIN CAPITAL LETTER X | ||
1585 | 16E59; C; 16E79; # MEDEFAIDRIN CAPITAL LETTER D | ||
1586 | 16E5A; C; 16E7A; # MEDEFAIDRIN CAPITAL LETTER OE | ||
1587 | 16E5B; C; 16E7B; # MEDEFAIDRIN CAPITAL LETTER N | ||
1588 | 16E5C; C; 16E7C; # MEDEFAIDRIN CAPITAL LETTER R | ||
1589 | 16E5D; C; 16E7D; # MEDEFAIDRIN CAPITAL LETTER O | ||
1590 | 16E5E; C; 16E7E; # MEDEFAIDRIN CAPITAL LETTER AI | ||
1591 | 16E5F; C; 16E7F; # MEDEFAIDRIN CAPITAL LETTER Y | ||
1592 | 1E900; C; 1E922; # ADLAM CAPITAL LETTER ALIF | ||
1593 | 1E901; C; 1E923; # ADLAM CAPITAL LETTER DAALI | ||
1594 | 1E902; C; 1E924; # ADLAM CAPITAL LETTER LAAM | ||
1595 | 1E903; C; 1E925; # ADLAM CAPITAL LETTER MIIM | ||
1596 | 1E904; C; 1E926; # ADLAM CAPITAL LETTER BA | ||
1597 | 1E905; C; 1E927; # ADLAM CAPITAL LETTER SINNYIIYHE | ||
1598 | 1E906; C; 1E928; # ADLAM CAPITAL LETTER PE | ||
1599 | 1E907; C; 1E929; # ADLAM CAPITAL LETTER BHE | ||
1600 | 1E908; C; 1E92A; # ADLAM CAPITAL LETTER RA | ||
1601 | 1E909; C; 1E92B; # ADLAM CAPITAL LETTER E | ||
1602 | 1E90A; C; 1E92C; # ADLAM CAPITAL LETTER FA | ||
1603 | 1E90B; C; 1E92D; # ADLAM CAPITAL LETTER I | ||
1604 | 1E90C; C; 1E92E; # ADLAM CAPITAL LETTER O | ||
1605 | 1E90D; C; 1E92F; # ADLAM CAPITAL LETTER DHA | ||
1606 | 1E90E; C; 1E930; # ADLAM CAPITAL LETTER YHE | ||
1607 | 1E90F; C; 1E931; # ADLAM CAPITAL LETTER WAW | ||
1608 | 1E910; C; 1E932; # ADLAM CAPITAL LETTER NUN | ||
1609 | 1E911; C; 1E933; # ADLAM CAPITAL LETTER KAF | ||
1610 | 1E912; C; 1E934; # ADLAM CAPITAL LETTER YA | ||
1611 | 1E913; C; 1E935; # ADLAM CAPITAL LETTER U | ||
1612 | 1E914; C; 1E936; # ADLAM CAPITAL LETTER JIIM | ||
1613 | 1E915; C; 1E937; # ADLAM CAPITAL LETTER CHI | ||
1614 | 1E916; C; 1E938; # ADLAM CAPITAL LETTER HA | ||
1615 | 1E917; C; 1E939; # ADLAM CAPITAL LETTER QAAF | ||
1616 | 1E918; C; 1E93A; # ADLAM CAPITAL LETTER GA | ||
1617 | 1E919; C; 1E93B; # ADLAM CAPITAL LETTER NYA | ||
1618 | 1E91A; C; 1E93C; # ADLAM CAPITAL LETTER TU | ||
1619 | 1E91B; C; 1E93D; # ADLAM CAPITAL LETTER NHA | ||
1620 | 1E91C; C; 1E93E; # ADLAM CAPITAL LETTER VA | ||
1621 | 1E91D; C; 1E93F; # ADLAM CAPITAL LETTER KHA | ||
1622 | 1E91E; C; 1E940; # ADLAM CAPITAL LETTER GBE | ||
1623 | 1E91F; C; 1E941; # ADLAM CAPITAL LETTER ZAL | ||
1624 | 1E920; C; 1E942; # ADLAM CAPITAL LETTER KPO | ||
1625 | 1E921; C; 1E943; # ADLAM CAPITAL LETTER SHA | ||
1626 | # | ||
1627 | # EOF | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/check_android_jni.py b/src/contrib/SDL-3.2.20/build-scripts/check_android_jni.py new file mode 100755 index 0000000..9e519fb --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/check_android_jni.py | |||
@@ -0,0 +1,172 @@ | |||
1 | #!/usr/bin/env python | ||
2 | |||
3 | import argparse | ||
4 | import dataclasses | ||
5 | import os | ||
6 | import pathlib | ||
7 | import re | ||
8 | |||
9 | ROOT = pathlib.Path(__file__).resolve().parents[1] | ||
10 | SDL_ANDROID_C = ROOT / "src/core/android/SDL_android.c" | ||
11 | METHOD_SOURCE_PATHS = ( | ||
12 | SDL_ANDROID_C, | ||
13 | ROOT / "src/hidapi/android/hid.cpp", | ||
14 | ) | ||
15 | JAVA_ROOT = ROOT / "android-project/app/src/main/java" | ||
16 | |||
17 | |||
18 | BASIC_TYPE_SPEC_LUT = { | ||
19 | "char": "C", | ||
20 | "byte": "B", | ||
21 | "short": "S", | ||
22 | "int": "I", | ||
23 | "long": "J", | ||
24 | "float": "F", | ||
25 | "double": "D", | ||
26 | "void": "V", | ||
27 | "boolean": "Z", | ||
28 | "Object": "Ljava/lang/Object;", | ||
29 | "String": "Ljava/lang/String;", | ||
30 | } | ||
31 | |||
32 | |||
33 | @dataclasses.dataclass(frozen=True) | ||
34 | class JniType: | ||
35 | typ: str | ||
36 | array: int | ||
37 | |||
38 | |||
39 | def java_type_to_jni_spec_internal(type_str: str) -> tuple[int, str]: | ||
40 | for basic_type_str, basic_type_spec in BASIC_TYPE_SPEC_LUT.items(): | ||
41 | if type_str.startswith(basic_type_str): | ||
42 | return len(basic_type_str), basic_type_spec | ||
43 | raise ValueError(f"Don't know how to convert {repr(type_str)} to its equivalent jni spec") | ||
44 | |||
45 | |||
46 | def java_type_to_jni_spec(type_str: str) -> str: | ||
47 | end, type_spec = java_type_to_jni_spec_internal(type_str) | ||
48 | suffix_str = type_str[end:] | ||
49 | assert(all(c in "[] \t" for c in suffix_str)) | ||
50 | suffix_str = "".join(filter(lambda v: v in "[]", suffix_str)) | ||
51 | assert len(suffix_str) % 2 == 0 | ||
52 | array_spec = "[" * (len(suffix_str) // 2) | ||
53 | return array_spec + type_spec | ||
54 | |||
55 | |||
56 | def java_method_to_jni_spec(ret: str, args: list[str]) -> str: | ||
57 | return "(" + "".join(java_type_to_jni_spec(a) for a in args) +")" + java_type_to_jni_spec(ret) | ||
58 | |||
59 | |||
60 | @dataclasses.dataclass(frozen=True) | ||
61 | class JniMethodBinding: | ||
62 | name: str | ||
63 | spec: str | ||
64 | |||
65 | |||
66 | def collect_jni_bindings_from_c() -> dict[str, set[JniMethodBinding]]: | ||
67 | bindings = {} | ||
68 | |||
69 | sdl_android_text = SDL_ANDROID_C.read_text() | ||
70 | for m in re.finditer(r"""register_methods\((?:[A-Za-z0-9]+),\s*"(?P<class>[a-zA-Z0-9_/]+)",\s*(?P<table>[a-zA-Z0-9_]+),\s*SDL_arraysize\((?P=table)\)\)""", sdl_android_text): | ||
71 | kls = m["class"] | ||
72 | table = m["table"] | ||
73 | methods = set() | ||
74 | in_struct = False | ||
75 | for method_source_path in METHOD_SOURCE_PATHS: | ||
76 | method_source = method_source_path.read_text() | ||
77 | for line in method_source.splitlines(keepends=False): | ||
78 | if re.match(f"(static )?JNINativeMethod {table}" + r"\[([0-9]+)?\] = \{", line): | ||
79 | in_struct = True | ||
80 | continue | ||
81 | if in_struct: | ||
82 | if re.match(r"\};", line): | ||
83 | in_struct = False | ||
84 | break | ||
85 | n = re.match(r"""\s*\{\s*"(?P<method>[a-zA-Z0-9_]+)"\s*,\s*"(?P<spec>[()A-Za-z0-9_/;[]+)"\s*,\s*(\(void\*\))?(HID|SDL)[_A-Z]*_JAVA_[_A-Z]*INTERFACE[_A-Z]*\((?P=method)\)\s*\},?""", line) | ||
86 | assert n, f"'{line}' does not match regex" | ||
87 | methods.add(JniMethodBinding(name=n["method"], spec=n["spec"])) | ||
88 | continue | ||
89 | if methods: | ||
90 | break | ||
91 | if methods: | ||
92 | break | ||
93 | assert methods, f"Could not find methods for {kls} (table={table})" | ||
94 | |||
95 | assert not in_struct | ||
96 | |||
97 | assert kls not in bindings, f"{kls} must be unique in C sources" | ||
98 | bindings[kls] = methods | ||
99 | return bindings | ||
100 | |||
101 | def collect_jni_bindings_from_java() -> dict[str, set[JniMethodBinding]]: | ||
102 | bindings = {} | ||
103 | |||
104 | for root, _, files in os.walk(JAVA_ROOT): | ||
105 | for file in files: | ||
106 | file_path = pathlib.Path(root) / file | ||
107 | java_text = file_path.read_text() | ||
108 | methods = set() | ||
109 | for m in re.finditer(r"(?:(?:public|private)\s+)?(?:static\s+)?native\s+(?P<ret>[A-Za-z0-9_]+)\s+(?P<method>[a-zA-Z0-9_]+)\s*\(\s*(?P<args>[^)]*)\);", java_text): | ||
110 | name = m["method"] | ||
111 | ret = m["ret"] | ||
112 | args = [] | ||
113 | args_str = m["args"].strip() | ||
114 | if args_str: | ||
115 | for a_s in args_str.split(","): | ||
116 | atype_str, _ = a_s.strip().rsplit(" ") | ||
117 | args.append(atype_str.strip()) | ||
118 | |||
119 | spec = java_method_to_jni_spec(ret=ret, args=args) | ||
120 | methods.add(JniMethodBinding(name=name, spec=spec)) | ||
121 | if methods: | ||
122 | relative_java_path = file_path.relative_to(JAVA_ROOT) | ||
123 | relative_java_path_without_suffix = relative_java_path.with_suffix("") | ||
124 | kls = "/".join(relative_java_path_without_suffix.parts) | ||
125 | assert kls not in bindings, f"{kls} must be unique in JAVA sources" | ||
126 | bindings[kls] = methods | ||
127 | return bindings | ||
128 | |||
129 | |||
130 | def print_error(*args): | ||
131 | print("ERROR:", *args) | ||
132 | |||
133 | |||
134 | def main(): | ||
135 | parser = argparse.ArgumentParser(allow_abbrev=False, description="Verify Android JNI bindings") | ||
136 | args = parser.parse_args() | ||
137 | |||
138 | bindings_from_c = collect_jni_bindings_from_c() | ||
139 | bindings_from_java = collect_jni_bindings_from_java() | ||
140 | |||
141 | all_ok = bindings_from_c == bindings_from_java | ||
142 | if all_ok: | ||
143 | print("OK") | ||
144 | else: | ||
145 | print("NOT OK") | ||
146 | kls_c = set(bindings_from_c.keys()) | ||
147 | kls_java = set(bindings_from_java.keys()) | ||
148 | if kls_c != kls_java: | ||
149 | only_c = kls_c - kls_java | ||
150 | for c in only_c: | ||
151 | print_error(f"Missing class in JAVA sources: {c}") | ||
152 | only_java = kls_java - kls_c | ||
153 | for c in only_java: | ||
154 | print_error(f"Missing class in C sources: {c}") | ||
155 | |||
156 | klasses = kls_c.union(kls_java) | ||
157 | for kls in klasses: | ||
158 | m_c = bindings_from_c.get(kls) | ||
159 | m_j = bindings_from_java.get(kls) | ||
160 | if m_c and m_j and m_c != m_j: | ||
161 | m_only_c = m_c - m_j | ||
162 | for c in m_only_c: | ||
163 | print_error(f"{kls}: Binding only in C source: {c.name} {c.spec}") | ||
164 | m_only_j = m_j - m_c | ||
165 | for c in m_only_j: | ||
166 | print_error(f"{kls}: Binding only in JAVA source: {c.name} {c.spec}") | ||
167 | |||
168 | return 0 if all_ok else 1 | ||
169 | |||
170 | |||
171 | if __name__ == "__main__": | ||
172 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/check_stdlib_usage.py b/src/contrib/SDL-3.2.20/build-scripts/check_stdlib_usage.py new file mode 100755 index 0000000..0994130 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/check_stdlib_usage.py | |||
@@ -0,0 +1,262 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # Simple DirectMedia Layer | ||
4 | # Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
5 | # | ||
6 | # This software is provided 'as-is', without any express or implied | ||
7 | # warranty. In no event will the authors be held liable for any damages | ||
8 | # arising from the use of this software. | ||
9 | # | ||
10 | # Permission is granted to anyone to use this software for any purpose, | ||
11 | # including commercial applications, and to alter it and redistribute it | ||
12 | # freely, subject to the following restrictions: | ||
13 | # | ||
14 | # 1. The origin of this software must not be misrepresented; you must not | ||
15 | # claim that you wrote the original software. If you use this software | ||
16 | # in a product, an acknowledgment in the product documentation would be | ||
17 | # appreciated but is not required. | ||
18 | # 2. Altered source versions must be plainly marked as such, and must not be | ||
19 | # misrepresented as being the original software. | ||
20 | # 3. This notice may not be removed or altered from any source distribution. | ||
21 | # | ||
22 | # This script detects use of stdlib function in SDL code | ||
23 | |||
24 | import argparse | ||
25 | import os | ||
26 | import pathlib | ||
27 | import re | ||
28 | import sys | ||
29 | |||
30 | SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] | ||
31 | |||
32 | STDLIB_SYMBOLS = [ | ||
33 | 'abs', | ||
34 | 'acos', | ||
35 | 'acosf', | ||
36 | 'asin', | ||
37 | 'asinf', | ||
38 | 'asprintf', | ||
39 | 'atan', | ||
40 | 'atan2', | ||
41 | 'atan2f', | ||
42 | 'atanf', | ||
43 | 'atof', | ||
44 | 'atoi', | ||
45 | 'bsearch', | ||
46 | 'calloc', | ||
47 | 'ceil', | ||
48 | 'ceilf', | ||
49 | 'copysign', | ||
50 | 'copysignf', | ||
51 | 'cos', | ||
52 | 'cosf', | ||
53 | 'crc32', | ||
54 | 'exp', | ||
55 | 'expf', | ||
56 | 'fabs', | ||
57 | 'fabsf', | ||
58 | 'floor', | ||
59 | 'floorf', | ||
60 | 'fmod', | ||
61 | 'fmodf', | ||
62 | 'free', | ||
63 | 'getenv', | ||
64 | 'isalnum', | ||
65 | 'isalpha', | ||
66 | 'isblank', | ||
67 | 'iscntrl', | ||
68 | 'isdigit', | ||
69 | 'isgraph', | ||
70 | 'islower', | ||
71 | 'isprint', | ||
72 | 'ispunct', | ||
73 | 'isspace', | ||
74 | 'isupper', | ||
75 | 'isxdigit', | ||
76 | 'itoa', | ||
77 | 'lltoa', | ||
78 | 'log10', | ||
79 | 'log10f', | ||
80 | 'logf', | ||
81 | 'lround', | ||
82 | 'lroundf', | ||
83 | 'ltoa', | ||
84 | 'malloc', | ||
85 | 'memalign', | ||
86 | 'memcmp', | ||
87 | 'memcpy', | ||
88 | 'memcpy4', | ||
89 | 'memmove', | ||
90 | 'memset', | ||
91 | 'pow', | ||
92 | 'powf', | ||
93 | 'qsort', | ||
94 | 'qsort_r', | ||
95 | 'qsort_s', | ||
96 | 'realloc', | ||
97 | 'round', | ||
98 | 'roundf', | ||
99 | 'scalbn', | ||
100 | 'scalbnf', | ||
101 | 'setenv', | ||
102 | 'sin', | ||
103 | 'sinf', | ||
104 | 'snprintf', | ||
105 | 'sqrt', | ||
106 | 'sqrtf', | ||
107 | 'sscanf', | ||
108 | 'strcasecmp', | ||
109 | 'strchr', | ||
110 | 'strcmp', | ||
111 | 'strdup', | ||
112 | 'strlcat', | ||
113 | 'strlcpy', | ||
114 | 'strlen', | ||
115 | 'strlwr', | ||
116 | 'strncasecmp', | ||
117 | 'strncmp', | ||
118 | 'strrchr', | ||
119 | 'strrev', | ||
120 | 'strstr', | ||
121 | 'strtod', | ||
122 | 'strtokr', | ||
123 | 'strtol', | ||
124 | 'strtoll', | ||
125 | 'strtoul', | ||
126 | 'strupr', | ||
127 | 'tan', | ||
128 | 'tanf', | ||
129 | 'tolower', | ||
130 | 'toupper', | ||
131 | 'trunc', | ||
132 | 'truncf', | ||
133 | 'uitoa', | ||
134 | 'ulltoa', | ||
135 | 'ultoa', | ||
136 | 'utf8strlcpy', | ||
137 | 'utf8strlen', | ||
138 | 'vasprintf', | ||
139 | 'vsnprintf', | ||
140 | 'vsscanf', | ||
141 | 'wcscasecmp', | ||
142 | 'wcscmp', | ||
143 | 'wcsdup', | ||
144 | 'wcslcat', | ||
145 | 'wcslcpy', | ||
146 | 'wcslen', | ||
147 | 'wcsncasecmp', | ||
148 | 'wcsncmp', | ||
149 | 'wcsstr', | ||
150 | ] | ||
151 | RE_STDLIB_SYMBOL = re.compile(rf"\b(?P<symbol>{'|'.join(STDLIB_SYMBOLS)})\b\(") | ||
152 | |||
153 | |||
154 | def find_symbols_in_file(file: pathlib.Path) -> int: | ||
155 | match_count = 0 | ||
156 | |||
157 | allowed_extensions = [ ".c", ".cpp", ".m", ".h", ".hpp", ".cc" ] | ||
158 | |||
159 | excluded_paths = [ | ||
160 | "src/stdlib", | ||
161 | "src/libm", | ||
162 | "src/hidapi", | ||
163 | "src/video/khronos", | ||
164 | "src/video/stb_image.h", | ||
165 | "include/SDL3", | ||
166 | "build-scripts/gen_audio_resampler_filter.c", | ||
167 | "build-scripts/gen_audio_channel_conversion.c", | ||
168 | "test/win32/sdlprocdump.c", | ||
169 | ] | ||
170 | |||
171 | filename = pathlib.Path(file) | ||
172 | |||
173 | for ep in excluded_paths: | ||
174 | if ep in filename.as_posix(): | ||
175 | # skip | ||
176 | return 0 | ||
177 | |||
178 | if filename.suffix not in allowed_extensions: | ||
179 | # skip | ||
180 | return 0 | ||
181 | |||
182 | # print("Parse %s" % file) | ||
183 | |||
184 | try: | ||
185 | with file.open("r", encoding="UTF-8", newline="") as rfp: | ||
186 | parsing_comment = False | ||
187 | for line_i, original_line in enumerate(rfp, start=1): | ||
188 | line = original_line.strip() | ||
189 | |||
190 | line_comment = "" | ||
191 | |||
192 | # Get the comment block /* ... */ across several lines | ||
193 | while True: | ||
194 | if parsing_comment: | ||
195 | pos_end_comment = line.find("*/") | ||
196 | if pos_end_comment >= 0: | ||
197 | line = line[pos_end_comment+2:] | ||
198 | parsing_comment = False | ||
199 | else: | ||
200 | break | ||
201 | else: | ||
202 | pos_start_comment = line.find("/*") | ||
203 | if pos_start_comment >= 0: | ||
204 | pos_end_comment = line.find("*/", pos_start_comment+2) | ||
205 | if pos_end_comment >= 0: | ||
206 | line_comment += line[pos_start_comment:pos_end_comment+2] | ||
207 | line = line[:pos_start_comment] + line[pos_end_comment+2:] | ||
208 | else: | ||
209 | line_comment += line[pos_start_comment:] | ||
210 | line = line[:pos_start_comment] | ||
211 | parsing_comment = True | ||
212 | break | ||
213 | else: | ||
214 | break | ||
215 | if parsing_comment: | ||
216 | continue | ||
217 | pos_line_comment = line.find("//") | ||
218 | if pos_line_comment >= 0: | ||
219 | line_comment += line[pos_line_comment:] | ||
220 | line = line[:pos_line_comment] | ||
221 | |||
222 | if m := RE_STDLIB_SYMBOL.match(line): | ||
223 | override_string = f"This should NOT be SDL_{m['symbol']}()" | ||
224 | if override_string not in line_comment: | ||
225 | print(f"{filename}:{line_i}") | ||
226 | print(f" {line}") | ||
227 | print(f"") | ||
228 | match_count += 1 | ||
229 | |||
230 | except UnicodeDecodeError: | ||
231 | print(f"{file} is not text, skipping", file=sys.stderr) | ||
232 | |||
233 | return match_count | ||
234 | |||
235 | def find_symbols_in_dir(path: pathlib.Path) -> int: | ||
236 | match_count = 0 | ||
237 | for entry in path.glob("*"): | ||
238 | if entry.is_dir(): | ||
239 | match_count += find_symbols_in_dir(entry) | ||
240 | else: | ||
241 | match_count += find_symbols_in_file(entry) | ||
242 | return match_count | ||
243 | |||
244 | def main(): | ||
245 | parser = argparse.ArgumentParser(fromfile_prefix_chars="@") | ||
246 | parser.add_argument("path", default=SDL_ROOT, nargs="?", type=pathlib.Path, help="Path to look for stdlib symbols") | ||
247 | args = parser.parse_args() | ||
248 | |||
249 | print(f"Looking for stdlib usage in {args.path}...") | ||
250 | |||
251 | match_count = find_symbols_in_dir(args.path) | ||
252 | |||
253 | if match_count: | ||
254 | print("If the stdlib usage is intentional, add a '// This should NOT be SDL_<symbol>()' line comment.") | ||
255 | print("") | ||
256 | print("NOT OK") | ||
257 | else: | ||
258 | print("OK") | ||
259 | return 1 if match_count else 0 | ||
260 | |||
261 | if __name__ == "__main__": | ||
262 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/clang-format-src.sh b/src/contrib/SDL-3.2.20/build-scripts/clang-format-src.sh new file mode 100755 index 0000000..bc0defc --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/clang-format-src.sh | |||
@@ -0,0 +1,39 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd "$(dirname $0)/../src" | ||
4 | |||
5 | echo "Running clang-format in $(pwd)" | ||
6 | |||
7 | find . -regex '.*\.[chm]p*' -exec clang-format -i {} \; | ||
8 | |||
9 | # Revert third-party code | ||
10 | git checkout \ | ||
11 | events/imKStoUCS.* \ | ||
12 | hidapi \ | ||
13 | joystick/controller_type.c \ | ||
14 | joystick/controller_type.h \ | ||
15 | joystick/hidapi/steam/controller_constants.h \ | ||
16 | joystick/hidapi/steam/controller_structs.h \ | ||
17 | libm \ | ||
18 | stdlib/SDL_malloc.c \ | ||
19 | stdlib/SDL_qsort.c \ | ||
20 | stdlib/SDL_strtokr.c \ | ||
21 | video/khronos \ | ||
22 | video/x11/edid.h \ | ||
23 | video/x11/edid-parse.c \ | ||
24 | video/x11/xsettings-client.* \ | ||
25 | video/yuv2rgb | ||
26 | clang-format -i hidapi/SDL_hidapi.c | ||
27 | |||
28 | # Revert generated code | ||
29 | git checkout \ | ||
30 | dynapi/SDL_dynapi_overrides.h \ | ||
31 | dynapi/SDL_dynapi_procs.h \ | ||
32 | render/*/*Shader*.h \ | ||
33 | render/metal/SDL_shaders_metal_*.h \ | ||
34 | render/vitagxm/SDL_render_vita_gxm_shaders.h \ | ||
35 | video/directx/SDL_d3d12_xbox_cmacros.h \ | ||
36 | video/directx/d3d12.h \ | ||
37 | video/directx/d3d12sdklayers.h \ | ||
38 | |||
39 | echo "clang-format complete!" | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-i686.cmake b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-i686.cmake new file mode 100644 index 0000000..8be7b3a --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-i686.cmake | |||
@@ -0,0 +1,18 @@ | |||
1 | set(CMAKE_SYSTEM_NAME Windows) | ||
2 | set(CMAKE_SYSTEM_PROCESSOR x86) | ||
3 | |||
4 | find_program(CMAKE_C_COMPILER NAMES i686-w64-mingw32-gcc) | ||
5 | find_program(CMAKE_CXX_COMPILER NAMES i686-w64-mingw32-g++) | ||
6 | find_program(CMAKE_RC_COMPILER NAMES i686-w64-mingw32-windres windres) | ||
7 | |||
8 | if(NOT CMAKE_C_COMPILER) | ||
9 | message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") | ||
10 | endif() | ||
11 | |||
12 | if(NOT CMAKE_CXX_COMPILER) | ||
13 | message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") | ||
14 | endif() | ||
15 | |||
16 | if(NOT CMAKE_RC_COMPILER) | ||
17 | message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") | ||
18 | endif() | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-x86_64.cmake b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-x86_64.cmake new file mode 100644 index 0000000..8bf4366 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-mingw64-x86_64.cmake | |||
@@ -0,0 +1,18 @@ | |||
1 | set(CMAKE_SYSTEM_NAME Windows) | ||
2 | set(CMAKE_SYSTEM_PROCESSOR x86_64) | ||
3 | |||
4 | find_program(CMAKE_C_COMPILER NAMES x86_64-w64-mingw32-gcc) | ||
5 | find_program(CMAKE_CXX_COMPILER NAMES x86_64-w64-mingw32-g++) | ||
6 | find_program(CMAKE_RC_COMPILER NAMES x86_64-w64-mingw32-windres windres) | ||
7 | |||
8 | if(NOT CMAKE_C_COMPILER) | ||
9 | message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") | ||
10 | endif() | ||
11 | |||
12 | if(NOT CMAKE_CXX_COMPILER) | ||
13 | message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") | ||
14 | endif() | ||
15 | |||
16 | if(NOT CMAKE_RC_COMPILER) | ||
17 | message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") | ||
18 | endif() | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-aarch64le.cmake b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-aarch64le.cmake new file mode 100644 index 0000000..26f5da4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-aarch64le.cmake | |||
@@ -0,0 +1,14 @@ | |||
1 | set(CMAKE_SYSTEM_NAME QNX) | ||
2 | |||
3 | set(arch gcc_ntoaarch64le) | ||
4 | |||
5 | set(CMAKE_C_COMPILER qcc) | ||
6 | set(CMAKE_C_COMPILER_TARGET ${arch}) | ||
7 | set(CMAKE_CXX_COMPILER q++) | ||
8 | set(CMAKE_CXX_COMPILER_TARGET ${arch}) | ||
9 | |||
10 | set(CMAKE_SYSROOT $ENV{QNX_TARGET}) | ||
11 | |||
12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
13 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-x86_64.cmake b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-x86_64.cmake new file mode 100644 index 0000000..29f795a --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/cmake-toolchain-qnx-x86_64.cmake | |||
@@ -0,0 +1,14 @@ | |||
1 | set(CMAKE_SYSTEM_NAME QNX) | ||
2 | |||
3 | set(arch gcc_ntox86_64) | ||
4 | |||
5 | set(CMAKE_C_COMPILER qcc) | ||
6 | set(CMAKE_C_COMPILER_TARGET ${arch}) | ||
7 | set(CMAKE_CXX_COMPILER q++) | ||
8 | set(CMAKE_CXX_COMPILER_TARGET ${arch}) | ||
9 | |||
10 | set(CMAKE_SYSROOT $ENV{QNX_TARGET}) | ||
11 | |||
12 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
13 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/codechecker-buildbot.sh b/src/contrib/SDL-3.2.20/build-scripts/codechecker-buildbot.sh new file mode 100755 index 0000000..76b7853 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/codechecker-buildbot.sh | |||
@@ -0,0 +1,59 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # This is a script used by some Buildbot build workers to push the project | ||
4 | # through Clang's static analyzer and prepare the output to be uploaded | ||
5 | # back to the buildmaster. You might find it useful too. | ||
6 | |||
7 | # Install Clang (you already have it on macOS, apt-get install clang | ||
8 | # on Ubuntu, etc), install CMake, and pip3 install codechecker. | ||
9 | |||
10 | FINALDIR="$1" | ||
11 | |||
12 | set -x | ||
13 | set -e | ||
14 | |||
15 | cd `dirname "$0"` | ||
16 | cd .. | ||
17 | |||
18 | rm -rf codechecker-buildbot | ||
19 | if [ ! -z "$FINALDIR" ]; then | ||
20 | rm -rf "$FINALDIR" | ||
21 | fi | ||
22 | |||
23 | mkdir codechecker-buildbot | ||
24 | cd codechecker-buildbot | ||
25 | |||
26 | # We turn off deprecated declarations, because we don't care about these warnings during static analysis. | ||
27 | cmake -Wno-dev -DSDL_STATIC=OFF -DCMAKE_BUILD_TYPE=Debug -DSDL_ASSERTIONS=enabled -DCMAKE_C_FLAGS="-Wno-deprecated-declarations" -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .. | ||
28 | |||
29 | # CMake on macOS adds "-arch arm64" or whatever is appropriate, but this confuses CodeChecker, so strip it out. | ||
30 | perl -w -pi -e 's/\-arch\s+.*?\s+//g;' compile_commands.json | ||
31 | |||
32 | rm -rf ../analysis | ||
33 | CodeChecker analyze compile_commands.json -o ./reports | ||
34 | |||
35 | # "parse" returns 2 if there was a static analysis issue to report, but this | ||
36 | # does not signify an error in the parsing (that would be error code 1). Turn | ||
37 | # off the abort-on-error flag. | ||
38 | set +e | ||
39 | CodeChecker parse ./reports -e html -o ../analysis | ||
40 | set -e | ||
41 | |||
42 | cd .. | ||
43 | chmod -R a+r analysis | ||
44 | chmod -R go-w analysis | ||
45 | find analysis -type d -exec chmod a+x {} \; | ||
46 | if [ -x /usr/bin/xattr ]; then find analysis -exec /usr/bin/xattr -d com.apple.quarantine {} \; 2>/dev/null ; fi | ||
47 | |||
48 | if [ ! -z "$FINALDIR" ]; then | ||
49 | mv analysis "$FINALDIR" | ||
50 | else | ||
51 | FINALDIR=analysis | ||
52 | fi | ||
53 | |||
54 | rm -rf codechecker-buildbot | ||
55 | |||
56 | echo "Done. Final output is in '$FINALDIR' ..." | ||
57 | |||
58 | # end of codechecker-buildbot.sh ... | ||
59 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/create-android-project.py b/src/contrib/SDL-3.2.20/build-scripts/create-android-project.py new file mode 100755 index 0000000..0b8994f --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/create-android-project.py | |||
@@ -0,0 +1,241 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | import os | ||
3 | from argparse import ArgumentParser | ||
4 | from pathlib import Path | ||
5 | import re | ||
6 | import shutil | ||
7 | import sys | ||
8 | import textwrap | ||
9 | |||
10 | |||
11 | SDL_ROOT = Path(__file__).resolve().parents[1] | ||
12 | |||
13 | def extract_sdl_version() -> str: | ||
14 | """ | ||
15 | Extract SDL version from SDL3/SDL_version.h | ||
16 | """ | ||
17 | |||
18 | with open(SDL_ROOT / "include/SDL3/SDL_version.h") as f: | ||
19 | data = f.read() | ||
20 | |||
21 | major = int(next(re.finditer(r"#define\s+SDL_MAJOR_VERSION\s+([0-9]+)", data)).group(1)) | ||
22 | minor = int(next(re.finditer(r"#define\s+SDL_MINOR_VERSION\s+([0-9]+)", data)).group(1)) | ||
23 | micro = int(next(re.finditer(r"#define\s+SDL_MICRO_VERSION\s+([0-9]+)", data)).group(1)) | ||
24 | return f"{major}.{minor}.{micro}" | ||
25 | |||
26 | def replace_in_file(path: Path, regex_what: str, replace_with: str) -> None: | ||
27 | with path.open("r") as f: | ||
28 | data = f.read() | ||
29 | |||
30 | new_data, count = re.subn(regex_what, replace_with, data) | ||
31 | |||
32 | assert count > 0, f"\"{regex_what}\" did not match anything in \"{path}\"" | ||
33 | |||
34 | with open(path, "w") as f: | ||
35 | f.write(new_data) | ||
36 | |||
37 | |||
38 | def android_mk_use_prefab(path: Path) -> None: | ||
39 | """ | ||
40 | Replace relative SDL inclusion with dependency on prefab package | ||
41 | """ | ||
42 | |||
43 | with path.open() as f: | ||
44 | data = "".join(line for line in f.readlines() if "# SDL" not in line) | ||
45 | |||
46 | data, _ = re.subn("[\n]{3,}", "\n\n", data) | ||
47 | |||
48 | data, count = re.subn(r"(LOCAL_SHARED_LIBRARIES\s*:=\s*SDL3)", "LOCAL_SHARED_LIBRARIES := SDL3 SDL3-Headers", data) | ||
49 | assert count == 1, f"Must have injected SDL3-Headers in {path} exactly once" | ||
50 | |||
51 | newdata = data + textwrap.dedent(""" | ||
52 | # https://google.github.io/prefab/build-systems.html | ||
53 | |||
54 | # Add the prefab modules to the import path. | ||
55 | $(call import-add-path,/out) | ||
56 | |||
57 | # Import SDL3 so we can depend on it. | ||
58 | $(call import-module,prefab/SDL3) | ||
59 | """) | ||
60 | |||
61 | with path.open("w") as f: | ||
62 | f.write(newdata) | ||
63 | |||
64 | |||
65 | def cmake_mk_no_sdl(path: Path) -> None: | ||
66 | """ | ||
67 | Don't add the source directories of SDL/SDL_image/SDL_mixer/... | ||
68 | """ | ||
69 | |||
70 | with path.open() as f: | ||
71 | lines = f.readlines() | ||
72 | |||
73 | newlines: list[str] = [] | ||
74 | for line in lines: | ||
75 | if "add_subdirectory(SDL" in line: | ||
76 | while newlines[-1].startswith("#"): | ||
77 | newlines = newlines[:-1] | ||
78 | continue | ||
79 | newlines.append(line) | ||
80 | |||
81 | newdata, _ = re.subn("[\n]{3,}", "\n\n", "".join(newlines)) | ||
82 | |||
83 | with path.open("w") as f: | ||
84 | f.write(newdata) | ||
85 | |||
86 | |||
87 | def gradle_add_prefab_and_aar(path: Path, aar: str) -> None: | ||
88 | with path.open() as f: | ||
89 | data = f.read() | ||
90 | |||
91 | data, count = re.subn("android {", textwrap.dedent(""" | ||
92 | android { | ||
93 | buildFeatures { | ||
94 | prefab true | ||
95 | }"""), data) | ||
96 | assert count == 1 | ||
97 | |||
98 | data, count = re.subn("dependencies {", textwrap.dedent(f""" | ||
99 | dependencies {{ | ||
100 | implementation files('libs/{aar}')"""), data) | ||
101 | assert count == 1 | ||
102 | |||
103 | with path.open("w") as f: | ||
104 | f.write(data) | ||
105 | |||
106 | |||
107 | def gradle_add_package_name(path: Path, package_name: str) -> None: | ||
108 | with path.open() as f: | ||
109 | data = f.read() | ||
110 | |||
111 | data, count = re.subn("org.libsdl.app", package_name, data) | ||
112 | assert count >= 1 | ||
113 | |||
114 | with path.open("w") as f: | ||
115 | f.write(data) | ||
116 | |||
117 | |||
118 | def main() -> int: | ||
119 | description = "Create a simple Android gradle project from input sources." | ||
120 | epilog = textwrap.dedent("""\ | ||
121 | You need to manually copy a prebuilt SDL3 Android archive into the project tree when using the aar variant. | ||
122 | |||
123 | Any changes you have done to the sources in the Android project will be lost | ||
124 | """) | ||
125 | parser = ArgumentParser(description=description, epilog=epilog, allow_abbrev=False) | ||
126 | parser.add_argument("package_name", metavar="PACKAGENAME", help="Android package name (e.g. com.yourcompany.yourapp)") | ||
127 | parser.add_argument("sources", metavar="SOURCE", nargs="*", help="Source code of your application. The files are copied to the output directory.") | ||
128 | parser.add_argument("--variant", choices=["copy", "symlink", "aar"], default="copy", help="Choose variant of SDL project (copy: copy SDL sources, symlink: symlink SDL sources, aar: use Android aar archive)") | ||
129 | parser.add_argument("--output", "-o", default=SDL_ROOT / "build", type=Path, help="Location where to store the Android project") | ||
130 | parser.add_argument("--version", default=None, help="SDL3 version to use as aar dependency (only used for aar variant)") | ||
131 | |||
132 | args = parser.parse_args() | ||
133 | if not args.sources: | ||
134 | print("Reading source file paths from stdin (press CTRL+D to stop)") | ||
135 | args.sources = [path for path in sys.stdin.read().strip().split() if path] | ||
136 | if not args.sources: | ||
137 | parser.error("No sources passed") | ||
138 | |||
139 | if not os.getenv("ANDROID_HOME"): | ||
140 | print("WARNING: ANDROID_HOME environment variable not set", file=sys.stderr) | ||
141 | if not os.getenv("ANDROID_NDK_HOME"): | ||
142 | print("WARNING: ANDROID_NDK_HOME environment variable not set", file=sys.stderr) | ||
143 | |||
144 | args.sources = [Path(src) for src in args.sources] | ||
145 | |||
146 | build_path = args.output / args.package_name | ||
147 | |||
148 | # Remove the destination folder | ||
149 | shutil.rmtree(build_path, ignore_errors=True) | ||
150 | |||
151 | # Copy the Android project | ||
152 | shutil.copytree(SDL_ROOT / "android-project", build_path) | ||
153 | |||
154 | # Add the source files to the ndk-build and cmake projects | ||
155 | replace_in_file(build_path / "app/jni/src/Android.mk", r"YourSourceHere\.c", " \\\n ".join(src.name for src in args.sources)) | ||
156 | replace_in_file(build_path / "app/jni/src/CMakeLists.txt", r"YourSourceHere\.c", "\n ".join(src.name for src in args.sources)) | ||
157 | |||
158 | # Remove placeholder source "YourSourceHere.c" | ||
159 | (build_path / "app/jni/src/YourSourceHere.c").unlink() | ||
160 | |||
161 | # Copy sources to output folder | ||
162 | for src in args.sources: | ||
163 | if not src.is_file(): | ||
164 | parser.error(f"\"{src}\" is not a file") | ||
165 | shutil.copyfile(src, build_path / "app/jni/src" / src.name) | ||
166 | |||
167 | sdl_project_files = ( | ||
168 | SDL_ROOT / "src", | ||
169 | SDL_ROOT / "include", | ||
170 | SDL_ROOT / "LICENSE.txt", | ||
171 | SDL_ROOT / "README.md", | ||
172 | SDL_ROOT / "Android.mk", | ||
173 | SDL_ROOT / "CMakeLists.txt", | ||
174 | SDL_ROOT / "cmake", | ||
175 | ) | ||
176 | if args.variant == "copy": | ||
177 | (build_path / "app/jni/SDL").mkdir(exist_ok=True, parents=True) | ||
178 | for sdl_project_file in sdl_project_files: | ||
179 | # Copy SDL project files and directories | ||
180 | if sdl_project_file.is_dir(): | ||
181 | shutil.copytree(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) | ||
182 | elif sdl_project_file.is_file(): | ||
183 | shutil.copyfile(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) | ||
184 | elif args.variant == "symlink": | ||
185 | (build_path / "app/jni/SDL").mkdir(exist_ok=True, parents=True) | ||
186 | # Create symbolic links for all SDL project files | ||
187 | for sdl_project_file in sdl_project_files: | ||
188 | os.symlink(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) | ||
189 | elif args.variant == "aar": | ||
190 | if not args.version: | ||
191 | args.version = extract_sdl_version() | ||
192 | |||
193 | major = args.version.split(".")[0] | ||
194 | aar = f"SDL{ major }-{ args.version }.aar" | ||
195 | |||
196 | # Remove all SDL java classes | ||
197 | shutil.rmtree(build_path / "app/src/main/java") | ||
198 | |||
199 | # Use prefab to generate include-able files | ||
200 | gradle_add_prefab_and_aar(build_path / "app/build.gradle", aar=aar) | ||
201 | |||
202 | # Make sure to use the prefab-generated files and not SDL sources | ||
203 | android_mk_use_prefab(build_path / "app/jni/src/Android.mk") | ||
204 | cmake_mk_no_sdl(build_path / "app/jni/CMakeLists.txt") | ||
205 | |||
206 | aar_libs_folder = build_path / "app/libs" | ||
207 | aar_libs_folder.mkdir(parents=True) | ||
208 | with (aar_libs_folder / "copy-sdl-aars-here.txt").open("w") as f: | ||
209 | f.write(f"Copy {aar} to this folder.\n") | ||
210 | |||
211 | print(f"WARNING: copy { aar } to { aar_libs_folder }", file=sys.stderr) | ||
212 | |||
213 | # Add the package name to build.gradle | ||
214 | gradle_add_package_name(build_path / "app/build.gradle", args.package_name) | ||
215 | |||
216 | # Create entry activity, subclassing SDLActivity | ||
217 | activity = args.package_name[args.package_name.rfind(".") + 1:].capitalize() + "Activity" | ||
218 | activity_path = build_path / "app/src/main/java" / args.package_name.replace(".", "/") / f"{activity}.java" | ||
219 | activity_path.parent.mkdir(parents=True) | ||
220 | with activity_path.open("w") as f: | ||
221 | f.write(textwrap.dedent(f""" | ||
222 | package {args.package_name}; | ||
223 | |||
224 | import org.libsdl.app.SDLActivity; | ||
225 | |||
226 | public class {activity} extends SDLActivity | ||
227 | {{ | ||
228 | }} | ||
229 | """)) | ||
230 | |||
231 | # Add the just-generated activity to the Android manifest | ||
232 | replace_in_file(build_path / "app/src/main/AndroidManifest.xml", 'name="SDLActivity"', f'name="{activity}"') | ||
233 | |||
234 | # Update project and build | ||
235 | print("To build and install to a device for testing, run the following:") | ||
236 | print(f"cd {build_path}") | ||
237 | print("./gradlew installDebug") | ||
238 | return 0 | ||
239 | |||
240 | if __name__ == "__main__": | ||
241 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/create-release.py b/src/contrib/SDL-3.2.20/build-scripts/create-release.py new file mode 100755 index 0000000..14916fa --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/create-release.py | |||
@@ -0,0 +1,45 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | |||
3 | import argparse | ||
4 | from pathlib import Path | ||
5 | import json | ||
6 | import logging | ||
7 | import re | ||
8 | import subprocess | ||
9 | |||
10 | ROOT = Path(__file__).resolve().parents[1] | ||
11 | |||
12 | |||
13 | def determine_remote() -> str: | ||
14 | text = (ROOT / "build-scripts/release-info.json").read_text() | ||
15 | release_info = json.loads(text) | ||
16 | if "remote" in release_info: | ||
17 | return release_info["remote"] | ||
18 | project_with_version = release_info["name"] | ||
19 | project, _ = re.subn("([^a-zA-Z_])", "", project_with_version) | ||
20 | return f"libsdl-org/{project}" | ||
21 | |||
22 | |||
23 | def main(): | ||
24 | default_remote = determine_remote() | ||
25 | |||
26 | parser = argparse.ArgumentParser(allow_abbrev=False) | ||
27 | parser.add_argument("--ref", required=True, help=f"Name of branch or tag containing release.yml") | ||
28 | parser.add_argument("--remote", "-R", default=default_remote, help=f"Remote repo (default={default_remote})") | ||
29 | parser.add_argument("--commit", help=f"Input 'commit' of release.yml (default is the hash of the ref)") | ||
30 | args = parser.parse_args() | ||
31 | |||
32 | if args.commit is None: | ||
33 | args.commit = subprocess.check_output(["git", "rev-parse", args.ref], cwd=ROOT, text=True).strip() | ||
34 | |||
35 | |||
36 | print(f"Running release.yml workflow:") | ||
37 | print(f" remote = {args.remote}") | ||
38 | print(f" ref = {args.ref}") | ||
39 | print(f" commit = {args.commit}") | ||
40 | |||
41 | subprocess.check_call(["gh", "-R", args.remote, "workflow", "run", "release.yml", "--ref", args.ref, "-f", f"commit={args.commit}"], cwd=ROOT) | ||
42 | |||
43 | |||
44 | if __name__ == "__main__": | ||
45 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/fnsince.pl b/src/contrib/SDL-3.2.20/build-scripts/fnsince.pl new file mode 100755 index 0000000..9d987fc --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/fnsince.pl | |||
@@ -0,0 +1,169 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | use warnings; | ||
4 | use strict; | ||
5 | use File::Basename; | ||
6 | use Cwd qw(abs_path); | ||
7 | |||
8 | my $wikipath = undef; | ||
9 | foreach (@ARGV) { | ||
10 | $wikipath = abs_path($_), next if not defined $wikipath; | ||
11 | } | ||
12 | |||
13 | chdir(dirname(__FILE__)); | ||
14 | chdir('..'); | ||
15 | |||
16 | my %fulltags = (); | ||
17 | my @unsorted_releases = (); | ||
18 | open(PIPEFH, '-|', 'git tag -l') or die "Failed to read git release tags: $!\n"; | ||
19 | |||
20 | while (<PIPEFH>) { | ||
21 | chomp; | ||
22 | my $fulltag = $_; | ||
23 | if ($fulltag =~ /\A(prerelease|preview|release)\-(\d+)\.(\d+)\.(\d+)\Z/) { | ||
24 | # Ignore anything that isn't a x.y.0 release. | ||
25 | # Make sure new APIs are assigned to the next minor version and ignore the patch versions, but we'll make an except for the prereleases. | ||
26 | my $release_type = $1; | ||
27 | my $major = int($2); | ||
28 | my $minor = int($3); | ||
29 | my $patch = int($4); | ||
30 | next if ($major != 3); # Ignore anything that isn't an SDL3 release. | ||
31 | next if ($patch != 0) && ($minor >= 2); # Ignore anything that is a patch release (unless it was between the preview release and the official release). | ||
32 | |||
33 | # Consider this release version. | ||
34 | my $ver = "${major}.${minor}.${patch}"; | ||
35 | push @unsorted_releases, $ver; | ||
36 | $fulltags{$ver} = $fulltag; | ||
37 | } | ||
38 | } | ||
39 | close(PIPEFH); | ||
40 | |||
41 | #print("\n\nUNSORTED\n"); | ||
42 | #foreach (@unsorted_releases) { | ||
43 | # print "$_\n"; | ||
44 | #} | ||
45 | |||
46 | my @releases = sort { | ||
47 | my @asplit = split /\./, $a; | ||
48 | my @bsplit = split /\./, $b; | ||
49 | my $rc; | ||
50 | for (my $i = 0; $i < scalar(@asplit); $i++) { | ||
51 | return 1 if (scalar(@bsplit) <= $i); # a is "2.0.1" and b is "2.0", or whatever. | ||
52 | my $aseg = $asplit[$i]; | ||
53 | my $bseg = $bsplit[$i]; | ||
54 | $rc = int($aseg) <=> int($bseg); | ||
55 | return $rc if ($rc != 0); # found the difference. | ||
56 | } | ||
57 | return 0; # still here? They matched completely?! | ||
58 | } @unsorted_releases; | ||
59 | |||
60 | my $current_release = $releases[-1]; | ||
61 | my $next_release; | ||
62 | |||
63 | if (scalar(@releases) > 0) { | ||
64 | # this happens to work for how SDL versions things at the moment. | ||
65 | $current_release = $releases[-1]; | ||
66 | |||
67 | my @current_release_segments = split /\./, $current_release; | ||
68 | # if we're still in the 3.1.x prereleases, call the "next release" 3.2.0 even if we do more prereleases. | ||
69 | if (($current_release_segments[0] == '3') && ($current_release_segments[1] == '1')) { | ||
70 | $next_release = '3.2.0'; | ||
71 | } else { | ||
72 | @current_release_segments[1] = '' . (int($current_release_segments[1]) + 2); | ||
73 | $next_release = join('.', @current_release_segments); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | #print("\n\nSORTED\n"); | ||
78 | #foreach (@releases) { | ||
79 | # print "$_\n"; | ||
80 | #} | ||
81 | #print("\nCURRENT RELEASE: $current_release\n"); | ||
82 | #print("NEXT RELEASE: $next_release\n\n"); | ||
83 | |||
84 | push @releases, 'HEAD'; | ||
85 | $fulltags{'HEAD'} = 'HEAD'; | ||
86 | |||
87 | my %funcs = (); | ||
88 | foreach my $release (@releases) { | ||
89 | #print("Checking $release...\n"); | ||
90 | my $tag = $fulltags{$release}; | ||
91 | my $blobname = "$tag:src/dynapi/SDL_dynapi_overrides.h"; | ||
92 | |||
93 | if ($release =~ /\A3\.[01]\.\d+\Z/) { # make everything up to the first SDL3 official release look like 3.2.0. | ||
94 | $release = '3.2.0'; | ||
95 | } | ||
96 | |||
97 | open(PIPEFH, '-|', "git show '$blobname'") or die "Failed to read git blob '$blobname': $!\n"; | ||
98 | while (<PIPEFH>) { | ||
99 | chomp; | ||
100 | if (/\A\#define\s+(SDL_.*?)\s+SDL_.*?_REAL\Z/) { | ||
101 | my $fn = $1; | ||
102 | $funcs{$fn} = $release if not defined $funcs{$fn}; | ||
103 | } | ||
104 | } | ||
105 | close(PIPEFH); | ||
106 | } | ||
107 | |||
108 | if (not defined $wikipath) { | ||
109 | foreach my $release (@releases) { | ||
110 | foreach my $fn (sort keys %funcs) { | ||
111 | print("$fn: $funcs{$fn}\n") if $funcs{$fn} eq $release; | ||
112 | } | ||
113 | } | ||
114 | } else { | ||
115 | if (defined $wikipath) { | ||
116 | chdir($wikipath); | ||
117 | foreach my $fn (keys %funcs) { | ||
118 | next if $fn eq 'SDL_ThreadID'; # this was a function early on (it's now called SDL_GetThreadID), but now it's a datatype (which originally had a different capitalization). | ||
119 | my $revision = $funcs{$fn}; | ||
120 | $revision = $next_release if $revision eq 'HEAD'; | ||
121 | my $fname = "$fn.md"; | ||
122 | if ( ! -f $fname ) { | ||
123 | #print STDERR "No such file: $fname\n"; | ||
124 | next; | ||
125 | } | ||
126 | |||
127 | my @lines = (); | ||
128 | open(FH, '<', $fname) or die("Can't open $fname for read: $!\n"); | ||
129 | my $added = 0; | ||
130 | while (<FH>) { | ||
131 | chomp; | ||
132 | if ((/\A\-\-\-\-/) && (!$added)) { | ||
133 | push @lines, "## Version"; | ||
134 | push @lines, ""; | ||
135 | push @lines, "This function is available since SDL $revision."; | ||
136 | push @lines, ""; | ||
137 | $added = 1; | ||
138 | } | ||
139 | push @lines, $_; | ||
140 | next if not /\A\#\#\s+Version/; | ||
141 | $added = 1; | ||
142 | push @lines, ""; | ||
143 | push @lines, "This function is available since SDL $revision."; | ||
144 | push @lines, ""; | ||
145 | while (<FH>) { | ||
146 | chomp; | ||
147 | next if not (/\A\#\#\s+/ || /\A\-\-\-\-/); | ||
148 | push @lines, $_; | ||
149 | last; | ||
150 | } | ||
151 | } | ||
152 | close(FH); | ||
153 | |||
154 | if (!$added) { | ||
155 | push @lines, "## Version"; | ||
156 | push @lines, ""; | ||
157 | push @lines, "This function is available since SDL $revision."; | ||
158 | push @lines, ""; | ||
159 | } | ||
160 | |||
161 | open(FH, '>', $fname) or die("Can't open $fname for write: $!\n"); | ||
162 | foreach (@lines) { | ||
163 | print FH "$_\n"; | ||
164 | } | ||
165 | close(FH); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/gen_audio_channel_conversion.c b/src/contrib/SDL-3.2.20/build-scripts/gen_audio_channel_conversion.c new file mode 100644 index 0000000..85a856e --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/gen_audio_channel_conversion.c | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
4 | |||
5 | This software is provided 'as-is', without any express or implied | ||
6 | warranty. In no event will the authors be held liable for any damages | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely, subject to the following restrictions: | ||
12 | |||
13 | 1. The origin of this software must not be misrepresented; you must not | ||
14 | claim that you wrote the original software. If you use this software | ||
15 | in a product, an acknowledgment in the product documentation would be | ||
16 | appreciated but is not required. | ||
17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
18 | misrepresented as being the original software. | ||
19 | 3. This notice may not be removed or altered from any source distribution. | ||
20 | */ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | |||
24 | /* | ||
25 | |||
26 | Built with: | ||
27 | |||
28 | gcc -o genchancvt build-scripts/gen_audio_channel_conversion.c -lm && ./genchancvt > src/audio/SDL_audio_channel_converters.h | ||
29 | |||
30 | */ | ||
31 | |||
32 | #define NUM_CHANNELS 8 | ||
33 | |||
34 | static const char *layout_names[NUM_CHANNELS] = { | ||
35 | "Mono", "Stereo", "2.1", "Quad", "4.1", "5.1", "6.1", "7.1" | ||
36 | }; | ||
37 | |||
38 | static const char *channel_names[NUM_CHANNELS][NUM_CHANNELS] = { | ||
39 | /* mono */ { "FC" }, | ||
40 | /* stereo */ { "FL", "FR" }, | ||
41 | /* 2.1 */ { "FL", "FR", "LFE" }, | ||
42 | /* quad */ { "FL", "FR", "BL", "BR" }, | ||
43 | /* 4.1 */ { "FL", "FR", "LFE", "BL", "BR" }, | ||
44 | /* 5.1 */ { "FL", "FR", "FC", "LFE", "BL", "BR" }, | ||
45 | /* 6.1 */ { "FL", "FR", "FC", "LFE", "BC", "SL", "SR" }, | ||
46 | /* 7.1 */ { "FL", "FR", "FC", "LFE", "BL", "BR", "SL", "SR" }, | ||
47 | }; | ||
48 | |||
49 | |||
50 | /* | ||
51 | * This table is from FAudio: | ||
52 | * | ||
53 | * https://raw.githubusercontent.com/FNA-XNA/FAudio/master/src/matrix_defaults.inl | ||
54 | */ | ||
55 | static const float channel_conversion_matrix[8][8][64] = { | ||
56 | { | ||
57 | /* 1 x 1 */ | ||
58 | { 1.000000000f }, | ||
59 | /* 1 x 2 */ | ||
60 | { 1.000000000f, 1.000000000f }, | ||
61 | /* 1 x 3 */ | ||
62 | { 1.000000000f, 1.000000000f, 0.000000000f }, | ||
63 | /* 1 x 4 */ | ||
64 | { 1.000000000f, 1.000000000f, 0.000000000f, 0.000000000f }, | ||
65 | /* 1 x 5 */ | ||
66 | { 1.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
67 | /* 1 x 6 */ | ||
68 | { 1.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
69 | /* 1 x 7 */ | ||
70 | { 1.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
71 | /* 1 x 8 */ | ||
72 | { 1.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
73 | }, | ||
74 | { | ||
75 | /* 2 x 1 */ | ||
76 | { 0.500000000f, 0.500000000f }, | ||
77 | /* 2 x 2 */ | ||
78 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
79 | /* 2 x 3 */ | ||
80 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f }, | ||
81 | /* 2 x 4 */ | ||
82 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
83 | /* 2 x 5 */ | ||
84 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
85 | /* 2 x 6 */ | ||
86 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
87 | /* 2 x 7 */ | ||
88 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
89 | /* 2 x 8 */ | ||
90 | { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
91 | }, | ||
92 | { | ||
93 | /* 3 x 1 */ | ||
94 | { 0.333333343f, 0.333333343f, 0.333333343f }, | ||
95 | /* 3 x 2 */ | ||
96 | { 0.800000012f, 0.000000000f, 0.200000003f, 0.000000000f, 0.800000012f, 0.200000003f }, | ||
97 | /* 3 x 3 */ | ||
98 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
99 | /* 3 x 4 */ | ||
100 | { 0.888888896f, 0.000000000f, 0.111111112f, 0.000000000f, 0.888888896f, 0.111111112f, 0.000000000f, 0.000000000f, 0.111111112f, 0.000000000f, 0.000000000f, 0.111111112f }, | ||
101 | /* 3 x 5 */ | ||
102 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
103 | /* 3 x 6 */ | ||
104 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
105 | /* 3 x 7 */ | ||
106 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
107 | /* 3 x 8 */ | ||
108 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
109 | }, | ||
110 | { | ||
111 | /* 4 x 1 */ | ||
112 | { 0.250000000f, 0.250000000f, 0.250000000f, 0.250000000f }, | ||
113 | /* 4 x 2 */ | ||
114 | { 0.421000004f, 0.000000000f, 0.358999997f, 0.219999999f, 0.000000000f, 0.421000004f, 0.219999999f, 0.358999997f }, | ||
115 | /* 4 x 3 */ | ||
116 | { 0.421000004f, 0.000000000f, 0.358999997f, 0.219999999f, 0.000000000f, 0.421000004f, 0.219999999f, 0.358999997f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
117 | /* 4 x 4 */ | ||
118 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
119 | /* 4 x 5 */ | ||
120 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
121 | /* 4 x 6 */ | ||
122 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
123 | /* 4 x 7 */ | ||
124 | { 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.500000000f, 0.500000000f, 0.000000000f, 0.000000000f, 0.796000004f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.796000004f }, | ||
125 | /* 4 x 8 */ | ||
126 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
127 | }, | ||
128 | { | ||
129 | /* 5 x 1 */ | ||
130 | { 0.200000003f, 0.200000003f, 0.200000003f, 0.200000003f, 0.200000003f }, | ||
131 | /* 5 x 2 */ | ||
132 | { 0.374222219f, 0.000000000f, 0.111111112f, 0.319111109f, 0.195555553f, 0.000000000f, 0.374222219f, 0.111111112f, 0.195555553f, 0.319111109f }, | ||
133 | /* 5 x 3 */ | ||
134 | { 0.421000004f, 0.000000000f, 0.000000000f, 0.358999997f, 0.219999999f, 0.000000000f, 0.421000004f, 0.000000000f, 0.219999999f, 0.358999997f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f }, | ||
135 | /* 5 x 4 */ | ||
136 | { 0.941176474f, 0.000000000f, 0.058823530f, 0.000000000f, 0.000000000f, 0.000000000f, 0.941176474f, 0.058823530f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.058823530f, 0.941176474f, 0.000000000f, 0.000000000f, 0.000000000f, 0.058823530f, 0.000000000f, 0.941176474f }, | ||
137 | /* 5 x 5 */ | ||
138 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
139 | /* 5 x 6 */ | ||
140 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
141 | /* 5 x 7 */ | ||
142 | { 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.500000000f, 0.500000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.796000004f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.796000004f }, | ||
143 | /* 5 x 8 */ | ||
144 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
145 | }, | ||
146 | { | ||
147 | /* 6 x 1 */ | ||
148 | { 0.166666672f, 0.166666672f, 0.166666672f, 0.166666672f, 0.166666672f, 0.166666672f }, | ||
149 | /* 6 x 2 */ | ||
150 | { 0.294545442f, 0.000000000f, 0.208181813f, 0.090909094f, 0.251818180f, 0.154545456f, 0.000000000f, 0.294545442f, 0.208181813f, 0.090909094f, 0.154545456f, 0.251818180f }, | ||
151 | /* 6 x 3 */ | ||
152 | { 0.324000001f, 0.000000000f, 0.229000002f, 0.000000000f, 0.277000010f, 0.170000002f, 0.000000000f, 0.324000001f, 0.229000002f, 0.000000000f, 0.170000002f, 0.277000010f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f }, | ||
153 | /* 6 x 4 */ | ||
154 | { 0.558095276f, 0.000000000f, 0.394285709f, 0.047619049f, 0.000000000f, 0.000000000f, 0.000000000f, 0.558095276f, 0.394285709f, 0.047619049f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.047619049f, 0.558095276f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.047619049f, 0.000000000f, 0.558095276f }, | ||
155 | /* 6 x 5 */ | ||
156 | { 0.586000025f, 0.000000000f, 0.414000005f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.586000025f, 0.414000005f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.586000025f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.586000025f }, | ||
157 | /* 6 x 6 */ | ||
158 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
159 | /* 6 x 7 */ | ||
160 | { 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.939999998f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.500000000f, 0.500000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.796000004f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.796000004f }, | ||
161 | /* 6 x 8 */ | ||
162 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } | ||
163 | }, | ||
164 | { | ||
165 | /* 7 x 1 */ | ||
166 | { 0.143142849f, 0.143142849f, 0.143142849f, 0.142857149f, 0.143142849f, 0.143142849f, 0.143142849f }, | ||
167 | /* 7 x 2 */ | ||
168 | { 0.247384623f, 0.000000000f, 0.174461529f, 0.076923080f, 0.174461529f, 0.226153851f, 0.100615382f, 0.000000000f, 0.247384623f, 0.174461529f, 0.076923080f, 0.174461529f, 0.100615382f, 0.226153851f }, | ||
169 | /* 7 x 3 */ | ||
170 | { 0.268000007f, 0.000000000f, 0.188999996f, 0.000000000f, 0.188999996f, 0.245000005f, 0.108999997f, 0.000000000f, 0.268000007f, 0.188999996f, 0.000000000f, 0.188999996f, 0.108999997f, 0.245000005f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
171 | /* 7 x 4 */ | ||
172 | { 0.463679999f, 0.000000000f, 0.327360004f, 0.040000003f, 0.000000000f, 0.168960005f, 0.000000000f, 0.000000000f, 0.463679999f, 0.327360004f, 0.040000003f, 0.000000000f, 0.000000000f, 0.168960005f, 0.000000000f, 0.000000000f, 0.000000000f, 0.040000003f, 0.327360004f, 0.431039989f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.040000003f, 0.327360004f, 0.000000000f, 0.431039989f }, | ||
173 | /* 7 x 5 */ | ||
174 | { 0.483000010f, 0.000000000f, 0.340999991f, 0.000000000f, 0.000000000f, 0.175999999f, 0.000000000f, 0.000000000f, 0.483000010f, 0.340999991f, 0.000000000f, 0.000000000f, 0.000000000f, 0.175999999f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.340999991f, 0.449000001f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.340999991f, 0.000000000f, 0.449000001f }, | ||
175 | /* 7 x 6 */ | ||
176 | { 0.611000001f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.223000005f, 0.000000000f, 0.000000000f, 0.611000001f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.223000005f, 0.000000000f, 0.000000000f, 0.611000001f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.432000011f, 0.568000019f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.432000011f, 0.000000000f, 0.568000019f }, | ||
177 | /* 7 x 7 */ | ||
178 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f }, | ||
179 | /* 7 x 8 */ | ||
180 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.707000017f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.707000017f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f } | ||
181 | }, | ||
182 | { | ||
183 | /* 8 x 1 */ | ||
184 | { 0.125125006f, 0.125125006f, 0.125125006f, 0.125000000f, 0.125125006f, 0.125125006f, 0.125125006f, 0.125125006f }, | ||
185 | /* 8 x 2 */ | ||
186 | { 0.211866662f, 0.000000000f, 0.150266662f, 0.066666670f, 0.181066677f, 0.111066669f, 0.194133341f, 0.085866667f, 0.000000000f, 0.211866662f, 0.150266662f, 0.066666670f, 0.111066669f, 0.181066677f, 0.085866667f, 0.194133341f }, | ||
187 | /* 8 x 3 */ | ||
188 | { 0.226999998f, 0.000000000f, 0.160999998f, 0.000000000f, 0.194000006f, 0.119000003f, 0.208000004f, 0.092000000f, 0.000000000f, 0.226999998f, 0.160999998f, 0.000000000f, 0.119000003f, 0.194000006f, 0.092000000f, 0.208000004f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f }, | ||
189 | /* 8 x 4 */ | ||
190 | { 0.466344833f, 0.000000000f, 0.329241365f, 0.034482758f, 0.000000000f, 0.000000000f, 0.169931039f, 0.000000000f, 0.000000000f, 0.466344833f, 0.329241365f, 0.034482758f, 0.000000000f, 0.000000000f, 0.000000000f, 0.169931039f, 0.000000000f, 0.000000000f, 0.000000000f, 0.034482758f, 0.466344833f, 0.000000000f, 0.433517247f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.034482758f, 0.000000000f, 0.466344833f, 0.000000000f, 0.433517247f }, | ||
191 | /* 8 x 5 */ | ||
192 | { 0.483000010f, 0.000000000f, 0.340999991f, 0.000000000f, 0.000000000f, 0.000000000f, 0.175999999f, 0.000000000f, 0.000000000f, 0.483000010f, 0.340999991f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.175999999f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.483000010f, 0.000000000f, 0.449000001f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.483000010f, 0.000000000f, 0.449000001f }, | ||
193 | /* 8 x 6 */ | ||
194 | { 0.518000007f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.188999996f, 0.000000000f, 0.000000000f, 0.518000007f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.188999996f, 0.000000000f, 0.000000000f, 0.518000007f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.518000007f, 0.000000000f, 0.481999993f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.518000007f, 0.000000000f, 0.481999993f }, | ||
195 | /* 8 x 7 */ | ||
196 | { 0.541000009f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.541000009f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.541000009f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.287999988f, 0.287999988f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.458999991f, 0.000000000f, 0.541000009f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.458999991f, 0.000000000f, 0.541000009f }, | ||
197 | /* 8 x 8 */ | ||
198 | { 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f } | ||
199 | } | ||
200 | }; | ||
201 | |||
202 | static char *remove_dots(const char *str) /* this is NOT robust. */ | ||
203 | { | ||
204 | static char retval1[32]; | ||
205 | static char retval2[32]; | ||
206 | static int idx = 0; | ||
207 | char *retval = (idx++ & 1) ? retval1 : retval2; | ||
208 | char *ptr = retval; | ||
209 | while (*str) { | ||
210 | if (*str != '.') { | ||
211 | *(ptr++) = *str; | ||
212 | } | ||
213 | str++; | ||
214 | } | ||
215 | *ptr = '\0'; | ||
216 | return retval; | ||
217 | } | ||
218 | |||
219 | static char *lowercase(const char *str) /* this is NOT robust. */ | ||
220 | { | ||
221 | static char retval1[32]; | ||
222 | static char retval2[32]; | ||
223 | static int idx = 0; | ||
224 | char *retval = (idx++ & 1) ? retval1 : retval2; | ||
225 | char *ptr = retval; | ||
226 | while (*str) { | ||
227 | const char ch = *(str++); | ||
228 | *(ptr++) = ((ch >= 'A') && (ch <= 'Z')) ? (ch - ('A' - 'a')) : ch; | ||
229 | } | ||
230 | *ptr = '\0'; | ||
231 | return retval; | ||
232 | } | ||
233 | |||
234 | static void write_converter(const int fromchans, const int tochans) | ||
235 | { | ||
236 | const char *fromstr = layout_names[fromchans-1]; | ||
237 | const char *tostr = layout_names[tochans-1]; | ||
238 | const float *cvtmatrix = channel_conversion_matrix[fromchans-1][tochans-1]; | ||
239 | const float *fptr; | ||
240 | const int convert_backwards = (tochans > fromchans); | ||
241 | int input_channel_used[NUM_CHANNELS]; | ||
242 | int i, j; | ||
243 | |||
244 | if (tochans == fromchans) { | ||
245 | return; /* nothing to convert, don't generate a converter. */ | ||
246 | } | ||
247 | |||
248 | for (i = 0; i < fromchans; i++) { | ||
249 | input_channel_used[i] = 0; | ||
250 | } | ||
251 | |||
252 | fptr = cvtmatrix; | ||
253 | for (j = 0; j < tochans; j++) { | ||
254 | for (i = 0; i < fromchans; i++) { | ||
255 | #if 0 | ||
256 | printf("to=%d, from=%d, coeff=%f\n", j, i, *fptr); | ||
257 | #endif | ||
258 | if (*(fptr++) != 0.0f) { | ||
259 | input_channel_used[i]++; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | printf("static void SDL_Convert%sTo%s(float *dst, const float *src, int num_frames)\n{\n", remove_dots(fromstr), remove_dots(tostr)); | ||
265 | |||
266 | printf(" int i;\n" | ||
267 | "\n" | ||
268 | " LOG_DEBUG_AUDIO_CONVERT(\"%s\", \"%s\");\n" | ||
269 | "\n", lowercase(fromstr), lowercase(tostr)); | ||
270 | |||
271 | if (convert_backwards) { /* must convert backwards when growing the output in-place. */ | ||
272 | printf(" // convert backwards, since output is growing in-place.\n"); | ||
273 | printf(" src += (num_frames-1)"); | ||
274 | if (fromchans != 1) { | ||
275 | printf(" * %d", fromchans); | ||
276 | } | ||
277 | printf(";\n"); | ||
278 | |||
279 | printf(" dst += (num_frames-1)"); | ||
280 | if (tochans != 1) { | ||
281 | printf(" * %d", tochans); | ||
282 | } | ||
283 | printf(";\n"); | ||
284 | printf(" for (i = num_frames; i; i--, "); | ||
285 | if (fromchans == 1) { | ||
286 | printf("src--"); | ||
287 | } else { | ||
288 | printf("src -= %d", fromchans); | ||
289 | } | ||
290 | printf(", "); | ||
291 | if (tochans == 1) { | ||
292 | printf("dst--"); | ||
293 | } else { | ||
294 | printf("dst -= %d", tochans); | ||
295 | } | ||
296 | printf(") {\n"); | ||
297 | fptr = cvtmatrix; | ||
298 | for (i = 0; i < fromchans; i++) { | ||
299 | if (input_channel_used[i] > 1) { /* don't read it from src more than once. */ | ||
300 | printf(" const float src%s = src[%d];\n", channel_names[fromchans-1][i], i); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | for (j = tochans - 1; j >= 0; j--) { | ||
305 | int has_input = 0; | ||
306 | fptr = cvtmatrix + (fromchans * j); | ||
307 | printf(" dst[%d] /* %s */ =", j, channel_names[tochans-1][j]); | ||
308 | for (i = fromchans - 1; i >= 0; i--) { | ||
309 | const float coefficient = fptr[i]; | ||
310 | char srcname[32]; | ||
311 | if (coefficient == 0.0f) { | ||
312 | continue; | ||
313 | } else if (input_channel_used[i] > 1) { | ||
314 | snprintf(srcname, sizeof (srcname), "src%s", channel_names[fromchans-1][i]); | ||
315 | } else { | ||
316 | snprintf(srcname, sizeof (srcname), "src[%d]", i); | ||
317 | } | ||
318 | |||
319 | if (has_input) { | ||
320 | printf(" +"); | ||
321 | } | ||
322 | |||
323 | has_input = 1; | ||
324 | |||
325 | if (coefficient == 1.0f) { | ||
326 | printf(" %s", srcname); | ||
327 | } else { | ||
328 | printf(" (%s * %.9ff)", srcname, coefficient); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | if (!has_input) { | ||
333 | printf(" 0.0f"); | ||
334 | } | ||
335 | |||
336 | printf(";\n"); | ||
337 | } | ||
338 | |||
339 | printf(" }\n"); | ||
340 | } else { | ||
341 | printf(" for (i = num_frames; i; i--, "); | ||
342 | if (fromchans == 1) { | ||
343 | printf("src++"); | ||
344 | } else { | ||
345 | printf("src += %d", fromchans); | ||
346 | } | ||
347 | printf(", "); | ||
348 | if (tochans == 1) { | ||
349 | printf("dst++"); | ||
350 | } else { | ||
351 | printf("dst += %d", tochans); | ||
352 | } | ||
353 | printf(") {\n"); | ||
354 | |||
355 | fptr = cvtmatrix; | ||
356 | for (i = 0; i < fromchans; i++) { | ||
357 | if (input_channel_used[i] > 1) { /* don't read it from src more than once. */ | ||
358 | printf(" const float src%s = src[%d];\n", channel_names[fromchans-1][i], i); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | for (j = 0; j < tochans; j++) { | ||
363 | int has_input = 0; | ||
364 | fptr = cvtmatrix + (fromchans * j); | ||
365 | printf(" dst[%d] /* %s */ =", j, channel_names[tochans-1][j]); | ||
366 | for (i = 0; i < fromchans; i++) { | ||
367 | const float coefficient = fptr[i]; | ||
368 | char srcname[32]; | ||
369 | if (coefficient == 0.0f) { | ||
370 | continue; | ||
371 | } else if (input_channel_used[i] > 1) { | ||
372 | snprintf(srcname, sizeof (srcname), "src%s", channel_names[fromchans-1][i]); | ||
373 | } else { | ||
374 | snprintf(srcname, sizeof (srcname), "src[%d]", i); | ||
375 | } | ||
376 | |||
377 | if (has_input) { | ||
378 | printf(" +"); | ||
379 | } | ||
380 | |||
381 | has_input = 1; | ||
382 | |||
383 | if (coefficient == 1.0f) { | ||
384 | printf(" %s", srcname); | ||
385 | } else { | ||
386 | printf(" (%s * %.9ff)", srcname, coefficient); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | if (!has_input) { | ||
391 | printf(" 0.0f"); | ||
392 | } | ||
393 | |||
394 | printf(";\n"); | ||
395 | } | ||
396 | printf(" }\n"); | ||
397 | } | ||
398 | |||
399 | printf("\n}\n\n"); | ||
400 | } | ||
401 | |||
402 | int main(void) | ||
403 | { | ||
404 | int ini, outi; | ||
405 | |||
406 | printf( | ||
407 | "/*\n" | ||
408 | " Simple DirectMedia Layer\n" | ||
409 | " Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>\n" | ||
410 | "\n" | ||
411 | " This software is provided 'as-is', without any express or implied\n" | ||
412 | " warranty. In no event will the authors be held liable for any damages\n" | ||
413 | " arising from the use of this software.\n" | ||
414 | "\n" | ||
415 | " Permission is granted to anyone to use this software for any purpose,\n" | ||
416 | " including commercial applications, and to alter it and redistribute it\n" | ||
417 | " freely, subject to the following restrictions:\n" | ||
418 | "\n" | ||
419 | " 1. The origin of this software must not be misrepresented; you must not\n" | ||
420 | " claim that you wrote the original software. If you use this software\n" | ||
421 | " in a product, an acknowledgment in the product documentation would be\n" | ||
422 | " appreciated but is not required.\n" | ||
423 | " 2. Altered source versions must be plainly marked as such, and must not be\n" | ||
424 | " misrepresented as being the original software.\n" | ||
425 | " 3. This notice may not be removed or altered from any source distribution.\n" | ||
426 | "*/\n" | ||
427 | "\n" | ||
428 | "// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c\n" | ||
429 | "\n" | ||
430 | "\n" | ||
431 | "typedef void (*SDL_AudioChannelConverter)(float *dst, const float *src, int num_frames);\n" | ||
432 | "\n" | ||
433 | ); | ||
434 | |||
435 | for (ini = 1; ini <= NUM_CHANNELS; ini++) { | ||
436 | for (outi = 1; outi <= NUM_CHANNELS; outi++) { | ||
437 | write_converter(ini, outi); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | printf("static const SDL_AudioChannelConverter channel_converters[%d][%d] = { /* [from][to] */\n", NUM_CHANNELS, NUM_CHANNELS); | ||
442 | for (ini = 1; ini <= NUM_CHANNELS; ini++) { | ||
443 | const char *comma = ""; | ||
444 | printf(" {"); | ||
445 | for (outi = 1; outi <= NUM_CHANNELS; outi++) { | ||
446 | const char *fromstr = layout_names[ini-1]; | ||
447 | const char *tostr = layout_names[outi-1]; | ||
448 | if (ini == outi) { | ||
449 | printf("%s NULL", comma); | ||
450 | } else { | ||
451 | printf("%s SDL_Convert%sTo%s", comma, remove_dots(fromstr), remove_dots(tostr)); | ||
452 | } | ||
453 | comma = ","; | ||
454 | } | ||
455 | printf(" }%s\n", (ini == NUM_CHANNELS) ? "" : ","); | ||
456 | } | ||
457 | |||
458 | printf("};\n\n"); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/git-pre-push-hook.pl b/src/contrib/SDL-3.2.20/build-scripts/git-pre-push-hook.pl new file mode 100755 index 0000000..63596b6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/git-pre-push-hook.pl | |||
@@ -0,0 +1,78 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | # To use this script: symlink it to .git/hooks/pre-push, then "git push" | ||
4 | # | ||
5 | # This script is called by "git push" after it has checked the remote status, | ||
6 | # but before anything has been pushed. If this script exits with a non-zero | ||
7 | # status nothing will be pushed. | ||
8 | # | ||
9 | # This hook is called with the following parameters: | ||
10 | # | ||
11 | # $1 -- Name of the remote to which the push is being done | ||
12 | # $2 -- URL to which the push is being done | ||
13 | # | ||
14 | # If pushing without using a named remote those arguments will be equal. | ||
15 | # | ||
16 | # Information about the commits which are being pushed is supplied as lines to | ||
17 | # the standard input in the form: | ||
18 | # | ||
19 | # <local ref> <local sha1> <remote ref> <remote sha1> | ||
20 | |||
21 | use warnings; | ||
22 | use strict; | ||
23 | |||
24 | my $remote = $ARGV[0]; | ||
25 | my $url = $ARGV[1]; | ||
26 | |||
27 | #print("remote: $remote\n"); | ||
28 | #print("url: $url\n"); | ||
29 | |||
30 | $url =~ s/\.git$//; # change myorg/myproject.git to myorg/myproject | ||
31 | $url =~ s#^git\@github\.com\:#https://github.com/#i; | ||
32 | my $commiturl = $url =~ /\Ahttps?:\/\/github.com\// ? "$url/commit/" : ''; | ||
33 | |||
34 | my $z40 = '0000000000000000000000000000000000000000'; | ||
35 | my $reported = 0; | ||
36 | |||
37 | while (<STDIN>) { | ||
38 | chomp; | ||
39 | my ($local_ref, $local_sha, $remote_ref, $remote_sha) = split / /; | ||
40 | #print("local_ref: $local_ref\n"); | ||
41 | #print("local_sha: $local_sha\n"); | ||
42 | #print("remote_ref: $remote_ref\n"); | ||
43 | #print("remote_sha: $remote_sha\n"); | ||
44 | |||
45 | my $range = ''; | ||
46 | if ($remote_sha eq $z40) { # New branch, examine all commits | ||
47 | $range = $local_sha; | ||
48 | } else { # Update to existing branch, examine new commits | ||
49 | $range = "$remote_sha..$local_sha"; | ||
50 | } | ||
51 | |||
52 | my $gitcmd = "git log --reverse --oneline --no-abbrev-commit '$range'"; | ||
53 | open(GITPIPE, '-|', $gitcmd) or die("\n\n$0: Failed to run '$gitcmd': $!\n\nAbort push!\n\n"); | ||
54 | while (<GITPIPE>) { | ||
55 | chomp; | ||
56 | if (/\A([a-fA-F0-9]+)\s+(.*?)\Z/) { | ||
57 | my $hash = $1; | ||
58 | my $msg = $2; | ||
59 | |||
60 | if (!$reported) { | ||
61 | print("\nCommits expected to be pushed:\n"); | ||
62 | $reported = 1; | ||
63 | } | ||
64 | |||
65 | #print("hash: $hash\n"); | ||
66 | #print("msg: $msg\n"); | ||
67 | |||
68 | print("$commiturl$hash -- $msg\n"); | ||
69 | } else { | ||
70 | die("$0: Unexpected output from '$gitcmd'!\n\nAbort push!\n\n"); | ||
71 | } | ||
72 | } | ||
73 | die("\n\n$0: Failing exit code from running '$gitcmd'!\n\nAbort push!\n\n") if !close(GITPIPE); | ||
74 | } | ||
75 | |||
76 | print("\n") if $reported; | ||
77 | |||
78 | exit(0); # Let the push go forward. | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/makecasefoldhashtable.pl b/src/contrib/SDL-3.2.20/build-scripts/makecasefoldhashtable.pl new file mode 100755 index 0000000..efe3534 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/makecasefoldhashtable.pl | |||
@@ -0,0 +1,322 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | # Simple DirectMedia Layer | ||
4 | # Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
5 | # | ||
6 | # This software is provided 'as-is', without any express or implied | ||
7 | # warranty. In no event will the authors be held liable for any damages | ||
8 | # arising from the use of this software. | ||
9 | # | ||
10 | # Permission is granted to anyone to use this software for any purpose, | ||
11 | # including commercial applications, and to alter it and redistribute it | ||
12 | # freely, subject to the following restrictions: | ||
13 | # | ||
14 | # 1. The origin of this software must not be misrepresented; you must not | ||
15 | # claim that you wrote the original software. If you use this software | ||
16 | # in a product, an acknowledgment in the product documentation would be | ||
17 | # appreciated but is not required. | ||
18 | # 2. Altered source versions must be plainly marked as such, and must not be | ||
19 | # misrepresented as being the original software. | ||
20 | # 3. This notice may not be removed or altered from any source distribution. | ||
21 | |||
22 | # This script was originally written by Ryan C. Gordon for PhysicsFS | ||
23 | # ( https://icculus.org/physfs/ ), under the zlib license: the same license | ||
24 | # that SDL itself uses). | ||
25 | |||
26 | use warnings; | ||
27 | use strict; | ||
28 | |||
29 | my $HASHBUCKETS1_16 = 256; | ||
30 | my $HASHBUCKETS1_32 = 16; | ||
31 | my $HASHBUCKETS2_16 = 16; | ||
32 | my $HASHBUCKETS3_16 = 4; | ||
33 | |||
34 | my $mem_used = 0; | ||
35 | |||
36 | print <<__EOF__; | ||
37 | /* | ||
38 | Simple DirectMedia Layer | ||
39 | Copyright (C) 1997-2025 Sam Lantinga <slouken\@libsdl.org> | ||
40 | |||
41 | This software is provided 'as-is', without any express or implied | ||
42 | warranty. In no event will the authors be held liable for any damages | ||
43 | arising from the use of this software. | ||
44 | |||
45 | Permission is granted to anyone to use this software for any purpose, | ||
46 | including commercial applications, and to alter it and redistribute it | ||
47 | freely, subject to the following restrictions: | ||
48 | |||
49 | 1. The origin of this software must not be misrepresented; you must not | ||
50 | claim that you wrote the original software. If you use this software | ||
51 | in a product, an acknowledgment in the product documentation would be | ||
52 | appreciated but is not required. | ||
53 | 2. Altered source versions must be plainly marked as such, and must not be | ||
54 | misrepresented as being the original software. | ||
55 | 3. This notice may not be removed or altered from any source distribution. | ||
56 | */ | ||
57 | |||
58 | /* | ||
59 | * This data was generated by SDL/build-scripts/makecasefoldhashtable.pl | ||
60 | * | ||
61 | * Do not manually edit this file! | ||
62 | */ | ||
63 | |||
64 | #ifndef SDL_casefolding_h_ | ||
65 | #define SDL_casefolding_h_ | ||
66 | |||
67 | /* We build three simple hashmaps here: one that maps Unicode codepoints to | ||
68 | a one, two, or three lowercase codepoints. To retrieve this info: look at | ||
69 | case_fold_hashX, where X is 1, 2, or 3. Most foldable codepoints fold to one, | ||
70 | a few dozen fold to two, and a handful fold to three. If the codepoint isn't | ||
71 | in any of these hashes, it doesn't fold (no separate upper and lowercase). | ||
72 | |||
73 | Almost all these codepoints fit into 16 bits, so we hash them as such to save | ||
74 | memory. If a codepoint is > 0xFFFF, we have separate hashes for them, | ||
75 | since there are (currently) only about 120 of them and (currently) all of them | ||
76 | map to a single lowercase codepoint. */ | ||
77 | |||
78 | typedef struct CaseFoldMapping1_32 | ||
79 | { | ||
80 | Uint32 from; | ||
81 | Uint32 to0; | ||
82 | } CaseFoldMapping1_32; | ||
83 | |||
84 | typedef struct CaseFoldMapping1_16 | ||
85 | { | ||
86 | Uint16 from; | ||
87 | Uint16 to0; | ||
88 | } CaseFoldMapping1_16; | ||
89 | |||
90 | typedef struct CaseFoldMapping2_16 | ||
91 | { | ||
92 | Uint16 from; | ||
93 | Uint16 to0; | ||
94 | Uint16 to1; | ||
95 | } CaseFoldMapping2_16; | ||
96 | |||
97 | typedef struct CaseFoldMapping3_16 | ||
98 | { | ||
99 | Uint16 from; | ||
100 | Uint16 to0; | ||
101 | Uint16 to1; | ||
102 | Uint16 to2; | ||
103 | } CaseFoldMapping3_16; | ||
104 | |||
105 | typedef struct CaseFoldHashBucket1_16 | ||
106 | { | ||
107 | const CaseFoldMapping1_16 *list; | ||
108 | const Uint8 count; | ||
109 | } CaseFoldHashBucket1_16; | ||
110 | |||
111 | typedef struct CaseFoldHashBucket1_32 | ||
112 | { | ||
113 | const CaseFoldMapping1_32 *list; | ||
114 | const Uint8 count; | ||
115 | } CaseFoldHashBucket1_32; | ||
116 | |||
117 | typedef struct CaseFoldHashBucket2_16 | ||
118 | { | ||
119 | const CaseFoldMapping2_16 *list; | ||
120 | const Uint8 count; | ||
121 | } CaseFoldHashBucket2_16; | ||
122 | |||
123 | typedef struct CaseFoldHashBucket3_16 | ||
124 | { | ||
125 | const CaseFoldMapping3_16 *list; | ||
126 | const Uint8 count; | ||
127 | } CaseFoldHashBucket3_16; | ||
128 | |||
129 | __EOF__ | ||
130 | |||
131 | |||
132 | my @foldPairs1_16; | ||
133 | my @foldPairs2_16; | ||
134 | my @foldPairs3_16; | ||
135 | my @foldPairs1_32; | ||
136 | |||
137 | for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) { | ||
138 | $foldPairs1_16[$i] = ''; | ||
139 | } | ||
140 | |||
141 | for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) { | ||
142 | $foldPairs1_32[$i] = ''; | ||
143 | } | ||
144 | |||
145 | for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) { | ||
146 | $foldPairs2_16[$i] = ''; | ||
147 | } | ||
148 | |||
149 | for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) { | ||
150 | $foldPairs3_16[$i] = ''; | ||
151 | } | ||
152 | |||
153 | open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n"); | ||
154 | while (<FH>) { | ||
155 | chomp; | ||
156 | # strip comments from textfile... | ||
157 | s/\#.*\Z//; | ||
158 | |||
159 | # strip whitespace... | ||
160 | s/\A\s+//; | ||
161 | s/\s+\Z//; | ||
162 | |||
163 | next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/; | ||
164 | my ($code, $status, $mapping) = ($1, $2, $3); | ||
165 | |||
166 | my $hexxed = hex($code); | ||
167 | #print("// code '$code' status '$status' mapping '$mapping'\n"); | ||
168 | |||
169 | if (($status eq 'C') or ($status eq 'F')) { | ||
170 | my ($map1, $map2, $map3) = (undef, undef, undef); | ||
171 | $map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//; | ||
172 | $map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//; | ||
173 | $map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//; | ||
174 | die("mapping space too small for '$code'\n") if ($mapping ne ''); | ||
175 | die("problem parsing mapping for '$code'\n") if (not defined($map1)); | ||
176 | |||
177 | if ($hexxed < 128) { | ||
178 | # Just ignore these, we'll handle the low-ASCII ones ourselves. | ||
179 | } elsif ($hexxed > 0xFFFF) { | ||
180 | # We just need to add the 32-bit 2 and/or 3 codepoint maps if this die()'s here. | ||
181 | die("Uhoh, a codepoint > 0xFFFF that folds to multiple codepoints! Fixme.") if defined($map2); | ||
182 | my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_32-1)); | ||
183 | #print("// hexxed '$hexxed' hashed1 '$hashed'\n"); | ||
184 | $foldPairs1_32[$hashed] .= " { 0x$code, 0x$map1 },\n"; | ||
185 | $mem_used += 8; | ||
186 | } elsif (not defined($map2)) { | ||
187 | my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_16-1)); | ||
188 | #print("// hexxed '$hexxed' hashed1 '$hashed'\n"); | ||
189 | $foldPairs1_16[$hashed] .= " { 0x$code, 0x$map1 },\n"; | ||
190 | $mem_used += 4; | ||
191 | } elsif (not defined($map3)) { | ||
192 | my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS2_16-1)); | ||
193 | #print("// hexxed '$hexxed' hashed2 '$hashed'\n"); | ||
194 | $foldPairs2_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2 },\n"; | ||
195 | $mem_used += 6; | ||
196 | } else { | ||
197 | my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS3_16-1)); | ||
198 | #print("// hexxed '$hexxed' hashed3 '$hashed'\n"); | ||
199 | $foldPairs3_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n"; | ||
200 | $mem_used += 8; | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | close(FH); | ||
205 | |||
206 | for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) { | ||
207 | $foldPairs1_16[$i] =~ s/,\n\Z//; | ||
208 | my $str = $foldPairs1_16[$i]; | ||
209 | next if $str eq ''; | ||
210 | my $num = '000' . $i; | ||
211 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
212 | my $sym = "case_fold1_16_${num}"; | ||
213 | print("static const CaseFoldMapping1_16 ${sym}[] = {\n$str\n};\n\n"); | ||
214 | } | ||
215 | |||
216 | for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) { | ||
217 | $foldPairs1_32[$i] =~ s/,\n\Z//; | ||
218 | my $str = $foldPairs1_32[$i]; | ||
219 | next if $str eq ''; | ||
220 | my $num = '000' . $i; | ||
221 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
222 | my $sym = "case_fold1_32_${num}"; | ||
223 | print("static const CaseFoldMapping1_32 ${sym}[] = {\n$str\n};\n\n"); | ||
224 | } | ||
225 | |||
226 | for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) { | ||
227 | $foldPairs2_16[$i] =~ s/,\n\Z//; | ||
228 | my $str = $foldPairs2_16[$i]; | ||
229 | next if $str eq ''; | ||
230 | my $num = '000' . $i; | ||
231 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
232 | my $sym = "case_fold2_16_${num}"; | ||
233 | print("static const CaseFoldMapping2_16 ${sym}[] = {\n$str\n};\n\n"); | ||
234 | } | ||
235 | |||
236 | for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) { | ||
237 | $foldPairs3_16[$i] =~ s/,\n\Z//; | ||
238 | my $str = $foldPairs3_16[$i]; | ||
239 | next if $str eq ''; | ||
240 | my $num = '000' . $i; | ||
241 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
242 | my $sym = "case_fold3_16_${num}"; | ||
243 | print("static const CaseFoldMapping3_16 ${sym}[] = {\n$str\n};\n\n"); | ||
244 | } | ||
245 | |||
246 | print("static const CaseFoldHashBucket1_16 case_fold_hash1_16[] = {\n"); | ||
247 | |||
248 | for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) { | ||
249 | my $str = $foldPairs1_16[$i]; | ||
250 | if ($str eq '') { | ||
251 | print(" { NULL, 0 },\n"); | ||
252 | } else { | ||
253 | my $num = '000' . $i; | ||
254 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
255 | my $sym = "case_fold1_16_${num}"; | ||
256 | print(" { $sym, SDL_arraysize($sym) },\n"); | ||
257 | } | ||
258 | $mem_used += 12; | ||
259 | } | ||
260 | print("};\n\n"); | ||
261 | |||
262 | |||
263 | print("static const CaseFoldHashBucket1_32 case_fold_hash1_32[] = {\n"); | ||
264 | |||
265 | for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) { | ||
266 | my $str = $foldPairs1_32[$i]; | ||
267 | if ($str eq '') { | ||
268 | print(" { NULL, 0 },\n"); | ||
269 | } else { | ||
270 | my $num = '000' . $i; | ||
271 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
272 | my $sym = "case_fold1_32_${num}"; | ||
273 | print(" { $sym, SDL_arraysize($sym) },\n"); | ||
274 | } | ||
275 | $mem_used += 12; | ||
276 | } | ||
277 | print("};\n\n"); | ||
278 | |||
279 | |||
280 | print("static const CaseFoldHashBucket2_16 case_fold_hash2_16[] = {\n"); | ||
281 | |||
282 | for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) { | ||
283 | my $str = $foldPairs2_16[$i]; | ||
284 | if ($str eq '') { | ||
285 | print(" { NULL, 0 },\n"); | ||
286 | } else { | ||
287 | my $num = '000' . $i; | ||
288 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
289 | my $sym = "case_fold2_16_${num}"; | ||
290 | print(" { $sym, SDL_arraysize($sym) },\n"); | ||
291 | } | ||
292 | $mem_used += 12; | ||
293 | } | ||
294 | print("};\n\n"); | ||
295 | |||
296 | print("static const CaseFoldHashBucket3_16 case_fold_hash3_16[] = {\n"); | ||
297 | |||
298 | for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) { | ||
299 | my $str = $foldPairs3_16[$i]; | ||
300 | if ($str eq '') { | ||
301 | print(" { NULL, 0 },\n"); | ||
302 | } else { | ||
303 | my $num = '000' . $i; | ||
304 | $num =~ s/\A.*?(\d\d\d)\Z/$1/; | ||
305 | my $sym = "case_fold3_16_${num}"; | ||
306 | print(" { $sym, SDL_arraysize($sym) },\n"); | ||
307 | } | ||
308 | $mem_used += 12; | ||
309 | } | ||
310 | print("};\n\n"); | ||
311 | |||
312 | print <<__EOF__; | ||
313 | #endif /* SDL_casefolding_h_ */ | ||
314 | |||
315 | __EOF__ | ||
316 | |||
317 | print STDERR "Memory required for case-folding hashtable: $mem_used bytes\n"; | ||
318 | |||
319 | exit 0; | ||
320 | |||
321 | # end of makecashfoldhashtable.pl ... | ||
322 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/mkinstalldirs b/src/contrib/SDL-3.2.20/build-scripts/mkinstalldirs new file mode 100755 index 0000000..c364f3d --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/mkinstalldirs | |||
@@ -0,0 +1,162 @@ | |||
1 | #! /bin/sh | ||
2 | # mkinstalldirs --- make directory hierarchy | ||
3 | |||
4 | scriptversion=2020-07-26.22; # UTC | ||
5 | |||
6 | # Original author: Noah Friedman <friedman@prep.ai.mit.edu> | ||
7 | # Created: 1993-05-16 | ||
8 | # Public domain. | ||
9 | # | ||
10 | # This file is maintained in Automake, please report | ||
11 | # bugs to <bug-automake@gnu.org> or send patches to | ||
12 | # <automake-patches@gnu.org>. | ||
13 | |||
14 | nl=' | ||
15 | ' | ||
16 | IFS=" "" $nl" | ||
17 | errstatus=0 | ||
18 | dirmode= | ||
19 | |||
20 | usage="\ | ||
21 | Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... | ||
22 | |||
23 | Create each directory DIR (with mode MODE, if specified), including all | ||
24 | leading file name components. | ||
25 | |||
26 | Report bugs to <bug-automake@gnu.org>." | ||
27 | |||
28 | # process command line arguments | ||
29 | while test $# -gt 0 ; do | ||
30 | case $1 in | ||
31 | -h | --help | --h*) # -h for help | ||
32 | echo "$usage" | ||
33 | exit $? | ||
34 | ;; | ||
35 | -m) # -m PERM arg | ||
36 | shift | ||
37 | test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } | ||
38 | dirmode=$1 | ||
39 | shift | ||
40 | ;; | ||
41 | --version) | ||
42 | echo "$0 $scriptversion" | ||
43 | exit $? | ||
44 | ;; | ||
45 | --) # stop option processing | ||
46 | shift | ||
47 | break | ||
48 | ;; | ||
49 | -*) # unknown option | ||
50 | echo "$usage" 1>&2 | ||
51 | exit 1 | ||
52 | ;; | ||
53 | *) # first non-opt arg | ||
54 | break | ||
55 | ;; | ||
56 | esac | ||
57 | done | ||
58 | |||
59 | for file | ||
60 | do | ||
61 | if test -d "$file"; then | ||
62 | shift | ||
63 | else | ||
64 | break | ||
65 | fi | ||
66 | done | ||
67 | |||
68 | case $# in | ||
69 | 0) exit 0 ;; | ||
70 | esac | ||
71 | |||
72 | # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and | ||
73 | # mkdir -p a/c at the same time, both will detect that a is missing, | ||
74 | # one will create a, then the other will try to create a and die with | ||
75 | # a "File exists" error. This is a problem when calling mkinstalldirs | ||
76 | # from a parallel make. We use --version in the probe to restrict | ||
77 | # ourselves to GNU mkdir, which is thread-safe. | ||
78 | case $dirmode in | ||
79 | '') | ||
80 | if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then | ||
81 | echo "mkdir -p -- $*" | ||
82 | exec mkdir -p -- "$@" | ||
83 | else | ||
84 | # On NextStep and OpenStep, the 'mkdir' command does not | ||
85 | # recognize any option. It will interpret all options as | ||
86 | # directories to create, and then abort because '.' already | ||
87 | # exists. | ||
88 | test -d ./-p && rmdir ./-p | ||
89 | test -d ./--version && rmdir ./--version | ||
90 | fi | ||
91 | ;; | ||
92 | *) | ||
93 | if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && | ||
94 | test ! -d ./--version; then | ||
95 | echo "umask 22" | ||
96 | umask 22 | ||
97 | echo "mkdir -m $dirmode -p -- $*" | ||
98 | exec mkdir -m "$dirmode" -p -- "$@" | ||
99 | else | ||
100 | # Clean up after NextStep and OpenStep mkdir. | ||
101 | for d in ./-m ./-p ./--version "./$dirmode"; | ||
102 | do | ||
103 | test -d $d && rmdir $d | ||
104 | done | ||
105 | fi | ||
106 | ;; | ||
107 | esac | ||
108 | |||
109 | echo "umask 22" | ||
110 | umask 22 | ||
111 | |||
112 | for file | ||
113 | do | ||
114 | case $file in | ||
115 | /*) pathcomp=/ ;; | ||
116 | *) pathcomp= ;; | ||
117 | esac | ||
118 | oIFS=$IFS | ||
119 | IFS=/ | ||
120 | set fnord $file | ||
121 | shift | ||
122 | IFS=$oIFS | ||
123 | |||
124 | for d | ||
125 | do | ||
126 | test "x$d" = x && continue | ||
127 | |||
128 | pathcomp=$pathcomp$d | ||
129 | case $pathcomp in | ||
130 | -*) pathcomp=./$pathcomp ;; | ||
131 | esac | ||
132 | |||
133 | if test ! -d "$pathcomp"; then | ||
134 | echo "mkdir $pathcomp" | ||
135 | |||
136 | mkdir "$pathcomp" || lasterr=$? | ||
137 | |||
138 | if test ! -d "$pathcomp"; then | ||
139 | errstatus=$lasterr | ||
140 | fi | ||
141 | fi | ||
142 | |||
143 | pathcomp=$pathcomp/ | ||
144 | done | ||
145 | |||
146 | if test ! -z "$dirmode"; then | ||
147 | echo "chmod $dirmode $file" | ||
148 | chmod "$dirmode" "$file" || errstatus=$? | ||
149 | fi | ||
150 | done | ||
151 | |||
152 | exit $errstatus | ||
153 | |||
154 | # Local Variables: | ||
155 | # mode: shell-script | ||
156 | # sh-indentation: 2 | ||
157 | # eval: (add-hook 'before-save-hook 'time-stamp) | ||
158 | # time-stamp-start: "scriptversion=" | ||
159 | # time-stamp-format: "%:y-%02m-%02d.%02H" | ||
160 | # time-stamp-time-zone: "UTC0" | ||
161 | # time-stamp-end: "; # UTC" | ||
162 | # End: | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/INSTALL.md.in new file mode 100644 index 0000000..80321c2 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/INSTALL.md.in | |||
@@ -0,0 +1,91 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for the Android platform. | ||
5 | |||
6 | ## Gradle integration | ||
7 | |||
8 | For integration with CMake/ndk-build, it uses [prefab](https://google.github.io/prefab/). | ||
9 | |||
10 | Copy the aar archive (@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar) to a `app/libs` directory of your project. | ||
11 | |||
12 | In `app/build.gradle` of your Android project, add: | ||
13 | ``` | ||
14 | android { | ||
15 | /* ... */ | ||
16 | buildFeatures { | ||
17 | prefab true | ||
18 | } | ||
19 | } | ||
20 | dependencies { | ||
21 | implementation files('libs/@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar') | ||
22 | /* ... */ | ||
23 | } | ||
24 | ``` | ||
25 | |||
26 | If you're using CMake, add the following to your CMakeLists.txt: | ||
27 | ``` | ||
28 | find_package(@<@PROJECT_NAME@>@ REQUIRED CONFIG) | ||
29 | target_link_libraries(yourgame PRIVATE @<@PROJECT_NAME@>@::@<@PROJECT_NAME@>@) | ||
30 | ``` | ||
31 | |||
32 | If you use ndk-build, add the following before `include $(BUILD_SHARED_LIBRARY)` to your `Android.mk`: | ||
33 | ``` | ||
34 | LOCAL_SHARED_LIBARARIES := SDL3 SDL3-Headers | ||
35 | ``` | ||
36 | And add the following at the bottom: | ||
37 | ``` | ||
38 | # https://google.github.io/prefab/build-systems.html | ||
39 | |||
40 | # Add the prefab modules to the import path. | ||
41 | $(call import-add-path,/out) | ||
42 | |||
43 | # Import @<@PROJECT_NAME@>@ so we can depend on it. | ||
44 | $(call import-module,prefab/@<@PROJECT_NAME@>@) | ||
45 | ``` | ||
46 | |||
47 | --- | ||
48 | |||
49 | ## Other build systems (advanced) | ||
50 | |||
51 | If you want to build a project without Gradle, | ||
52 | running the following command will extract the Android archive into a more common directory structure. | ||
53 | ``` | ||
54 | python @<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar -o android_prefix | ||
55 | ``` | ||
56 | Add `--help` for a list of all available options. | ||
57 | |||
58 | # Documentation | ||
59 | |||
60 | An API reference, tutorials, and additional documentation is available at: | ||
61 | |||
62 | https://wiki.libsdl.org/@<@PROJECT_NAME@>@ | ||
63 | |||
64 | # Example code | ||
65 | |||
66 | There are simple example programs available at: | ||
67 | |||
68 | https://examples.libsdl.org/SDL3 | ||
69 | |||
70 | # Discussions | ||
71 | |||
72 | ## Discord | ||
73 | |||
74 | You can join the official Discord server at: | ||
75 | |||
76 | https://discord.com/invite/BwpFGBWsv8 | ||
77 | |||
78 | ## Forums/mailing lists | ||
79 | |||
80 | You can join SDL development discussions at: | ||
81 | |||
82 | https://discourse.libsdl.org/ | ||
83 | |||
84 | Once you sign up, you can use the forum through the website or as a mailing list from your email client. | ||
85 | |||
86 | ## Announcement list | ||
87 | |||
88 | You can sign up for the low traffic announcement list at: | ||
89 | |||
90 | https://www.libsdl.org/mailing-list.php | ||
91 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/__main__.py.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/__main__.py.in new file mode 100755 index 0000000..344cf71 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/__main__.py.in | |||
@@ -0,0 +1,104 @@ | |||
1 | #!/usr/bin/env python | ||
2 | |||
3 | """ | ||
4 | Create a @<@PROJECT_NAME@>@ SDK prefix from an Android archive | ||
5 | This file is meant to be placed in a the root of an android .aar archive | ||
6 | |||
7 | Example usage: | ||
8 | ```sh | ||
9 | python @<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar -o /usr/opt/android-sdks | ||
10 | cmake -S my-project \ | ||
11 | -DCMAKE_PREFIX_PATH=/usr/opt/android-sdks \ | ||
12 | -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ | ||
13 | -B build-arm64 -DANDROID_ABI=arm64-v8a \ | ||
14 | -DCMAKE_BUILD_TYPE=Releaase | ||
15 | cmake --build build-arm64 | ||
16 | ``` | ||
17 | """ | ||
18 | import argparse | ||
19 | import io | ||
20 | import json | ||
21 | import os | ||
22 | import pathlib | ||
23 | import re | ||
24 | import stat | ||
25 | import zipfile | ||
26 | |||
27 | |||
28 | AAR_PATH = pathlib.Path(__file__).resolve().parent | ||
29 | ANDROID_ARCHS = { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } | ||
30 | |||
31 | |||
32 | def main(): | ||
33 | parser = argparse.ArgumentParser( | ||
34 | description="Convert a @<@PROJECT_NAME@>@ Android .aar archive into a SDK", | ||
35 | allow_abbrev=False, | ||
36 | ) | ||
37 | parser.add_argument("--version", action="version", version="@<@PROJECT_NAME@>@ @<@PROJECT_VERSION@>@") | ||
38 | parser.add_argument("-o", dest="output", type=pathlib.Path, required=True, help="Folder where to store the SDK") | ||
39 | args = parser.parse_args() | ||
40 | |||
41 | print(f"Creating a @<@PROJECT_NAME@>@ SDK at {args.output}...") | ||
42 | |||
43 | prefix = args.output | ||
44 | incdir = prefix / "include" | ||
45 | libdir = prefix / "lib" | ||
46 | |||
47 | RE_LIB_MODULE_ARCH = re.compile(r"prefab/modules/(?P<module>[A-Za-z0-9_-]+)/libs/android\.(?P<arch>[a-zA-Z0-9_-]+)/(?P<filename>lib[A-Za-z0-9_]+\.(?:so|a))") | ||
48 | RE_INC_MODULE_ARCH = re.compile(r"prefab/modules/(?P<module>[A-Za-z0-9_-]+)/include/(?P<header>[a-zA-Z0-9_./-]+)") | ||
49 | RE_LICENSE = re.compile(r"(?:.*/)?(?P<filename>(?:license|copying)(?:\.md|\.txt)?)", flags=re.I) | ||
50 | RE_PROGUARD = re.compile(r"(?:.*/)?(?P<filename>proguard.*\.(?:pro|txt))", flags=re.I) | ||
51 | RE_CMAKE = re.compile(r"(?:.*/)?(?P<filename>.*\.cmake)", flags=re.I) | ||
52 | |||
53 | with zipfile.ZipFile(AAR_PATH) as zf: | ||
54 | project_description = json.loads(zf.read("description.json")) | ||
55 | project_name = project_description["name"] | ||
56 | project_version = project_description["version"] | ||
57 | licensedir = prefix / "share/licenses" / project_name | ||
58 | cmakedir = libdir / "cmake" / project_name | ||
59 | javadir = prefix / "share/java" / project_name | ||
60 | javadocdir = prefix / "share/javadoc" / project_name | ||
61 | |||
62 | def read_zipfile_and_write(path: pathlib.Path, zippath: str): | ||
63 | data = zf.read(zippath) | ||
64 | path.parent.mkdir(parents=True, exist_ok=True) | ||
65 | path.write_bytes(data) | ||
66 | |||
67 | for zip_info in zf.infolist(): | ||
68 | zippath = zip_info.filename | ||
69 | if m := RE_LIB_MODULE_ARCH.match(zippath): | ||
70 | lib_path = libdir / m["arch"] / m["filename"] | ||
71 | read_zipfile_and_write(lib_path, zippath) | ||
72 | if m["filename"].endswith(".so"): | ||
73 | os.chmod(lib_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) | ||
74 | |||
75 | elif m := RE_INC_MODULE_ARCH.match(zippath): | ||
76 | header_path = incdir / m["header"] | ||
77 | read_zipfile_and_write(header_path, zippath) | ||
78 | elif m:= RE_LICENSE.match(zippath): | ||
79 | license_path = licensedir / m["filename"] | ||
80 | read_zipfile_and_write(license_path, zippath) | ||
81 | elif m:= RE_PROGUARD.match(zippath): | ||
82 | proguard_path = javadir / m["filename"] | ||
83 | read_zipfile_and_write(proguard_path, zippath) | ||
84 | elif m:= RE_CMAKE.match(zippath): | ||
85 | cmake_path = cmakedir / m["filename"] | ||
86 | read_zipfile_and_write(cmake_path, zippath) | ||
87 | elif zippath == "classes.jar": | ||
88 | versioned_jar_path = javadir / f"{project_name}-{project_version}.jar" | ||
89 | unversioned_jar_path = javadir / f"{project_name}.jar" | ||
90 | read_zipfile_and_write(versioned_jar_path, zippath) | ||
91 | os.symlink(src=versioned_jar_path.name, dst=unversioned_jar_path) | ||
92 | elif zippath == "classes-sources.jar": | ||
93 | jarpath = javadir / f"{project_name}-{project_version}-sources.jar" | ||
94 | read_zipfile_and_write(jarpath, zippath) | ||
95 | elif zippath == "classes-doc.jar": | ||
96 | jarpath = javadocdir / f"{project_name}-{project_version}-javadoc.jar" | ||
97 | read_zipfile_and_write(jarpath, zippath) | ||
98 | |||
99 | print("... done") | ||
100 | return 0 | ||
101 | |||
102 | |||
103 | if __name__ == "__main__": | ||
104 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in new file mode 100644 index 0000000..3268da7 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in | |||
@@ -0,0 +1,38 @@ | |||
1 | # @<@PROJECT_NAME@>@ CMake version configuration file: | ||
2 | # This file is meant to be placed in a lib/cmake/@<@PROJECT_NAME@>@ subfolder of a reconstructed Android SDL3 SDK | ||
3 | |||
4 | set(PACKAGE_VERSION "@<@PROJECT_VERSION@>@") | ||
5 | |||
6 | if(PACKAGE_FIND_VERSION_RANGE) | ||
7 | # Package version must be in the requested version range | ||
8 | if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) | ||
9 | OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) | ||
10 | OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) | ||
11 | set(PACKAGE_VERSION_COMPATIBLE FALSE) | ||
12 | else() | ||
13 | set(PACKAGE_VERSION_COMPATIBLE TRUE) | ||
14 | endif() | ||
15 | else() | ||
16 | if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) | ||
17 | set(PACKAGE_VERSION_COMPATIBLE FALSE) | ||
18 | else() | ||
19 | set(PACKAGE_VERSION_COMPATIBLE TRUE) | ||
20 | if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) | ||
21 | set(PACKAGE_VERSION_EXACT TRUE) | ||
22 | endif() | ||
23 | endif() | ||
24 | endif() | ||
25 | |||
26 | # if the using project doesn't have CMAKE_SIZEOF_VOID_P set, fail. | ||
27 | if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") | ||
28 | set(PACKAGE_VERSION_UNSUITABLE TRUE) | ||
29 | endif() | ||
30 | |||
31 | include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake") | ||
32 | SDL_DetectTargetCPUArchitectures(_detected_archs) | ||
33 | |||
34 | # check that the installed version has a compatible architecture as the one which is currently searching: | ||
35 | if(NOT(SDL_CPU_X86 OR SDL_CPU_X64 OR SDL_CPU_ARM32 OR SDL_CPU_ARM64)) | ||
36 | set(PACKAGE_VERSION "${PACKAGE_VERSION} (X86,X64,ARM32,ARM64)") | ||
37 | set(PACKAGE_VERSION_UNSUITABLE TRUE) | ||
38 | endif() | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/description.json.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/description.json.in new file mode 100644 index 0000000..e75ef38 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/android/aar/description.json.in | |||
@@ -0,0 +1,5 @@ | |||
1 | { | ||
2 | "name": "@<@PROJECT_NAME@>@", | ||
3 | "version": "@<@PROJECT_VERSION@>@", | ||
4 | "git-hash": "@<@PROJECT_COMMIT@>@" | ||
5 | } | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/INSTALL.md.in new file mode 100644 index 0000000..f1a6a78 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/INSTALL.md.in | |||
@@ -0,0 +1,53 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for the mingw-w64 toolchain. | ||
5 | |||
6 | The files for 32-bit architecture are in i686-w64-mingw32 | ||
7 | The files for 64-bit architecture are in x86_64-w64-mingw32 | ||
8 | |||
9 | You can install them to another location, just type `make` for help. | ||
10 | |||
11 | To use this package, point your include path at _arch_/include and your library path at _arch_/lib, link with the @<@PROJECT_NAME@>@ library and copy _arch_/bin/@<@PROJECT_NAME@>@.dll next to your executable. | ||
12 | |||
13 | e.g. | ||
14 | ```sh | ||
15 | gcc -o hello.exe hello.c -Ix86_64-w64-mingw32/include -Lx86_64-w64-mingw32/lib -l@<@PROJECT_NAME@>@ | ||
16 | cp x86_64-w64-mingw32/bin/@<@PROJECT_NAME@>@.dll . | ||
17 | ./hello.exe | ||
18 | ``` | ||
19 | |||
20 | # Documentation | ||
21 | |||
22 | An API reference, tutorials, and additional documentation is available at: | ||
23 | |||
24 | https://wiki.libsdl.org/@<@PROJECT_NAME@>@ | ||
25 | |||
26 | # Example code | ||
27 | |||
28 | There are simple example programs available at: | ||
29 | |||
30 | https://examples.libsdl.org/SDL3 | ||
31 | |||
32 | # Discussions | ||
33 | |||
34 | ## Discord | ||
35 | |||
36 | You can join the official Discord server at: | ||
37 | |||
38 | https://discord.com/invite/BwpFGBWsv8 | ||
39 | |||
40 | ## Forums/mailing lists | ||
41 | |||
42 | You can join SDL development discussions at: | ||
43 | |||
44 | https://discourse.libsdl.org/ | ||
45 | |||
46 | Once you sign up, you can use the forum through the website or as a mailing list from your email client. | ||
47 | |||
48 | ## Announcement list | ||
49 | |||
50 | You can sign up for the low traffic announcement list at: | ||
51 | |||
52 | https://www.libsdl.org/mailing-list.php | ||
53 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/Makefile b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/Makefile new file mode 100644 index 0000000..9b6cd55 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/mingw/Makefile | |||
@@ -0,0 +1,39 @@ | |||
1 | # | ||
2 | # Makefile for installing the mingw32 version of the SDL library | ||
3 | |||
4 | DESTDIR = /usr/local | ||
5 | ARCHITECTURES := i686-w64-mingw32 x86_64-w64-mingw32 | ||
6 | |||
7 | default: | ||
8 | @echo "Run \"make install-i686\" to install 32-bit" | ||
9 | @echo "Run \"make install-x86_64\" to install 64-bit" | ||
10 | @echo "Run \"make install-all\" to install both" | ||
11 | @echo "Add DESTDIR=/custom/path to change the destination folder" | ||
12 | |||
13 | install: | ||
14 | @if test -d $(ARCH) && test -d $(DESTDIR); then \ | ||
15 | (cd $(ARCH) && cp -rv bin include lib share $(DESTDIR)/); \ | ||
16 | else \ | ||
17 | echo "*** ERROR: $(ARCH) or $(DESTDIR) does not exist!"; \ | ||
18 | exit 1; \ | ||
19 | fi | ||
20 | |||
21 | install-i686: | ||
22 | $(MAKE) install ARCH=i686-w64-mingw32 | ||
23 | |||
24 | install-x86_64: | ||
25 | $(MAKE) install ARCH=x86_64-w64-mingw32 | ||
26 | |||
27 | install-all: | ||
28 | @if test -d $(DESTDIR); then \ | ||
29 | mkdir -p $(DESTDIR)/cmake; \ | ||
30 | cp -rv cmake/* $(DESTDIR)/cmake; \ | ||
31 | for arch in $(ARCHITECTURES); do \ | ||
32 | $(MAKE) install ARCH=$$arch DESTDIR=$(DESTDIR)/$$arch; \ | ||
33 | done \ | ||
34 | else \ | ||
35 | echo "*** ERROR: $(DESTDIR) does not exist!"; \ | ||
36 | exit 1; \ | ||
37 | fi | ||
38 | |||
39 | .PHONY: default install install-i686 install-x86_64 install-all | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/Directory.Build.props b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/Directory.Build.props new file mode 100644 index 0000000..24033f4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/Directory.Build.props | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
3 | <ItemDefinitionGroup> | ||
4 | <ClCompile> | ||
5 | <PreprocessorDefinitions>SDL_VENDOR_INFO="libsdl.org";%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
6 | </ClCompile> | ||
7 | </ItemDefinitionGroup> | ||
8 | </Project> | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/INSTALL.md.in new file mode 100644 index 0000000..671f524 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/INSTALL.md.in | |||
@@ -0,0 +1,45 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for Visual Studio. | ||
5 | |||
6 | To use this package, edit your project properties: | ||
7 | - Add the include directory to "VC++ Directories" -> "Include Directories" | ||
8 | - Add the lib/_arch_ directory to "VC++ Directories" -> "Library Directories" | ||
9 | - Add @<@PROJECT_NAME@>@.lib to Linker -> Input -> "Additional Dependencies" | ||
10 | - Copy lib/_arch_/@<@PROJECT_NAME@>@.dll to your project directory. | ||
11 | |||
12 | # Documentation | ||
13 | |||
14 | An API reference, tutorials, and additional documentation is available at: | ||
15 | |||
16 | https://wiki.libsdl.org/@<@PROJECT_NAME@>@ | ||
17 | |||
18 | # Example code | ||
19 | |||
20 | There are simple example programs available at: | ||
21 | |||
22 | https://examples.libsdl.org/SDL3 | ||
23 | |||
24 | # Discussions | ||
25 | |||
26 | ## Discord | ||
27 | |||
28 | You can join the official Discord server at: | ||
29 | |||
30 | https://discord.com/invite/BwpFGBWsv8 | ||
31 | |||
32 | ## Forums/mailing lists | ||
33 | |||
34 | You can join SDL development discussions at: | ||
35 | |||
36 | https://discourse.libsdl.org/ | ||
37 | |||
38 | Once you sign up, you can use the forum through the website or as a mailing list from your email client. | ||
39 | |||
40 | ## Announcement list | ||
41 | |||
42 | You can sign up for the low traffic announcement list at: | ||
43 | |||
44 | https://www.libsdl.org/mailing-list.php | ||
45 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/arm64/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/arm64/INSTALL.md.in new file mode 100644 index 0000000..c185171 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/arm64/INSTALL.md.in | |||
@@ -0,0 +1,13 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for arm64 Windows. | ||
5 | |||
6 | To use this package, simply replace an existing 64-bit ARM @<@PROJECT_NAME@>@.dll with the one included here. | ||
7 | |||
8 | # Development packages | ||
9 | |||
10 | If you're looking for packages with headers and libraries, you can download one of these: | ||
11 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip, for development using Visual Studio | ||
12 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-mingw.zip, for development using mingw-w64 | ||
13 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in new file mode 100644 index 0000000..6387376 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in | |||
@@ -0,0 +1,135 @@ | |||
1 | # @<@PROJECT_NAME@>@ CMake configuration file: | ||
2 | # This file is meant to be placed in a cmake subfolder of @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip | ||
3 | |||
4 | cmake_minimum_required(VERSION 3.0...3.28) | ||
5 | |||
6 | include(FeatureSummary) | ||
7 | set_package_properties(SDL3 PROPERTIES | ||
8 | URL "https://www.libsdl.org/" | ||
9 | DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware" | ||
10 | ) | ||
11 | |||
12 | # Copied from `configure_package_config_file` | ||
13 | macro(set_and_check _var _file) | ||
14 | set(${_var} "${_file}") | ||
15 | if(NOT EXISTS "${_file}") | ||
16 | message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") | ||
17 | endif() | ||
18 | endmacro() | ||
19 | |||
20 | # Copied from `configure_package_config_file` | ||
21 | macro(check_required_components _NAME) | ||
22 | foreach(comp ${${_NAME}_FIND_COMPONENTS}) | ||
23 | if(NOT ${_NAME}_${comp}_FOUND) | ||
24 | if(${_NAME}_FIND_REQUIRED_${comp}) | ||
25 | set(${_NAME}_FOUND FALSE) | ||
26 | endif() | ||
27 | endif() | ||
28 | endforeach() | ||
29 | endmacro() | ||
30 | |||
31 | set(SDL3_FOUND TRUE) | ||
32 | |||
33 | if(SDL_CPU_X86) | ||
34 | set(_sdl_arch_subdir "x86") | ||
35 | elseif(SDL_CPU_X64 OR SDL_CPU_ARM64EC) | ||
36 | set(_sdl_arch_subdir "x64") | ||
37 | elseif(SDL_CPU_ARM64) | ||
38 | set(_sdl_arch_subdir "arm64") | ||
39 | else() | ||
40 | set(SDL3_FOUND FALSE) | ||
41 | return() | ||
42 | endif() | ||
43 | |||
44 | get_filename_component(_sdl3_prefix "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) | ||
45 | set_and_check(_sdl3_prefix "${_sdl3_prefix}") | ||
46 | set(_sdl3_include_dirs "${_sdl3_prefix}/include") | ||
47 | |||
48 | set(_sdl3_implib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.lib") | ||
49 | set(_sdl3_dll "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.dll") | ||
50 | set(_sdl3test_lib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3_test.lib") | ||
51 | |||
52 | unset(_sdl_arch_subdir) | ||
53 | unset(_sdl3_prefix) | ||
54 | |||
55 | # All targets are created, even when some might not be requested though COMPONENTS. | ||
56 | # This is done for compatibility with CMake generated SDL3-target.cmake files. | ||
57 | |||
58 | if(NOT TARGET SDL3::Headers) | ||
59 | add_library(SDL3::Headers INTERFACE IMPORTED) | ||
60 | set_target_properties(SDL3::Headers | ||
61 | PROPERTIES | ||
62 | INTERFACE_INCLUDE_DIRECTORIES "${_sdl3_include_dirs}" | ||
63 | ) | ||
64 | endif() | ||
65 | set(SDL3_Headers_FOUND TRUE) | ||
66 | unset(_sdl3_include_dirs) | ||
67 | |||
68 | if(EXISTS "${_sdl3_implib}" AND EXISTS "${_sdl3_dll}") | ||
69 | if(NOT TARGET SDL3::SDL3-shared) | ||
70 | add_library(SDL3::SDL3-shared SHARED IMPORTED) | ||
71 | set_target_properties(SDL3::SDL3-shared | ||
72 | PROPERTIES | ||
73 | INTERFACE_LINK_LIBRARIES "SDL3::Headers" | ||
74 | IMPORTED_IMPLIB "${_sdl3_implib}" | ||
75 | IMPORTED_LOCATION "${_sdl3_dll}" | ||
76 | COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" | ||
77 | INTERFACE_SDL3_SHARED "ON" | ||
78 | COMPATIBLE_INTERFACE_STRING "SDL_VERSION" | ||
79 | INTERFACE_SDL_VERSION "SDL3" | ||
80 | ) | ||
81 | endif() | ||
82 | set(SDL3_SDL3-shared_FOUND TRUE) | ||
83 | else() | ||
84 | set(SDL3_SDL3-shared_FOUND FALSE) | ||
85 | endif() | ||
86 | unset(_sdl3_implib) | ||
87 | unset(_sdl3_dll) | ||
88 | |||
89 | set(SDL3_SDL3-static_FOUND FALSE) | ||
90 | |||
91 | if(EXISTS "${_sdl3test_lib}") | ||
92 | if(NOT TARGET SDL3::SDL3_test) | ||
93 | add_library(SDL3::SDL3_test STATIC IMPORTED) | ||
94 | set_target_properties(SDL3::SDL3_test | ||
95 | PROPERTIES | ||
96 | INTERFACE_LINK_LIBRARIES "SDL3::Headers" | ||
97 | IMPORTED_LOCATION "${_sdl3test_lib}" | ||
98 | COMPATIBLE_INTERFACE_STRING "SDL_VERSION" | ||
99 | INTERFACE_SDL_VERSION "SDL3" | ||
100 | ) | ||
101 | endif() | ||
102 | set(SDL3_SDL3_test_FOUND TRUE) | ||
103 | else() | ||
104 | set(SDL3_SDL3_test_FOUND FALSE) | ||
105 | endif() | ||
106 | unset(_sdl3test_lib) | ||
107 | |||
108 | if(SDL3_SDL3-shared_FOUND OR SDL3_SDL3-static_FOUND) | ||
109 | set(SDL3_SDL3_FOUND TRUE) | ||
110 | endif() | ||
111 | |||
112 | function(_sdl_create_target_alias_compat NEW_TARGET TARGET) | ||
113 | if(CMAKE_VERSION VERSION_LESS "3.18") | ||
114 | # Aliasing local targets is not supported on CMake < 3.18, so make it global. | ||
115 | add_library(${NEW_TARGET} INTERFACE IMPORTED) | ||
116 | set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") | ||
117 | else() | ||
118 | add_library(${NEW_TARGET} ALIAS ${TARGET}) | ||
119 | endif() | ||
120 | endfunction() | ||
121 | |||
122 | # Make sure SDL3::SDL3 always exists | ||
123 | if(NOT TARGET SDL3::SDL3) | ||
124 | if(TARGET SDL3::SDL3-shared) | ||
125 | _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-shared) | ||
126 | endif() | ||
127 | endif() | ||
128 | |||
129 | check_required_components(SDL3) | ||
130 | |||
131 | set(SDL3_LIBRARIES SDL3::SDL3) | ||
132 | set(SDL3_STATIC_LIBRARIES SDL3::SDL3-static) | ||
133 | set(SDL3_STATIC_PRIVATE_LIBS) | ||
134 | |||
135 | set(SDL3TEST_LIBRARY SDL3::SDL3_test) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in new file mode 100644 index 0000000..82b6af0 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in | |||
@@ -0,0 +1,38 @@ | |||
1 | # @<@PROJECT_NAME@>@ CMake version configuration file: | ||
2 | # This file is meant to be placed in a cmake subfolder of @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip | ||
3 | |||
4 | set(PACKAGE_VERSION "@<@PROJECT_VERSION@>@") | ||
5 | |||
6 | if(PACKAGE_FIND_VERSION_RANGE) | ||
7 | # Package version must be in the requested version range | ||
8 | if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) | ||
9 | OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) | ||
10 | OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) | ||
11 | set(PACKAGE_VERSION_COMPATIBLE FALSE) | ||
12 | else() | ||
13 | set(PACKAGE_VERSION_COMPATIBLE TRUE) | ||
14 | endif() | ||
15 | else() | ||
16 | if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) | ||
17 | set(PACKAGE_VERSION_COMPATIBLE FALSE) | ||
18 | else() | ||
19 | set(PACKAGE_VERSION_COMPATIBLE TRUE) | ||
20 | if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) | ||
21 | set(PACKAGE_VERSION_EXACT TRUE) | ||
22 | endif() | ||
23 | endif() | ||
24 | endif() | ||
25 | |||
26 | # if the using project doesn't have CMAKE_SIZEOF_VOID_P set, fail. | ||
27 | if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") | ||
28 | set(PACKAGE_VERSION_UNSUITABLE TRUE) | ||
29 | endif() | ||
30 | |||
31 | include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake") | ||
32 | SDL_DetectTargetCPUArchitectures(_detected_archs) | ||
33 | |||
34 | # check that the installed version has a compatible architecture as the one which is currently searching: | ||
35 | if(NOT(SDL_CPU_X86 OR SDL_CPU_X64 OR SDL_CPU_ARM64 OR SDL_CPU_ARM64EC)) | ||
36 | set(PACKAGE_VERSION "${PACKAGE_VERSION} (X86,X64,ARM64)") | ||
37 | set(PACKAGE_VERSION_UNSUITABLE TRUE) | ||
38 | endif() | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x64/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x64/INSTALL.md.in new file mode 100644 index 0000000..74cd678 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x64/INSTALL.md.in | |||
@@ -0,0 +1,13 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for x64 Windows. | ||
5 | |||
6 | To use this package, simply replace an existing 64-bit @<@PROJECT_NAME@>@.dll with the one included here. | ||
7 | |||
8 | # Development packages | ||
9 | |||
10 | If you're looking for packages with headers and libraries, you can download one of these: | ||
11 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip, for development using Visual Studio | ||
12 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-mingw.zip, for development using mingw-w64 | ||
13 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x86/INSTALL.md.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x86/INSTALL.md.in new file mode 100644 index 0000000..041c116 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/msvc/x86/INSTALL.md.in | |||
@@ -0,0 +1,13 @@ | |||
1 | |||
2 | # Using this package | ||
3 | |||
4 | This package contains @<@PROJECT_NAME@>@ built for x86 Windows. | ||
5 | |||
6 | To use this package, simply replace an existing 32-bit @<@PROJECT_NAME@>@.dll with the one included here. | ||
7 | |||
8 | # Development packages | ||
9 | |||
10 | If you're looking for packages with headers and libraries, you can download one of these: | ||
11 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip, for development using Visual Studio | ||
12 | - @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-mingw.zip, for development using mingw-w64 | ||
13 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.cmake.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.cmake.in new file mode 100644 index 0000000..99e9f80 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.cmake.in | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
4 | |||
5 | This software is provided 'as-is', without any express or implied | ||
6 | warranty. In no event will the authors be held liable for any damages | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely, subject to the following restrictions: | ||
12 | |||
13 | 1. The origin of this software must not be misrepresented; you must not | ||
14 | claim that you wrote the original software. If you use this software | ||
15 | in a product, an acknowledgment in the product documentation would be | ||
16 | appreciated but is not required. | ||
17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
18 | misrepresented as being the original software. | ||
19 | 3. This notice may not be removed or altered from any source distribution. | ||
20 | */ | ||
21 | |||
22 | /* WIKI CATEGORY: Version */ | ||
23 | |||
24 | /* | ||
25 | * SDL_revision.h contains the SDL revision, which might be defined on the | ||
26 | * compiler command line, or generated right into the header itself by the | ||
27 | * build system. | ||
28 | */ | ||
29 | |||
30 | #ifndef SDL_revision_h_ | ||
31 | #define SDL_revision_h_ | ||
32 | |||
33 | #cmakedefine SDL_VENDOR_INFO "@SDL_VENDOR_INFO@" | ||
34 | |||
35 | #if defined(SDL_VENDOR_INFO) | ||
36 | #define SDL_REVISION "@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")" | ||
37 | #else | ||
38 | #define SDL_REVISION "@<@PROJECT_REVISION@>@" | ||
39 | #endif | ||
40 | |||
41 | #endif /* SDL_revision_h_ */ | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.in b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.in new file mode 100644 index 0000000..7dd6bc1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/pkg-support/source/SDL_revision.h.in | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
4 | |||
5 | This software is provided 'as-is', without any express or implied | ||
6 | warranty. In no event will the authors be held liable for any damages | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely, subject to the following restrictions: | ||
12 | |||
13 | 1. The origin of this software must not be misrepresented; you must not | ||
14 | claim that you wrote the original software. If you use this software | ||
15 | in a product, an acknowledgment in the product documentation would be | ||
16 | appreciated but is not required. | ||
17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
18 | misrepresented as being the original software. | ||
19 | 3. This notice may not be removed or altered from any source distribution. | ||
20 | */ | ||
21 | |||
22 | /* WIKI CATEGORY: Version */ | ||
23 | |||
24 | /* | ||
25 | * SDL_revision.h contains the SDL revision, which might be defined on the | ||
26 | * compiler command line, or generated right into the header itself by the | ||
27 | * build system. | ||
28 | */ | ||
29 | |||
30 | #ifndef SDL_revision_h_ | ||
31 | #define SDL_revision_h_ | ||
32 | |||
33 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
34 | |||
35 | /** | ||
36 | * This macro is a string describing the source at a particular point in | ||
37 | * development. | ||
38 | * | ||
39 | * This string is often generated from revision control's state at build time. | ||
40 | * | ||
41 | * This string can be quite complex and does not follow any standard. For | ||
42 | * example, it might be something like "SDL-prerelease-3.1.1-47-gf687e0732". | ||
43 | * It might also be user-defined at build time, so it's best to treat it as a | ||
44 | * clue in debugging forensics and not something the app will parse in any | ||
45 | * way. | ||
46 | * | ||
47 | * \since This macro is available since SDL 3.0.0. | ||
48 | */ | ||
49 | #define SDL_REVISION "Some arbitrary string decided at SDL build time" | ||
50 | #elif defined(SDL_VENDOR_INFO) | ||
51 | #define SDL_REVISION "@<@PROJECT_REVISION@>@ (" SDL_VENDOR_INFO ")" | ||
52 | #else | ||
53 | #define SDL_REVISION "@<@PROJECT_REVISION@>@" | ||
54 | #endif | ||
55 | |||
56 | #endif /* SDL_revision_h_ */ | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/release-info.json b/src/contrib/SDL-3.2.20/build-scripts/release-info.json new file mode 100644 index 0000000..8ba213a --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/release-info.json | |||
@@ -0,0 +1,210 @@ | |||
1 | { | ||
2 | "name": "SDL3", | ||
3 | "remote": "libsdl-org/SDL", | ||
4 | "version": { | ||
5 | "file": "include/SDL3/SDL_version.h", | ||
6 | "re_major": "^#define SDL_MAJOR_VERSION\\s+([0-9]+)$", | ||
7 | "re_minor": "^#define SDL_MINOR_VERSION\\s+([0-9]+)$", | ||
8 | "re_micro": "^#define SDL_MICRO_VERSION\\s+([0-9]+)$" | ||
9 | }, | ||
10 | "source": { | ||
11 | "checks": [ | ||
12 | "src/SDL.c", | ||
13 | "include/SDL3/SDL.h", | ||
14 | "test/testsprite.c", | ||
15 | "android-project/app/src/main/java/org/libsdl/app/SDLActivity.java" | ||
16 | ], | ||
17 | "files": { | ||
18 | "include/SDL3": [ | ||
19 | "build-scripts/pkg-support/source/SDL_revision.h.in:SDL_revision.h" | ||
20 | ], | ||
21 | "include/build_config": [ | ||
22 | "build-scripts/pkg-support/source/SDL_revision.h.cmake.in:SDL_revision.h.cmake" | ||
23 | ] | ||
24 | } | ||
25 | }, | ||
26 | "dmg": { | ||
27 | "project": "Xcode/SDL/SDL.xcodeproj", | ||
28 | "path": "Xcode/SDL/build/SDL3.dmg", | ||
29 | "target": "SDL3.dmg", | ||
30 | "build-xcconfig": "Xcode/SDL/pkg-support/build.xcconfig" | ||
31 | }, | ||
32 | "mingw": { | ||
33 | "cmake": { | ||
34 | "archs": ["x86", "x64"], | ||
35 | "args": [ | ||
36 | "-DSDL_SHARED=ON", | ||
37 | "-DSDL_STATIC=OFF", | ||
38 | "-DSDL_DISABLE_INSTALL_DOCS=ON", | ||
39 | "-DSDL_RELOCATABLE=ON", | ||
40 | "-DSDL_TEST_LIBRARY=ON", | ||
41 | "-DSDL_TESTS=OFF", | ||
42 | "-DSDL_VENDOR_INFO=libsdl.org" | ||
43 | ], | ||
44 | "shared-static": "args" | ||
45 | }, | ||
46 | "files": { | ||
47 | "": [ | ||
48 | "build-scripts/pkg-support/mingw/INSTALL.md.in:INSTALL.md", | ||
49 | "build-scripts/pkg-support/mingw/Makefile", | ||
50 | "LICENSE.txt", | ||
51 | "README.md" | ||
52 | ], | ||
53 | "cmake": [ | ||
54 | "build-scripts/pkg-support/mingw/cmake/SDL3Config.cmake", | ||
55 | "build-scripts/pkg-support/mingw/cmake/SDL3ConfigVersion.cmake" | ||
56 | ] | ||
57 | } | ||
58 | }, | ||
59 | "msvc": { | ||
60 | "msbuild": { | ||
61 | "archs": [ | ||
62 | "x86", | ||
63 | "x64" | ||
64 | ], | ||
65 | "directory-build-props": "build-scripts/pkg-support/msvc/Directory.Build.props", | ||
66 | "projects": [ | ||
67 | "VisualC/SDL/SDL.vcxproj", | ||
68 | "VisualC/SDL_test/SDL_test.vcxproj" | ||
69 | ], | ||
70 | "files-lib": { | ||
71 | "": [ | ||
72 | "VisualC/SDL/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3.dll" | ||
73 | ] | ||
74 | }, | ||
75 | "files-devel": { | ||
76 | "lib/@<@ARCH@>@": [ | ||
77 | "VisualC/SDL/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3.dll", | ||
78 | "VisualC/SDL/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3.lib", | ||
79 | "VisualC/SDL/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3.pdb", | ||
80 | "VisualC/SDL_test/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3_test.lib" | ||
81 | ] | ||
82 | } | ||
83 | }, | ||
84 | "cmake": { | ||
85 | "archs": [ | ||
86 | "arm64" | ||
87 | ], | ||
88 | "args": [ | ||
89 | "-DSDL_SHARED=ON", | ||
90 | "-DSDL_STATIC=OFF", | ||
91 | "-DSDL_TEST_LIBRARY=ON", | ||
92 | "-DSDL_TESTS=OFF", | ||
93 | "-DSDL_DISABLE_INSTALL_DOCS=ON", | ||
94 | "-DSDL_RELOCATABLE=ON", | ||
95 | "-DSDL_VENDOR_INFO=libsdl.org" | ||
96 | ], | ||
97 | "files-lib": { | ||
98 | "": [ | ||
99 | "bin/SDL3.dll" | ||
100 | ] | ||
101 | }, | ||
102 | "files-devel": { | ||
103 | "lib/@<@ARCH@>@": [ | ||
104 | "bin/SDL3.dll", | ||
105 | "bin/SDL3.pdb", | ||
106 | "lib/SDL3.lib", | ||
107 | "lib/SDL3_test.lib" | ||
108 | ] | ||
109 | } | ||
110 | }, | ||
111 | "files-lib": { | ||
112 | "": [ | ||
113 | "build-scripts/pkg-support/msvc/@<@ARCH@>@/INSTALL.md.in:INSTALL.md", | ||
114 | "LICENSE.txt", | ||
115 | "README.md" | ||
116 | ] | ||
117 | }, | ||
118 | "files-devel": { | ||
119 | "": [ | ||
120 | "build-scripts/pkg-support/msvc/INSTALL.md.in:INSTALL.md", | ||
121 | "LICENSE.txt", | ||
122 | "README.md" | ||
123 | ], | ||
124 | "cmake": [ | ||
125 | "build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in:SDL3Config.cmake", | ||
126 | "build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in:SDL3ConfigVersion.cmake", | ||
127 | "cmake/sdlcpu.cmake" | ||
128 | ], | ||
129 | "include/SDL3": [ | ||
130 | "include/SDL3/*.h" | ||
131 | ] | ||
132 | } | ||
133 | }, | ||
134 | "android": { | ||
135 | "cmake": { | ||
136 | "args": [ | ||
137 | "-DSDL_SHARED=ON", | ||
138 | "-DSDL_STATIC=OFF", | ||
139 | "-DSDL_TEST_LIBRARY=ON", | ||
140 | "-DSDL_TESTS=OFF", | ||
141 | "-DSDL_ANDROID_JAR=ON", | ||
142 | "-DSDL_INSTALL=ON", | ||
143 | "-DSDL_INSTALL_DOCS=ON", | ||
144 | "-DSDL_VENDOR_INFO=libsdl.org" | ||
145 | ] | ||
146 | }, | ||
147 | "modules": { | ||
148 | "SDL3-Headers": { | ||
149 | "type": "interface", | ||
150 | "includes": { | ||
151 | "SDL3": ["include/SDL3/*.h"] | ||
152 | } | ||
153 | }, | ||
154 | "Headers": { | ||
155 | "type": "interface", | ||
156 | "export-libraries": [":SDL3-Headers"] | ||
157 | }, | ||
158 | "SDL3_test": { | ||
159 | "type": "library", | ||
160 | "library": "lib/libSDL3_test.a", | ||
161 | "export-libraries": [":Headers"] | ||
162 | }, | ||
163 | "SDL3-shared": { | ||
164 | "type": "library", | ||
165 | "library": "lib/libSDL3.so", | ||
166 | "export-libraries": [":Headers"] | ||
167 | }, | ||
168 | "SDL3": { | ||
169 | "type": "interface", | ||
170 | "export-libraries": [":SDL3-shared"] | ||
171 | } | ||
172 | }, | ||
173 | "jars": { | ||
174 | "classes": "share/java/@<@PROJECT_NAME@>@/@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.jar", | ||
175 | "sources": "share/java/@<@PROJECT_NAME@>@/@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@-sources.jar", | ||
176 | "doc": "share/javadoc/@<@PROJECT_NAME@>@/@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@-javadoc.jar" | ||
177 | }, | ||
178 | "abis": [ | ||
179 | "armeabi-v7a", | ||
180 | "arm64-v8a", | ||
181 | "x86", | ||
182 | "x86_64" | ||
183 | ], | ||
184 | "api-minimum": 21, | ||
185 | "api-target": 35, | ||
186 | "ndk-minimum": 21, | ||
187 | "aar-files": { | ||
188 | "": [ | ||
189 | "android-project/app/proguard-rules.pro:proguard.txt", | ||
190 | "build-scripts/pkg-support/android/aar/__main__.py.in:__main__.py", | ||
191 | "build-scripts/pkg-support/android/aar/description.json.in:description.json" | ||
192 | ], | ||
193 | "META-INF": [ | ||
194 | "LICENSE.txt" | ||
195 | ], | ||
196 | "cmake": [ | ||
197 | "cmake/sdlcpu.cmake", | ||
198 | "build-scripts/pkg-support/android/aar/cmake/SDL3Config.cmake", | ||
199 | "build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in:SDL3ConfigVersion.cmake" | ||
200 | ] | ||
201 | }, | ||
202 | "files": { | ||
203 | "": [ | ||
204 | "build-scripts/pkg-support/android/INSTALL.md.in:INSTALL.md", | ||
205 | "LICENSE.txt", | ||
206 | "README.md" | ||
207 | ] | ||
208 | } | ||
209 | } | ||
210 | } | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_api.py b/src/contrib/SDL-3.2.20/build-scripts/rename_api.py new file mode 100755 index 0000000..605ffa0 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/rename_api.py | |||
@@ -0,0 +1,254 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # This script renames symbols in the API, updating SDL_oldnames.h and | ||
4 | # adding documentation for the change. | ||
5 | |||
6 | import argparse | ||
7 | import os | ||
8 | import pathlib | ||
9 | import pprint | ||
10 | import re | ||
11 | import sys | ||
12 | from rename_symbols import create_regex_from_replacements, replace_symbols_in_path | ||
13 | |||
14 | SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] | ||
15 | |||
16 | SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3" | ||
17 | SDL_BUILD_SCRIPTS = SDL_ROOT / "build-scripts" | ||
18 | |||
19 | |||
20 | def main(): | ||
21 | if len(args.args) == 0 or (len(args.args) % 2) != 0: | ||
22 | print("Usage: %s [-h] [--skip-header-check] header {enum,function,hint,structure,symbol} [old new ...]" % sys.argv[0]) | ||
23 | exit(1) | ||
24 | |||
25 | # Check whether we can still modify the ABI | ||
26 | version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text() | ||
27 | if not re.search(r"SDL_MINOR_VERSION\s+[01]\s", version_header): | ||
28 | raise Exception("ABI is frozen, symbols cannot be renamed") | ||
29 | |||
30 | # Find the symbol in the headers | ||
31 | if pathlib.Path(args.header).is_file(): | ||
32 | header = pathlib.Path(args.header) | ||
33 | else: | ||
34 | header = pathlib.Path(SDL_INCLUDE_DIR / args.header) | ||
35 | |||
36 | if not header.exists(): | ||
37 | raise Exception("Couldn't find header %s" % header) | ||
38 | |||
39 | header_name = header.name | ||
40 | if (header.name == "SDL_gamepad.h"): | ||
41 | header_name = "SDL_gamecontroller.h" | ||
42 | |||
43 | header_text = header.read_text() | ||
44 | |||
45 | # Replace the symbols in source code | ||
46 | replacements = {} | ||
47 | i = 0 | ||
48 | while i < len(args.args): | ||
49 | oldname = args.args[i + 0] | ||
50 | newname = args.args[i + 1] | ||
51 | |||
52 | if not args.skip_header_check and not re.search((r"\b%s\b" % oldname), header_text): | ||
53 | raise Exception("Couldn't find %s in %s" % (oldname, header)) | ||
54 | |||
55 | replacements[ oldname ] = newname | ||
56 | replacements[ oldname + "_REAL" ] = newname + "_REAL" | ||
57 | i += 2 | ||
58 | |||
59 | regex = create_regex_from_replacements(replacements) | ||
60 | for dir in ["src", "test", "examples", "include", "docs", "cmake/test"]: | ||
61 | replace_symbols_in_path(SDL_ROOT / dir, regex, replacements) | ||
62 | |||
63 | # Replace the symbols in documentation | ||
64 | i = 0 | ||
65 | while i < len(args.args): | ||
66 | oldname = args.args[i + 0] | ||
67 | newname = args.args[i + 1] | ||
68 | |||
69 | add_symbol_to_oldnames(header_name, oldname, newname) | ||
70 | add_symbol_to_migration(header_name, args.type, oldname, newname) | ||
71 | add_symbol_to_coccinelle(args.type, oldname, newname) | ||
72 | i += 2 | ||
73 | |||
74 | |||
75 | def add_line(lines, i, section): | ||
76 | lines.insert(i, section) | ||
77 | i += 1 | ||
78 | return i | ||
79 | |||
80 | |||
81 | def add_content(lines, i, content, add_trailing_line): | ||
82 | if lines[i - 1] == "": | ||
83 | lines[i - 1] = content | ||
84 | else: | ||
85 | i = add_line(lines, i, content) | ||
86 | |||
87 | if add_trailing_line: | ||
88 | i = add_line(lines, i, "") | ||
89 | return i | ||
90 | |||
91 | |||
92 | def add_symbol_to_coccinelle(symbol_type, oldname, newname): | ||
93 | file = open(SDL_BUILD_SCRIPTS / "SDL_migration.cocci", "a") | ||
94 | # Append-adds at last | ||
95 | |||
96 | if symbol_type == "function": | ||
97 | file.write("@@\n") | ||
98 | file.write("@@\n") | ||
99 | file.write("- %s\n" % oldname) | ||
100 | file.write("+ %s\n" % newname) | ||
101 | file.write(" (...)\n") | ||
102 | |||
103 | if symbol_type == "symbol": | ||
104 | file.write("@@\n") | ||
105 | file.write("@@\n") | ||
106 | file.write("- %s\n" % oldname) | ||
107 | file.write("+ %s\n" % newname) | ||
108 | |||
109 | # double check ? | ||
110 | if symbol_type == "hint": | ||
111 | file.write("@@\n") | ||
112 | file.write("@@\n") | ||
113 | file.write("- %s\n" % oldname) | ||
114 | file.write("+ %s\n" % newname) | ||
115 | |||
116 | if symbol_type == "enum" or symbol_type == "structure": | ||
117 | file.write("@@\n") | ||
118 | file.write("typedef %s, %s;\n" % (oldname, newname)) | ||
119 | file.write("@@\n") | ||
120 | file.write("- %s\n" % oldname) | ||
121 | file.write("+ %s\n" % newname) | ||
122 | |||
123 | file.close() | ||
124 | |||
125 | |||
126 | def add_symbol_to_oldnames(header, oldname, newname): | ||
127 | file = (SDL_INCLUDE_DIR / "SDL_oldnames.h") | ||
128 | lines = file.read_text().splitlines() | ||
129 | mode = 0 | ||
130 | i = 0 | ||
131 | while i < len(lines): | ||
132 | line = lines[i] | ||
133 | if line == "#ifdef SDL_ENABLE_OLD_NAMES": | ||
134 | if mode == 0: | ||
135 | mode = 1 | ||
136 | section = ("/* ##%s */" % header) | ||
137 | section_added = False | ||
138 | content = ("#define %s %s" % (oldname, newname)) | ||
139 | content_added = False | ||
140 | else: | ||
141 | raise Exception("add_symbol_to_oldnames(): expected mode 0") | ||
142 | elif line == "#elif !defined(SDL_DISABLE_OLD_NAMES)": | ||
143 | if mode == 1: | ||
144 | if not section_added: | ||
145 | i = add_line(lines, i, section) | ||
146 | |||
147 | if not content_added: | ||
148 | i = add_content(lines, i, content, True) | ||
149 | |||
150 | mode = 2 | ||
151 | section = ("/* ##%s */" % header) | ||
152 | section_added = False | ||
153 | content = ("#define %s %s_renamed_%s" % (oldname, oldname, newname)) | ||
154 | content_added = False | ||
155 | else: | ||
156 | raise Exception("add_symbol_to_oldnames(): expected mode 1") | ||
157 | elif line == "#endif /* SDL_ENABLE_OLD_NAMES */": | ||
158 | if mode == 2: | ||
159 | if not section_added: | ||
160 | i = add_line(lines, i, section) | ||
161 | |||
162 | if not content_added: | ||
163 | i = add_content(lines, i, content, True) | ||
164 | |||
165 | mode = 3 | ||
166 | else: | ||
167 | raise Exception("add_symbol_to_oldnames(): expected mode 2") | ||
168 | elif line != "" and (mode == 1 or mode == 2): | ||
169 | if line.startswith("/* ##"): | ||
170 | if section_added: | ||
171 | if not content_added: | ||
172 | i = add_content(lines, i, content, True) | ||
173 | content_added = True | ||
174 | elif line == section: | ||
175 | section_added = True | ||
176 | elif section < line: | ||
177 | i = add_line(lines, i, section) | ||
178 | section_added = True | ||
179 | i = add_content(lines, i, content, True) | ||
180 | content_added = True | ||
181 | elif line != "" and section_added and not content_added: | ||
182 | if content == line: | ||
183 | content_added = True | ||
184 | elif content < line: | ||
185 | i = add_content(lines, i, content, False) | ||
186 | content_added = True | ||
187 | i += 1 | ||
188 | |||
189 | file.write_text("\n".join(lines) + "\n") | ||
190 | |||
191 | |||
192 | def add_symbol_to_migration(header, symbol_type, oldname, newname): | ||
193 | file = (SDL_ROOT / "docs/README-migration.md") | ||
194 | lines = file.read_text().splitlines() | ||
195 | section = ("## %s" % header) | ||
196 | section_added = False | ||
197 | note = ("The following %ss have been renamed:" % symbol_type) | ||
198 | note_added = False | ||
199 | if symbol_type == "function": | ||
200 | content = ("* %s() => %s()" % (oldname, newname)) | ||
201 | else: | ||
202 | content = ("* %s => %s" % (oldname, newname)) | ||
203 | content_added = False | ||
204 | mode = 0 | ||
205 | i = 0 | ||
206 | while i < len(lines): | ||
207 | line = lines[i] | ||
208 | if line.startswith("##") and line.endswith(".h"): | ||
209 | if line == section: | ||
210 | section_added = True | ||
211 | elif section < line: | ||
212 | break | ||
213 | |||
214 | elif section_added and not note_added: | ||
215 | if note == line: | ||
216 | note_added = True | ||
217 | elif note_added and not content_added: | ||
218 | if content == line: | ||
219 | content_added = True | ||
220 | elif line == "" or content < line: | ||
221 | i = add_line(lines, i, content) | ||
222 | content_added = True | ||
223 | i += 1 | ||
224 | |||
225 | if not section_added: | ||
226 | i = add_line(lines, i, section) | ||
227 | i = add_line(lines, i, "") | ||
228 | |||
229 | if not note_added: | ||
230 | i = add_line(lines, i, note) | ||
231 | |||
232 | if not content_added: | ||
233 | i = add_content(lines, i, content, True) | ||
234 | |||
235 | file.write_text("\n".join(lines) + "\n") | ||
236 | |||
237 | |||
238 | if __name__ == "__main__": | ||
239 | |||
240 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@') | ||
241 | parser.add_argument("--skip-header-check", action="store_true") | ||
242 | parser.add_argument("header") | ||
243 | parser.add_argument("type", choices=["enum", "function", "hint", "structure", "symbol"]) | ||
244 | parser.add_argument("args", nargs="*") | ||
245 | args = parser.parse_args() | ||
246 | |||
247 | try: | ||
248 | main() | ||
249 | except Exception as e: | ||
250 | print(e) | ||
251 | exit(-1) | ||
252 | |||
253 | exit(0) | ||
254 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_headers.py b/src/contrib/SDL-3.2.20/build-scripts/rename_headers.py new file mode 100755 index 0000000..b61e477 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/rename_headers.py | |||
@@ -0,0 +1,75 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # This script renames SDL headers in the specified paths | ||
4 | |||
5 | import argparse | ||
6 | import pathlib | ||
7 | import re | ||
8 | |||
9 | |||
10 | def do_include_replacements(paths): | ||
11 | replacements = [ | ||
12 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_image.h(?:[\">])"), r"<SDL3_image/SDL_image.h>" ), | ||
13 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_mixer.h(?:[\">])"), r"<SDL3_mixer/SDL_mixer.h>" ), | ||
14 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_net.h(?:[\">])"), r"<SDL3_net/SDL_net.h>" ), | ||
15 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_rtf.h(?:[\">])"), r"<SDL3_rtf/SDL_rtf.h>" ), | ||
16 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_ttf.h(?:[\">])"), r"<SDL3_ttf/SDL_ttf.h>" ), | ||
17 | ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_gamecontroller.h(?:[\">])"), r"<SDL3/SDL_gamepad.h>" ), | ||
18 | ( re.compile(r"(?:[\"<])(?:SDL2/)?begin_code.h(?:[\">])"), r"<SDL3/SDL_begin_code.h>" ), | ||
19 | ( re.compile(r"(?:[\"<])(?:SDL2/)?close_code.h(?:[\">])"), r"<SDL3/SDL_close_code.h>" ), | ||
20 | ( re.compile(r"(?:[\"<])(?:SDL2/)?(SDL[_a-z0-9]*\.h)(?:[\">])"), r"<SDL3/\1>" ) | ||
21 | ] | ||
22 | for entry in paths: | ||
23 | path = pathlib.Path(entry) | ||
24 | if not path.exists(): | ||
25 | print("{} does not exist, skipping".format(entry)) | ||
26 | continue | ||
27 | |||
28 | replace_headers_in_path(path, replacements) | ||
29 | |||
30 | |||
31 | def replace_headers_in_file(file, replacements): | ||
32 | try: | ||
33 | with file.open("r", encoding="UTF-8", newline="") as rfp: | ||
34 | original = rfp.read() | ||
35 | contents = original | ||
36 | for regex, replacement in replacements: | ||
37 | contents = regex.sub(replacement, contents) | ||
38 | if contents != original: | ||
39 | with file.open("w", encoding="UTF-8", newline="") as wfp: | ||
40 | wfp.write(contents) | ||
41 | except UnicodeDecodeError: | ||
42 | print("%s is not text, skipping" % file) | ||
43 | except Exception as err: | ||
44 | print("%s" % err) | ||
45 | |||
46 | |||
47 | def replace_headers_in_dir(path, replacements): | ||
48 | for entry in path.glob("*"): | ||
49 | if entry.is_dir(): | ||
50 | replace_headers_in_dir(entry, replacements) | ||
51 | else: | ||
52 | print("Processing %s" % entry) | ||
53 | replace_headers_in_file(entry, replacements) | ||
54 | |||
55 | |||
56 | def replace_headers_in_path(path, replacements): | ||
57 | if path.is_dir(): | ||
58 | replace_headers_in_dir(path, replacements) | ||
59 | else: | ||
60 | replace_headers_in_file(path, replacements) | ||
61 | |||
62 | |||
63 | def main(): | ||
64 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@', description="Rename #include's for SDL3.") | ||
65 | parser.add_argument("args", metavar="PATH", nargs="*", help="Input source file") | ||
66 | args = parser.parse_args() | ||
67 | |||
68 | try: | ||
69 | do_include_replacements(args.args) | ||
70 | except Exception as e: | ||
71 | print(e) | ||
72 | return 1 | ||
73 | |||
74 | if __name__ == "__main__": | ||
75 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_macros.py b/src/contrib/SDL-3.2.20/build-scripts/rename_macros.py new file mode 100755 index 0000000..978120c --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/rename_macros.py | |||
@@ -0,0 +1,382 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # This script renames SDL macros in the specified paths | ||
4 | |||
5 | import argparse | ||
6 | import pathlib | ||
7 | import re | ||
8 | |||
9 | |||
10 | class TextReplacer: | ||
11 | def __init__(self, macros, repl_format): | ||
12 | if isinstance(macros, dict): | ||
13 | macros_keys = macros.keys() | ||
14 | else: | ||
15 | macros_keys = macros | ||
16 | self.macros = macros | ||
17 | self.re_macros = re.compile(r"\W(" + "|".join(macros_keys) + r")(?:\W|$)") | ||
18 | self.repl_format = repl_format | ||
19 | |||
20 | def apply(self, contents): | ||
21 | def cb(m): | ||
22 | macro = m.group(1) | ||
23 | original = m.group(0) | ||
24 | match_start, _ = m.span(0) | ||
25 | platform_start, platform_end = m.span(1) | ||
26 | if isinstance(self.macros, dict): | ||
27 | repl_args = (macro, self.macros[macro]) | ||
28 | else: | ||
29 | repl_args = macro, | ||
30 | new_text = self.repl_format.format(*repl_args) | ||
31 | r = original[:(platform_start-match_start)] + new_text + original[platform_end-match_start:] | ||
32 | return r | ||
33 | contents, _ = self.re_macros.subn(cb, contents) | ||
34 | |||
35 | return contents | ||
36 | |||
37 | |||
38 | class MacrosCheck: | ||
39 | def __init__(self): | ||
40 | self.renamed_platform_macros = TextReplacer(RENAMED_MACROS, "{1}") | ||
41 | self.deprecated_platform_macros = TextReplacer(DEPRECATED_PLATFORM_MACROS, "{0} /* {0} has been removed in SDL3 */") | ||
42 | |||
43 | def run(self, contents): | ||
44 | contents = self.renamed_platform_macros.apply(contents) | ||
45 | contents = self.deprecated_platform_macros.apply(contents) | ||
46 | return contents | ||
47 | |||
48 | |||
49 | def apply_checks(paths): | ||
50 | checks = ( | ||
51 | MacrosCheck(), | ||
52 | ) | ||
53 | |||
54 | for entry in paths: | ||
55 | path = pathlib.Path(entry) | ||
56 | if not path.exists(): | ||
57 | print("{} does not exist, skipping".format(entry)) | ||
58 | continue | ||
59 | apply_checks_in_path(path, checks) | ||
60 | |||
61 | |||
62 | def apply_checks_in_file(file, checks): | ||
63 | try: | ||
64 | with file.open("r", encoding="UTF-8", newline="") as rfp: | ||
65 | original = rfp.read() | ||
66 | contents = original | ||
67 | for check in checks: | ||
68 | contents = check.run(contents) | ||
69 | if contents != original: | ||
70 | with file.open("w", encoding="UTF-8", newline="") as wfp: | ||
71 | wfp.write(contents) | ||
72 | except UnicodeDecodeError: | ||
73 | print("%s is not text, skipping" % file) | ||
74 | except Exception as err: | ||
75 | print("%s" % err) | ||
76 | |||
77 | |||
78 | def apply_checks_in_dir(path, checks): | ||
79 | for entry in path.glob("*"): | ||
80 | if entry.is_dir(): | ||
81 | apply_checks_in_dir(entry, checks) | ||
82 | else: | ||
83 | print("Processing %s" % entry) | ||
84 | apply_checks_in_file(entry, checks) | ||
85 | |||
86 | |||
87 | def apply_checks_in_path(path, checks): | ||
88 | if path.is_dir(): | ||
89 | apply_checks_in_dir(path, checks) | ||
90 | else: | ||
91 | apply_checks_in_file(path, checks) | ||
92 | |||
93 | |||
94 | def main(): | ||
95 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@', description="Rename macros for SDL3") | ||
96 | parser.add_argument("args", nargs="*", help="Input source files") | ||
97 | args = parser.parse_args() | ||
98 | |||
99 | try: | ||
100 | apply_checks(args.args) | ||
101 | except Exception as e: | ||
102 | print(e) | ||
103 | return 1 | ||
104 | |||
105 | |||
106 | RENAMED_MACROS = { | ||
107 | "__AIX__": "SDL_PLATFORM_AIX", | ||
108 | "__HAIKU__": "SDL_PLATFORM_HAIKU", | ||
109 | "__BSDI__": "SDL_PLATFORM_BSDI", | ||
110 | "__FREEBSD__": "SDL_PLATFORM_FREEBSD", | ||
111 | "__HPUX__": "SDL_PLATFORM_HPUX", | ||
112 | "__IRIX__": "SDL_PLATFORM_IRIX", | ||
113 | "__LINUX__": "SDL_PLATFORM_LINUX", | ||
114 | "__OS2__": "SDL_PLATFORM_OS2", | ||
115 | # "__ANDROID__": "SDL_PLATFORM_ANDROID, | ||
116 | "__APPLE__": "SDL_PLATFORM_APPLE", | ||
117 | "__TVOS__": "SDL_PLATFORM_TVOS", | ||
118 | "__IPHONEOS__": "SDL_PLATFORM_IOS", | ||
119 | "__MACOSX__": "SDL_PLATFORM_MACOS", | ||
120 | "__NETBSD__": "SDL_PLATFORM_NETBSD", | ||
121 | "__OPENBSD__": "SDL_PLATFORM_OPENBSD", | ||
122 | "__OSF__": "SDL_PLATFORM_OSF", | ||
123 | "__QNXNTO__": "SDL_PLATFORM_QNXNTO", | ||
124 | "__RISCOS__": "SDL_PLATFORM_RISCOS", | ||
125 | "__SOLARIS__": "SDL_PLATFORM_SOLARIS", | ||
126 | "__PSP__": "SDL_PLATFORM_PSP", | ||
127 | "__PS2__": "SDL_PLATFORM_PS2", | ||
128 | "__VITA__": "SDL_PLATFORM_VITA", | ||
129 | "__3DS__": "SDL_PLATFORM_3DS", | ||
130 | # "__unix__": "SDL_PLATFORM_UNIX, | ||
131 | "__XBOXSERIES__": "SDL_PLATFORM_XBOXSERIES", | ||
132 | "__XBOXONE__": "SDL_PLATFORM_XBOXONE", | ||
133 | "__WINDOWS__": "SDL_PLATFORM_WINDOWS", | ||
134 | "__WIN32__": "SDL_PLATFORM_WIN32", | ||
135 | # "__CYGWIN_": "SDL_PLATFORM_CYGWIN", | ||
136 | "__WINGDK__": "SDL_PLATFORM_WINGDK", | ||
137 | "__GDK__": "SDL_PLATFORM_GDK", | ||
138 | # "__EMSCRIPTEN__": "SDL_PLATFORM_EMSCRIPTEN", | ||
139 | } | ||
140 | |||
141 | DEPRECATED_PLATFORM_MACROS = { | ||
142 | "__DREAMCAST__", | ||
143 | "__NACL__", | ||
144 | "__PNACL__", | ||
145 | "__WINDOWS__", | ||
146 | "__WINRT__", | ||
147 | "SDL_ALTIVEC_BLITTERS", | ||
148 | "SDL_ARM_NEON_BLITTERS", | ||
149 | "SDL_ARM_SIMD_BLITTERS", | ||
150 | "SDL_ATOMIC_DISABLED", | ||
151 | "SDL_AUDIO_DISABLED", | ||
152 | "SDL_AUDIO_DRIVER_AAUDIO", | ||
153 | "SDL_AUDIO_DRIVER_ALSA", | ||
154 | "SDL_AUDIO_DRIVER_ALSA_DYNAMIC", | ||
155 | "SDL_AUDIO_DRIVER_ANDROID", | ||
156 | "SDL_AUDIO_DRIVER_ARTS", | ||
157 | "SDL_AUDIO_DRIVER_ARTS_DYNAMIC", | ||
158 | "SDL_AUDIO_DRIVER_COREAUDIO", | ||
159 | "SDL_AUDIO_DRIVER_DISK", | ||
160 | "SDL_AUDIO_DRIVER_DSOUND", | ||
161 | "SDL_AUDIO_DRIVER_DUMMY", | ||
162 | "SDL_AUDIO_DRIVER_EMSCRIPTEN", | ||
163 | "SDL_AUDIO_DRIVER_ESD", | ||
164 | "SDL_AUDIO_DRIVER_ESD_DYNAMIC", | ||
165 | "SDL_AUDIO_DRIVER_FUSIONSOUND", | ||
166 | "SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC", | ||
167 | "SDL_AUDIO_DRIVER_HAIKU", | ||
168 | "SDL_AUDIO_DRIVER_JACK", | ||
169 | "SDL_AUDIO_DRIVER_JACK_DYNAMIC", | ||
170 | "SDL_AUDIO_DRIVER_N3DS", | ||
171 | "SDL_AUDIO_DRIVER_NAS", | ||
172 | "SDL_AUDIO_DRIVER_NAS_DYNAMIC", | ||
173 | "SDL_AUDIO_DRIVER_NETBSD", | ||
174 | "SDL_AUDIO_DRIVER_OPENSLES", | ||
175 | "SDL_AUDIO_DRIVER_OS2", | ||
176 | "SDL_AUDIO_DRIVER_OSS", | ||
177 | "SDL_AUDIO_DRIVER_PAUDIO", | ||
178 | "SDL_AUDIO_DRIVER_PIPEWIRE", | ||
179 | "SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC", | ||
180 | "SDL_AUDIO_DRIVER_PS2", | ||
181 | "SDL_AUDIO_DRIVER_PSP", | ||
182 | "SDL_AUDIO_DRIVER_PULSEAUDIO", | ||
183 | "SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC", | ||
184 | "SDL_AUDIO_DRIVER_QSA", | ||
185 | "SDL_AUDIO_DRIVER_SNDIO", | ||
186 | "SDL_AUDIO_DRIVER_SNDIO_DYNAMIC", | ||
187 | "SDL_AUDIO_DRIVER_SUNAUDIO", | ||
188 | "SDL_AUDIO_DRIVER_VITA", | ||
189 | "SDL_AUDIO_DRIVER_WASAPI", | ||
190 | "SDL_AUDIO_DRIVER_WINMM", | ||
191 | "SDL_CPUINFO_DISABLED", | ||
192 | "SDL_DEFAULT_ASSERT_LEVEL", | ||
193 | "SDL_EVENTS_DISABLED", | ||
194 | "SDL_FILESYSTEM_ANDROID", | ||
195 | "SDL_FILESYSTEM_COCOA", | ||
196 | "SDL_FILESYSTEM_DISABLED", | ||
197 | "SDL_FILESYSTEM_DUMMY", | ||
198 | "SDL_FILESYSTEM_EMSCRIPTEN", | ||
199 | "SDL_FILESYSTEM_HAIKU", | ||
200 | "SDL_FILESYSTEM_N3DS", | ||
201 | "SDL_FILESYSTEM_OS2", | ||
202 | "SDL_FILESYSTEM_PS2", | ||
203 | "SDL_FILESYSTEM_PSP", | ||
204 | "SDL_FILESYSTEM_RISCOS", | ||
205 | "SDL_FILESYSTEM_UNIX", | ||
206 | "SDL_FILESYSTEM_VITA", | ||
207 | "SDL_FILESYSTEM_WINDOWS", | ||
208 | "SDL_FILE_DISABLED", | ||
209 | "SDL_HAPTIC_ANDROID", | ||
210 | "SDL_HAPTIC_DINPUT", | ||
211 | "SDL_HAPTIC_DISABLED", | ||
212 | "SDL_HAPTIC_DUMMY", | ||
213 | "SDL_HAPTIC_IOKIT", | ||
214 | "SDL_HAPTIC_LINUX", | ||
215 | "SDL_HAPTIC_XINPUT", | ||
216 | "SDL_HAVE_LIBDECOR_GET_MIN_MAX", | ||
217 | "SDL_HAVE_MACHINE_JOYSTICK_H", | ||
218 | "SDL_HIDAPI_DISABLED", | ||
219 | "SDL_INPUT_FBSDKBIO", | ||
220 | "SDL_INPUT_LINUXEV", | ||
221 | "SDL_INPUT_LINUXKD", | ||
222 | "SDL_INPUT_WSCONS", | ||
223 | "SDL_IPHONE_KEYBOARD", | ||
224 | "SDL_IPHONE_LAUNCHSCREEN", | ||
225 | "SDL_JOYSTICK_ANDROID", | ||
226 | "SDL_JOYSTICK_DINPUT", | ||
227 | "SDL_JOYSTICK_DISABLED", | ||
228 | "SDL_JOYSTICK_DUMMY", | ||
229 | "SDL_JOYSTICK_EMSCRIPTEN", | ||
230 | "SDL_JOYSTICK_HAIKU", | ||
231 | "SDL_JOYSTICK_HIDAPI", | ||
232 | "SDL_JOYSTICK_IOKIT", | ||
233 | "SDL_JOYSTICK_LINUX", | ||
234 | "SDL_JOYSTICK_MFI", | ||
235 | "SDL_JOYSTICK_N3DS", | ||
236 | "SDL_JOYSTICK_OS2", | ||
237 | "SDL_JOYSTICK_PS2", | ||
238 | "SDL_JOYSTICK_PSP", | ||
239 | "SDL_JOYSTICK_RAWINPUT", | ||
240 | "SDL_JOYSTICK_USBHID", | ||
241 | "SDL_JOYSTICK_VIRTUAL", | ||
242 | "SDL_JOYSTICK_VITA", | ||
243 | "SDL_JOYSTICK_WGI", | ||
244 | "SDL_JOYSTICK_XINPUT", | ||
245 | "SDL_LIBSAMPLERATE_DYNAMIC", | ||
246 | "SDL_LIBUSB_DYNAMIC", | ||
247 | "SDL_LOADSO_DISABLED", | ||
248 | "SDL_LOADSO_DLOPEN", | ||
249 | "SDL_LOADSO_DUMMY", | ||
250 | "SDL_LOADSO_LDG", | ||
251 | "SDL_LOADSO_OS2", | ||
252 | "SDL_LOADSO_WINDOWS", | ||
253 | "SDL_LOCALE_DISABLED", | ||
254 | "SDL_LOCALE_DUMMY", | ||
255 | "SDL_MISC_DISABLED", | ||
256 | "SDL_MISC_DUMMY", | ||
257 | "SDL_POWER_ANDROID", | ||
258 | "SDL_POWER_DISABLED", | ||
259 | "SDL_POWER_EMSCRIPTEN", | ||
260 | "SDL_POWER_HAIKU", | ||
261 | "SDL_POWER_HARDWIRED", | ||
262 | "SDL_POWER_LINUX", | ||
263 | "SDL_POWER_MACOSX", | ||
264 | "SDL_POWER_N3DS", | ||
265 | "SDL_POWER_PSP", | ||
266 | "SDL_POWER_UIKIT", | ||
267 | "SDL_POWER_VITA", | ||
268 | "SDL_POWER_WINDOWS", | ||
269 | "SDL_POWER_WINRT", | ||
270 | "SDL_RENDER_DISABLED", | ||
271 | "SDL_SENSOR_ANDROID", | ||
272 | "SDL_SENSOR_COREMOTION", | ||
273 | "SDL_SENSOR_DISABLED", | ||
274 | "SDL_SENSOR_DUMMY", | ||
275 | "SDL_SENSOR_N3DS", | ||
276 | "SDL_SENSOR_VITA", | ||
277 | "SDL_SENSOR_WINDOWS", | ||
278 | "SDL_THREADS_DISABLED", | ||
279 | "SDL_THREAD_GENERIC_COND_SUFFIX", | ||
280 | "SDL_THREAD_N3DS", | ||
281 | "SDL_THREAD_OS2", | ||
282 | "SDL_THREAD_PS2", | ||
283 | "SDL_THREAD_PSP", | ||
284 | "SDL_THREAD_PTHREAD", | ||
285 | "SDL_THREAD_PTHREAD_RECURSIVE_MUTEX", | ||
286 | "SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP", | ||
287 | "SDL_THREAD_VITA", | ||
288 | "SDL_THREAD_WINDOWS", | ||
289 | "SDL_TIMERS_DISABLED", | ||
290 | "SDL_TIMER_DUMMY", | ||
291 | "SDL_TIMER_HAIKU", | ||
292 | "SDL_TIMER_N3DS", | ||
293 | "SDL_TIMER_OS2", | ||
294 | "SDL_TIMER_PS2", | ||
295 | "SDL_TIMER_PSP", | ||
296 | "SDL_TIMER_UNIX", | ||
297 | "SDL_TIMER_VITA", | ||
298 | "SDL_TIMER_WINDOWS", | ||
299 | "SDL_UDEV_DYNAMIC", | ||
300 | "SDL_USE_IME", | ||
301 | "SDL_USE_LIBICONV", | ||
302 | "SDL_VIDEO_DISABLED", | ||
303 | "SDL_VIDEO_DRIVER_ANDROID", | ||
304 | "SDL_VIDEO_DRIVER_COCOA", | ||
305 | "SDL_VIDEO_DRIVER_DIRECTFB", | ||
306 | "SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC", | ||
307 | "SDL_VIDEO_DRIVER_DUMMY", | ||
308 | "SDL_VIDEO_DRIVER_EMSCRIPTEN", | ||
309 | "SDL_VIDEO_DRIVER_HAIKU", | ||
310 | "SDL_VIDEO_DRIVER_KMSDRM", | ||
311 | "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC", | ||
312 | "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM", | ||
313 | "SDL_VIDEO_DRIVER_N3DS", | ||
314 | "SDL_VIDEO_DRIVER_OFFSCREEN", | ||
315 | "SDL_VIDEO_DRIVER_OS2", | ||
316 | "SDL_VIDEO_DRIVER_PS2", | ||
317 | "SDL_VIDEO_DRIVER_PSP", | ||
318 | "SDL_VIDEO_DRIVER_QNX", | ||
319 | "SDL_VIDEO_DRIVER_RISCOS", | ||
320 | "SDL_VIDEO_DRIVER_RPI", | ||
321 | "SDL_VIDEO_DRIVER_UIKIT", | ||
322 | "SDL_VIDEO_DRIVER_VITA", | ||
323 | "SDL_VIDEO_DRIVER_VIVANTE", | ||
324 | "SDL_VIDEO_DRIVER_VIVANTE_VDK", | ||
325 | "SDL_VIDEO_DRIVER_WAYLAND", | ||
326 | "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC", | ||
327 | "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR", | ||
328 | "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL", | ||
329 | "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR", | ||
330 | "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON", | ||
331 | "SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH", | ||
332 | "SDL_VIDEO_DRIVER_WINDOWS", | ||
333 | "SDL_VIDEO_DRIVER_WINRT", | ||
334 | "SDL_VIDEO_DRIVER_X11", | ||
335 | "SDL_VIDEO_DRIVER_X11_DYNAMIC", | ||
336 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR", | ||
337 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT", | ||
338 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES", | ||
339 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2", | ||
340 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR", | ||
341 | "SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS", | ||
342 | "SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM", | ||
343 | "SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS", | ||
344 | "SDL_VIDEO_DRIVER_X11_XCURSOR", | ||
345 | "SDL_VIDEO_DRIVER_X11_XDBE", | ||
346 | "SDL_VIDEO_DRIVER_X11_XFIXES", | ||
347 | "SDL_VIDEO_DRIVER_X11_XINPUT2", | ||
348 | "SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH", | ||
349 | "SDL_VIDEO_DRIVER_X11_XRANDR", | ||
350 | "SDL_VIDEO_DRIVER_X11_XSCRNSAVER", | ||
351 | "SDL_VIDEO_DRIVER_X11_XSHAPE", | ||
352 | "SDL_VIDEO_METAL", | ||
353 | "SDL_VIDEO_OPENGL", | ||
354 | "SDL_VIDEO_OPENGL_BGL", | ||
355 | "SDL_VIDEO_OPENGL_CGL", | ||
356 | "SDL_VIDEO_OPENGL_EGL", | ||
357 | "SDL_VIDEO_OPENGL_ES", | ||
358 | "SDL_VIDEO_OPENGL_ES2", | ||
359 | "SDL_VIDEO_OPENGL_GLX", | ||
360 | "SDL_VIDEO_OPENGL_OSMESA", | ||
361 | "SDL_VIDEO_OPENGL_OSMESA_DYNAMIC", | ||
362 | "SDL_VIDEO_OPENGL_WGL", | ||
363 | "SDL_VIDEO_RENDER_D3D", | ||
364 | "SDL_VIDEO_RENDER_D3D11", | ||
365 | "SDL_VIDEO_RENDER_D3D12", | ||
366 | "SDL_VIDEO_RENDER_DIRECTFB", | ||
367 | "SDL_VIDEO_RENDER_METAL", | ||
368 | "SDL_VIDEO_RENDER_OGL", | ||
369 | "SDL_VIDEO_RENDER_OGL_ES", | ||
370 | "SDL_VIDEO_RENDER_OGL_ES2", | ||
371 | "SDL_VIDEO_RENDER_PS2", | ||
372 | "SDL_VIDEO_RENDER_PSP", | ||
373 | "SDL_VIDEO_RENDER_VITA_GXM", | ||
374 | "SDL_VIDEO_VITA_PIB", | ||
375 | "SDL_VIDEO_VITA_PVR", | ||
376 | "SDL_VIDEO_VITA_PVR_OGL", | ||
377 | "SDL_VIDEO_VULKAN", | ||
378 | } | ||
379 | |||
380 | if __name__ == "__main__": | ||
381 | raise SystemExit(main()) | ||
382 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_symbols.py b/src/contrib/SDL-3.2.20/build-scripts/rename_symbols.py new file mode 100755 index 0000000..33a92dd --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/rename_symbols.py | |||
@@ -0,0 +1,130 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # This script renames symbols in the specified paths | ||
4 | |||
5 | import argparse | ||
6 | import os | ||
7 | import pathlib | ||
8 | import re | ||
9 | import sys | ||
10 | |||
11 | |||
12 | SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] | ||
13 | |||
14 | SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3" | ||
15 | |||
16 | |||
17 | def main(): | ||
18 | if args.all_symbols: | ||
19 | if len(args.args) < 1: | ||
20 | print("Usage: %s --all-symbols files_or_directories ..." % sys.argv[0]) | ||
21 | exit(1) | ||
22 | |||
23 | replacements = get_all_replacements() | ||
24 | entries = args.args | ||
25 | |||
26 | else: | ||
27 | if len(args.args) < 3: | ||
28 | print("Usage: %s [--substring] oldname newname files_or_directories ..." % sys.argv[0]) | ||
29 | exit(1) | ||
30 | |||
31 | replacements = { args.args[0]: args.args[1] } | ||
32 | entries = args.args[2:] | ||
33 | |||
34 | if args.substring: | ||
35 | regex = create_substring_regex_from_replacements(replacements) | ||
36 | else: | ||
37 | regex = create_regex_from_replacements(replacements) | ||
38 | |||
39 | for entry in entries: | ||
40 | path = pathlib.Path(entry) | ||
41 | if not path.exists(): | ||
42 | print("%s doesn't exist, skipping" % entry) | ||
43 | continue | ||
44 | |||
45 | replace_symbols_in_path(path, regex, replacements) | ||
46 | |||
47 | |||
48 | def get_all_replacements(): | ||
49 | replacements = {} | ||
50 | file = (SDL_INCLUDE_DIR / "SDL_oldnames.h") | ||
51 | mode = 0 | ||
52 | for line in file.read_text().splitlines(): | ||
53 | if line == "#ifdef SDL_ENABLE_OLD_NAMES": | ||
54 | if mode == 0: | ||
55 | mode = 1 | ||
56 | else: | ||
57 | raise Exception("get_all_replacements(): expected mode 0") | ||
58 | elif line == "#elif !defined(SDL_DISABLE_OLD_NAMES)": | ||
59 | if mode == 1: | ||
60 | mode = 2 | ||
61 | else: | ||
62 | raise Exception("get_all_replacements(): expected mode 1") | ||
63 | elif line == "#endif /* SDL_ENABLE_OLD_NAMES */": | ||
64 | if mode == 2: | ||
65 | mode = 3 | ||
66 | else: | ||
67 | raise Exception("add_symbol_to_oldnames(): expected mode 2") | ||
68 | elif mode == 1 and line.startswith("#define "): | ||
69 | words = line.split() | ||
70 | replacements[words[1]] = words[2] | ||
71 | # In case things are accidentally renamed to the "X_renamed_Y" symbol | ||
72 | #replacements[words[1] + "_renamed_" + words[2]] = words[2] | ||
73 | |||
74 | return replacements | ||
75 | |||
76 | |||
77 | def create_regex_from_replacements(replacements): | ||
78 | return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys()))) | ||
79 | |||
80 | |||
81 | def create_substring_regex_from_replacements(replacements): | ||
82 | return re.compile(r"(%s)" % "|".join(map(re.escape, replacements.keys()))) | ||
83 | |||
84 | |||
85 | def replace_symbols_in_file(file, regex, replacements): | ||
86 | try: | ||
87 | with file.open("r", encoding="UTF-8", newline="") as rfp: | ||
88 | original = rfp.read() | ||
89 | contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], original) | ||
90 | if contents != original: | ||
91 | with file.open("w", encoding="UTF-8", newline="") as wfp: | ||
92 | wfp.write(contents) | ||
93 | except UnicodeDecodeError: | ||
94 | print("%s is not text, skipping" % file) | ||
95 | except Exception as err: | ||
96 | print("%s" % err) | ||
97 | |||
98 | |||
99 | def replace_symbols_in_dir(path, regex, replacements): | ||
100 | for entry in path.glob("*"): | ||
101 | if entry.is_dir(): | ||
102 | replace_symbols_in_dir(entry, regex, replacements) | ||
103 | else: | ||
104 | print("Processing %s" % entry) | ||
105 | replace_symbols_in_file(entry, regex, replacements) | ||
106 | |||
107 | |||
108 | def replace_symbols_in_path(path, regex, replacements): | ||
109 | if path.is_dir(): | ||
110 | replace_symbols_in_dir(path, regex, replacements) | ||
111 | else: | ||
112 | replace_symbols_in_file(path, regex, replacements) | ||
113 | |||
114 | |||
115 | if __name__ == "__main__": | ||
116 | |||
117 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@') | ||
118 | parser.add_argument("--all-symbols", action="store_true") | ||
119 | parser.add_argument("--substring", action="store_true") | ||
120 | parser.add_argument("args", nargs="*") | ||
121 | args = parser.parse_args() | ||
122 | |||
123 | try: | ||
124 | main() | ||
125 | except Exception as e: | ||
126 | print(e) | ||
127 | exit(-1) | ||
128 | |||
129 | exit(0) | ||
130 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_types.py b/src/contrib/SDL-3.2.20/build-scripts/rename_types.py new file mode 100755 index 0000000..137b409 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/rename_types.py | |||
@@ -0,0 +1,80 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # This script renames symbols in the specified paths | ||
4 | |||
5 | import argparse | ||
6 | import os | ||
7 | import pathlib | ||
8 | import re | ||
9 | import sys | ||
10 | |||
11 | |||
12 | def main(): | ||
13 | if len(args.args) < 1: | ||
14 | print("Usage: %s files_or_directories ..." % sys.argv[0]) | ||
15 | exit(1) | ||
16 | |||
17 | replacements = { | ||
18 | "SDL_bool": "bool", | ||
19 | "SDL_TRUE": "true", | ||
20 | "SDL_FALSE": "false", | ||
21 | } | ||
22 | entries = args.args[0:] | ||
23 | |||
24 | regex = create_regex_from_replacements(replacements) | ||
25 | |||
26 | for entry in entries: | ||
27 | path = pathlib.Path(entry) | ||
28 | if not path.exists(): | ||
29 | print("%s doesn't exist, skipping" % entry) | ||
30 | continue | ||
31 | |||
32 | replace_symbols_in_path(path, regex, replacements) | ||
33 | |||
34 | def create_regex_from_replacements(replacements): | ||
35 | return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys()))) | ||
36 | |||
37 | def replace_symbols_in_file(file, regex, replacements): | ||
38 | try: | ||
39 | with file.open("r", encoding="UTF-8", newline="") as rfp: | ||
40 | original = rfp.read() | ||
41 | contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], original) | ||
42 | if contents != original: | ||
43 | with file.open("w", encoding="UTF-8", newline="") as wfp: | ||
44 | wfp.write(contents) | ||
45 | except UnicodeDecodeError: | ||
46 | print("%s is not text, skipping" % file) | ||
47 | except Exception as err: | ||
48 | print("%s" % err) | ||
49 | |||
50 | |||
51 | def replace_symbols_in_dir(path, regex, replacements): | ||
52 | for entry in path.glob("*"): | ||
53 | if entry.is_dir(): | ||
54 | replace_symbols_in_dir(entry, regex, replacements) | ||
55 | else: | ||
56 | print("Processing %s" % entry) | ||
57 | replace_symbols_in_file(entry, regex, replacements) | ||
58 | |||
59 | |||
60 | def replace_symbols_in_path(path, regex, replacements): | ||
61 | if path.is_dir(): | ||
62 | replace_symbols_in_dir(path, regex, replacements) | ||
63 | else: | ||
64 | replace_symbols_in_file(path, regex, replacements) | ||
65 | |||
66 | |||
67 | if __name__ == "__main__": | ||
68 | |||
69 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@') | ||
70 | parser.add_argument("args", nargs="*") | ||
71 | args = parser.parse_args() | ||
72 | |||
73 | try: | ||
74 | main() | ||
75 | except Exception as e: | ||
76 | print(e) | ||
77 | exit(-1) | ||
78 | |||
79 | exit(0) | ||
80 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/setup-gdk-desktop.py b/src/contrib/SDL-3.2.20/build-scripts/setup-gdk-desktop.py new file mode 100755 index 0000000..d2309a0 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/setup-gdk-desktop.py | |||
@@ -0,0 +1,303 @@ | |||
1 | #!/usr/bin/env python | ||
2 | |||
3 | import argparse | ||
4 | import functools | ||
5 | import logging | ||
6 | import os | ||
7 | from pathlib import Path | ||
8 | import re | ||
9 | import shutil | ||
10 | import subprocess | ||
11 | import tempfile | ||
12 | import textwrap | ||
13 | import urllib.request | ||
14 | import zipfile | ||
15 | |||
16 | # Update both variables when updating the GDK | ||
17 | GIT_REF = "June_2024_Update_1" | ||
18 | GDK_EDITION = "240601" # YYMMUU | ||
19 | |||
20 | logger = logging.getLogger(__name__) | ||
21 | |||
22 | class GdDesktopConfigurator: | ||
23 | def __init__(self, gdk_path, arch, vs_folder, vs_version=None, vs_toolset=None, temp_folder=None, git_ref=None, gdk_edition=None): | ||
24 | self.git_ref = git_ref or GIT_REF | ||
25 | self.gdk_edition = gdk_edition or GDK_EDITION | ||
26 | self.gdk_path = gdk_path | ||
27 | self.temp_folder = temp_folder or Path(tempfile.gettempdir()) | ||
28 | self.dl_archive_path = Path(self.temp_folder) / f"{ self.git_ref }.zip" | ||
29 | self.gdk_extract_path = Path(self.temp_folder) / f"GDK-{ self.git_ref }" | ||
30 | self.arch = arch | ||
31 | self.vs_folder = vs_folder | ||
32 | self._vs_version = vs_version | ||
33 | self._vs_toolset = vs_toolset | ||
34 | |||
35 | def download_archive(self) -> None: | ||
36 | gdk_url = f"https://github.com/microsoft/GDK/archive/refs/tags/{ GIT_REF }.zip" | ||
37 | logger.info("Downloading %s to %s", gdk_url, self.dl_archive_path) | ||
38 | urllib.request.urlretrieve(gdk_url, self.dl_archive_path) | ||
39 | assert self.dl_archive_path.is_file() | ||
40 | |||
41 | def extract_zip_archive(self) -> None: | ||
42 | extract_path = self.gdk_extract_path.parent | ||
43 | assert self.dl_archive_path.is_file() | ||
44 | logger.info("Extracting %s to %s", self.dl_archive_path, extract_path) | ||
45 | with zipfile.ZipFile(self.dl_archive_path) as zf: | ||
46 | zf.extractall(extract_path) | ||
47 | assert self.gdk_extract_path.is_dir(), f"{self.gdk_extract_path} must exist" | ||
48 | |||
49 | def extract_development_kit(self) -> None: | ||
50 | extract_dks_cmd = self.gdk_extract_path / "SetupScripts/ExtractXboxOneDKs.cmd" | ||
51 | assert extract_dks_cmd.is_file() | ||
52 | logger.info("Extracting GDK Development Kit: running %s", extract_dks_cmd) | ||
53 | cmd = ["cmd.exe", "/C", str(extract_dks_cmd), str(self.gdk_extract_path), str(self.gdk_path)] | ||
54 | logger.debug("Running %r", cmd) | ||
55 | subprocess.check_call(cmd) | ||
56 | |||
57 | def detect_vs_version(self) -> str: | ||
58 | vs_regex = re.compile("VS([0-9]{4})") | ||
59 | supported_vs_versions = [] | ||
60 | for p in self.gaming_grdk_build_path.iterdir(): | ||
61 | if not p.is_dir(): | ||
62 | continue | ||
63 | if m := vs_regex.match(p.name): | ||
64 | supported_vs_versions.append(m.group(1)) | ||
65 | logger.info(f"Supported Visual Studio versions: {supported_vs_versions}") | ||
66 | vs_versions = set(self.vs_folder.parts).intersection(set(supported_vs_versions)) | ||
67 | if not vs_versions: | ||
68 | raise RuntimeError("Visual Studio version is incompatible") | ||
69 | if len(vs_versions) > 1: | ||
70 | raise RuntimeError(f"Too many compatible VS versions found ({vs_versions})") | ||
71 | vs_version = vs_versions.pop() | ||
72 | logger.info(f"Used Visual Studio version: {vs_version}") | ||
73 | return vs_version | ||
74 | |||
75 | def detect_vs_toolset(self) -> str: | ||
76 | toolset_paths = [] | ||
77 | for ts_path in self.gdk_toolset_parent_path.iterdir(): | ||
78 | if not ts_path.is_dir(): | ||
79 | continue | ||
80 | ms_props = ts_path / "Microsoft.Cpp.props" | ||
81 | if not ms_props.is_file(): | ||
82 | continue | ||
83 | toolset_paths.append(ts_path.name) | ||
84 | logger.info("Detected Visual Studio toolsets: %s", toolset_paths) | ||
85 | assert toolset_paths, "Have we detected at least one toolset?" | ||
86 | |||
87 | def toolset_number(toolset: str) -> int: | ||
88 | if m:= re.match("[^0-9]*([0-9]+).*", toolset): | ||
89 | return int(m.group(1)) | ||
90 | return -9 | ||
91 | |||
92 | return max(toolset_paths, key=toolset_number) | ||
93 | |||
94 | @property | ||
95 | def vs_version(self) -> str: | ||
96 | if self._vs_version is None: | ||
97 | self._vs_version = self.detect_vs_version() | ||
98 | return self._vs_version | ||
99 | |||
100 | @property | ||
101 | def vs_toolset(self) -> str: | ||
102 | if self._vs_toolset is None: | ||
103 | self._vs_toolset = self.detect_vs_toolset() | ||
104 | return self._vs_toolset | ||
105 | |||
106 | @staticmethod | ||
107 | def copy_files_and_merge_into(srcdir: Path, dstdir: Path) -> None: | ||
108 | logger.info(f"Copy {srcdir} to {dstdir}") | ||
109 | for root, _, files in os.walk(srcdir): | ||
110 | dest_root = dstdir / Path(root).relative_to(srcdir) | ||
111 | if not dest_root.is_dir(): | ||
112 | dest_root.mkdir() | ||
113 | for file in files: | ||
114 | srcfile = Path(root) / file | ||
115 | dstfile = dest_root / file | ||
116 | shutil.copy(srcfile, dstfile) | ||
117 | |||
118 | def copy_msbuild(self) -> None: | ||
119 | vc_toolset_parent_path = self.vs_folder / "MSBuild/Microsoft/VC" | ||
120 | if 1: | ||
121 | logger.info(f"Detected compatible Visual Studio version: {self.vs_version}") | ||
122 | srcdir = vc_toolset_parent_path | ||
123 | dstdir = self.gdk_toolset_parent_path | ||
124 | assert srcdir.is_dir(), "Source directory must exist" | ||
125 | assert dstdir.is_dir(), "Destination directory must exist" | ||
126 | |||
127 | self.copy_files_and_merge_into(srcdir=srcdir, dstdir=dstdir) | ||
128 | |||
129 | @property | ||
130 | def game_dk_path(self) -> Path: | ||
131 | return self.gdk_path / "Microsoft GDK" | ||
132 | |||
133 | @property | ||
134 | def game_dk_latest_path(self) -> Path: | ||
135 | return self.game_dk_path / self.gdk_edition | ||
136 | |||
137 | @property | ||
138 | def windows_sdk_path(self) -> Path: | ||
139 | return self.gdk_path / "Windows Kits/10" | ||
140 | |||
141 | @property | ||
142 | def gaming_grdk_build_path(self) -> Path: | ||
143 | return self.game_dk_latest_path / "GRDK" | ||
144 | |||
145 | @property | ||
146 | def gdk_toolset_parent_path(self) -> Path: | ||
147 | return self.gaming_grdk_build_path / f"VS{self.vs_version}/flatDeployment/MSBuild/Microsoft/VC" | ||
148 | |||
149 | @property | ||
150 | def env(self) -> dict[str, str]: | ||
151 | game_dk = self.game_dk_path | ||
152 | game_dk_latest = self.game_dk_latest_path | ||
153 | windows_sdk_dir = self.windows_sdk_path | ||
154 | gaming_grdk_build = self.gaming_grdk_build_path | ||
155 | |||
156 | return { | ||
157 | "GRDKEDITION": f"{self.gdk_edition}", | ||
158 | "GameDK": f"{game_dk}\\", | ||
159 | "GameDKLatest": f"{ game_dk_latest }\\", | ||
160 | "WindowsSdkDir": f"{ windows_sdk_dir }\\", | ||
161 | "GamingGRDKBuild": f"{ gaming_grdk_build }\\", | ||
162 | "VSInstallDir": f"{ self.vs_folder }\\", | ||
163 | } | ||
164 | |||
165 | def create_user_props(self, path: Path) -> None: | ||
166 | vc_targets_path = self.gaming_grdk_build_path / f"VS{ self.vs_version }/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" | ||
167 | vc_targets_path16 = self.gaming_grdk_build_path / f"VS2019/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" | ||
168 | vc_targets_path17 = self.gaming_grdk_build_path / f"VS2022/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" | ||
169 | additional_include_directories = ";".join(str(p) for p in self.gdk_include_paths) | ||
170 | additional_library_directories = ";".join(str(p) for p in self.gdk_library_paths) | ||
171 | durango_xdk_install_path = self.gdk_path / "Microsoft GDK" | ||
172 | with path.open("w") as f: | ||
173 | f.write(textwrap.dedent(f"""\ | ||
174 | <?xml version="1.0" encoding="utf-8"?> | ||
175 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
176 | <PropertyGroup> | ||
177 | <VCTargetsPath>{ vc_targets_path }\\</VCTargetsPath> | ||
178 | <VCTargetsPath16>{ vc_targets_path16 }\\</VCTargetsPath16> | ||
179 | <VCTargetsPath17>{ vc_targets_path17 }\\</VCTargetsPath17> | ||
180 | <BWOI_GDK_Path>{ self.gaming_grdk_build_path }\\</BWOI_GDK_Path> | ||
181 | <Platform Condition="'$(Platform)' == ''">Gaming.Desktop.x64</Platform> | ||
182 | <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> | ||
183 | <XdkEditionTarget>{ self.gdk_edition }</XdkEditionTarget> | ||
184 | <DurangoXdkInstallPath>{ durango_xdk_install_path }</DurangoXdkInstallPath> | ||
185 | |||
186 | <DefaultXdkEditionRootVS2019>$(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2019\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\</DefaultXdkEditionRootVS2019> | ||
187 | <XdkEditionRootVS2019>$(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2019\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\</XdkEditionRootVS2019> | ||
188 | <DefaultXdkEditionRootVS2022>$(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2022\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\</DefaultXdkEditionRootVS2022> | ||
189 | <XdkEditionRootVS2022>$(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2022\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\</XdkEditionRootVS2022> | ||
190 | |||
191 | <Deterministic>true</Deterministic> | ||
192 | <DisableInstalledVCTargetsUse>true</DisableInstalledVCTargetsUse> | ||
193 | <ClearDevCommandPromptEnvVars>true</ClearDevCommandPromptEnvVars> | ||
194 | </PropertyGroup> | ||
195 | <ItemDefinitionGroup Condition="'$(Platform)' == 'Gaming.Desktop.x64'"> | ||
196 | <ClCompile> | ||
197 | <AdditionalIncludeDirectories>{ additional_include_directories };%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
198 | </ClCompile> | ||
199 | <Link> | ||
200 | <AdditionalLibraryDirectories>{ additional_library_directories };%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||
201 | </Link> | ||
202 | </ItemDefinitionGroup> | ||
203 | </Project> | ||
204 | """)) | ||
205 | |||
206 | @property | ||
207 | def gdk_include_paths(self) -> list[Path]: | ||
208 | return [ | ||
209 | self.gaming_grdk_build_path / "gamekit/include", | ||
210 | ] | ||
211 | |||
212 | @property | ||
213 | def gdk_library_paths(self) -> list[Path]: | ||
214 | return [ | ||
215 | self.gaming_grdk_build_path / f"gamekit/lib/{self.arch}", | ||
216 | ] | ||
217 | |||
218 | @property | ||
219 | def gdk_binary_path(self) -> list[Path]: | ||
220 | return [ | ||
221 | self.gaming_grdk_build_path / "bin", | ||
222 | self.game_dk_path / "bin", | ||
223 | ] | ||
224 | |||
225 | @property | ||
226 | def build_env(self) -> dict[str, str]: | ||
227 | gdk_include = ";".join(str(p) for p in self.gdk_include_paths) | ||
228 | gdk_lib = ";".join(str(p) for p in self.gdk_library_paths) | ||
229 | gdk_path = ";".join(str(p) for p in self.gdk_binary_path) | ||
230 | return { | ||
231 | "GDK_INCLUDE": gdk_include, | ||
232 | "GDK_LIB": gdk_lib, | ||
233 | "GDK_PATH": gdk_path, | ||
234 | } | ||
235 | |||
236 | def print_env(self) -> None: | ||
237 | for k, v in self.env.items(): | ||
238 | print(f"set \"{k}={v}\"") | ||
239 | print() | ||
240 | for k, v in self.build_env.items(): | ||
241 | print(f"set \"{k}={v}\"") | ||
242 | print() | ||
243 | print(f"set \"PATH=%GDK_PATH%;%PATH%\"") | ||
244 | print(f"set \"LIB=%GDK_LIB%;%LIB%\"") | ||
245 | print(f"set \"INCLUDE=%GDK_INCLUDE%;%INCLUDE%\"") | ||
246 | |||
247 | |||
248 | def main(): | ||
249 | logging.basicConfig(level=logging.INFO) | ||
250 | parser = argparse.ArgumentParser(allow_abbrev=False) | ||
251 | parser.add_argument("--arch", choices=["amd64"], default="amd64", help="Architecture") | ||
252 | parser.add_argument("--download", action="store_true", help="Download GDK") | ||
253 | parser.add_argument("--extract", action="store_true", help="Extract downloaded GDK") | ||
254 | parser.add_argument("--copy-msbuild", action="store_true", help="Copy MSBuild files") | ||
255 | parser.add_argument("--temp-folder", help="Temporary folder where to download and extract GDK") | ||
256 | parser.add_argument("--gdk-path", required=True, type=Path, help="Folder where to store the GDK") | ||
257 | parser.add_argument("--ref-edition", type=str, help="Git ref and GDK edition separated by comma") | ||
258 | parser.add_argument("--vs-folder", required=True, type=Path, help="Installation folder of Visual Studio") | ||
259 | parser.add_argument("--vs-version", required=False, type=int, help="Visual Studio version") | ||
260 | parser.add_argument("--vs-toolset", required=False, help="Visual Studio toolset (e.g. v150)") | ||
261 | parser.add_argument("--props-folder", required=False, type=Path, default=Path(), help="Visual Studio toolset (e.g. v150)") | ||
262 | parser.add_argument("--no-user-props", required=False, dest="user_props", action="store_false", help="Don't ") | ||
263 | args = parser.parse_args() | ||
264 | |||
265 | logging.basicConfig(level=logging.INFO) | ||
266 | |||
267 | git_ref = None | ||
268 | gdk_edition = None | ||
269 | if args.ref_edition is not None: | ||
270 | git_ref, gdk_edition = args.ref_edition.split(",", 1) | ||
271 | try: | ||
272 | int(gdk_edition) | ||
273 | except ValueError: | ||
274 | parser.error("Edition should be an integer (YYMMUU) (Y=year M=month U=update)") | ||
275 | |||
276 | configurator = GdDesktopConfigurator( | ||
277 | arch=args.arch, | ||
278 | git_ref=git_ref, | ||
279 | gdk_edition=gdk_edition, | ||
280 | vs_folder=args.vs_folder, | ||
281 | vs_version=args.vs_version, | ||
282 | vs_toolset=args.vs_toolset, | ||
283 | gdk_path=args.gdk_path, | ||
284 | temp_folder=args.temp_folder, | ||
285 | ) | ||
286 | |||
287 | if args.download: | ||
288 | configurator.download_archive() | ||
289 | |||
290 | if args.extract: | ||
291 | configurator.extract_zip_archive() | ||
292 | |||
293 | configurator.extract_development_kit() | ||
294 | |||
295 | if args.copy_msbuild: | ||
296 | configurator.copy_msbuild() | ||
297 | |||
298 | if args.user_props: | ||
299 | configurator.print_env() | ||
300 | configurator.create_user_props(args.props_folder / "Directory.Build.props") | ||
301 | |||
302 | if __name__ == "__main__": | ||
303 | raise SystemExit(main()) | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/showrev.sh b/src/contrib/SDL-3.2.20/build-scripts/showrev.sh new file mode 100755 index 0000000..764d3a4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/showrev.sh | |||
@@ -0,0 +1,48 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Print the current source revision, if available | ||
4 | |||
5 | SDL_ROOT=$(dirname $0)/.. | ||
6 | cd $SDL_ROOT | ||
7 | |||
8 | if [ -e ./VERSION.txt ]; then | ||
9 | cat ./VERSION.txt | ||
10 | exit 0 | ||
11 | fi | ||
12 | |||
13 | major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' include/SDL3/SDL_version.h) | ||
14 | minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' include/SDL3/SDL_version.h) | ||
15 | micro=$(sed -ne 's/^#define SDL_MICRO_VERSION *//p' include/SDL3/SDL_version.h) | ||
16 | version="${major}.${minor}.${micro}" | ||
17 | |||
18 | if [ -x "$(command -v git)" ]; then | ||
19 | rev="$(git describe --tags --long 2>/dev/null)" | ||
20 | if [ -n "$rev" ]; then | ||
21 | # e.g. release-2.24.0-542-g96361fc47 | ||
22 | # or release-2.24.1-5-g36b987dab | ||
23 | # or prerelease-2.23.2-0-gcb46e1b3f | ||
24 | echo "$rev" | ||
25 | exit 0 | ||
26 | fi | ||
27 | |||
28 | rev="$(git describe --always --tags --long 2>/dev/null)" | ||
29 | if [ -n "$rev" ]; then | ||
30 | # Just a truncated sha1, e.g. 96361fc47. | ||
31 | # Turn it into e.g. 2.25.0-g96361fc47 | ||
32 | echo "${version}-g${rev}" | ||
33 | exit 0 | ||
34 | fi | ||
35 | fi | ||
36 | |||
37 | if [ -x "$(command -v p4)" ]; then | ||
38 | rev="$(p4 changes -m1 ./...\#have 2>/dev/null| awk '{print $2}')" | ||
39 | if [ $? = 0 ]; then | ||
40 | # e.g. 2.25.0-p7511446 | ||
41 | echo "${version}-p${rev}" | ||
42 | exit 0 | ||
43 | fi | ||
44 | fi | ||
45 | |||
46 | # best we can do | ||
47 | echo "${version}-no-vcs" | ||
48 | exit 0 | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/strip_fPIC.sh b/src/contrib/SDL-3.2.20/build-scripts/strip_fPIC.sh new file mode 100755 index 0000000..8719b89 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/strip_fPIC.sh | |||
@@ -0,0 +1,21 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # libtool assumes that the compiler can handle the -fPIC flag | ||
4 | # This isn't always true (for example, nasm can't handle it) | ||
5 | command="" | ||
6 | while [ $# -gt 0 ]; do | ||
7 | case "$1" in | ||
8 | -?PIC) | ||
9 | # Ignore -fPIC and -DPIC options | ||
10 | ;; | ||
11 | -fno-common) | ||
12 | # Ignore -fPIC and -DPIC options | ||
13 | ;; | ||
14 | *) | ||
15 | command="$command $1" | ||
16 | ;; | ||
17 | esac | ||
18 | shift | ||
19 | done | ||
20 | echo $command | ||
21 | exec $command | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/test-versioning.sh b/src/contrib/SDL-3.2.20/build-scripts/test-versioning.sh new file mode 100755 index 0000000..55e29a3 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/test-versioning.sh | |||
@@ -0,0 +1,170 @@ | |||
1 | #!/bin/sh | ||
2 | # Copyright 2022 Collabora Ltd. | ||
3 | # SPDX-License-Identifier: Zlib | ||
4 | |||
5 | set -eu | ||
6 | |||
7 | cd `dirname $0`/.. | ||
8 | |||
9 | ref_major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' include/SDL3/SDL_version.h) | ||
10 | ref_minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' include/SDL3/SDL_version.h) | ||
11 | ref_micro=$(sed -ne 's/^#define SDL_MICRO_VERSION *//p' include/SDL3/SDL_version.h) | ||
12 | ref_version="${ref_major}.${ref_minor}.${ref_micro}" | ||
13 | |||
14 | tests=0 | ||
15 | failed=0 | ||
16 | |||
17 | ok () { | ||
18 | tests=$(( tests + 1 )) | ||
19 | echo "ok - $*" | ||
20 | } | ||
21 | |||
22 | not_ok () { | ||
23 | tests=$(( tests + 1 )) | ||
24 | echo "not ok - $*" | ||
25 | failed=1 | ||
26 | } | ||
27 | |||
28 | version=$(sed -Ene 's/^.* version ([0-9.]*)$/\1/p' include/SDL3/SDL.h) | ||
29 | |||
30 | if [ "$ref_version" = "$version" ]; then | ||
31 | ok "SDL.h $version" | ||
32 | else | ||
33 | not_ok "SDL.h $version disagrees with SDL_version.h $ref_version" | ||
34 | fi | ||
35 | |||
36 | version=$(sed -Ene 's/^project\(SDL[0-9]+ LANGUAGES C VERSION "([0-9.]*)"\)$/\1/p' CMakeLists.txt) | ||
37 | |||
38 | if [ "$ref_version" = "$version" ]; then | ||
39 | ok "CMakeLists.txt $version" | ||
40 | else | ||
41 | not_ok "CMakeLists.txt $version disagrees with SDL_version.h $ref_version" | ||
42 | fi | ||
43 | |||
44 | major=$(sed -ne 's/.*SDL_MAJOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java) | ||
45 | minor=$(sed -ne 's/.*SDL_MINOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java) | ||
46 | micro=$(sed -ne 's/.*SDL_MICRO_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java) | ||
47 | version="${major}.${minor}.${micro}" | ||
48 | |||
49 | if [ "$ref_version" = "$version" ]; then | ||
50 | ok "SDLActivity.java $version" | ||
51 | else | ||
52 | not_ok "android-project/app/src/main/java/org/libsdl/app/SDLActivity.java $version disagrees with SDL_version.h $ref_version" | ||
53 | fi | ||
54 | |||
55 | tuple=$(sed -ne 's/^ *FILEVERSION *//p' src/core/windows/version.rc | tr -d '\r') | ||
56 | ref_tuple="${ref_major},${ref_minor},${ref_micro},0" | ||
57 | |||
58 | if [ "$ref_tuple" = "$tuple" ]; then | ||
59 | ok "version.rc FILEVERSION $tuple" | ||
60 | else | ||
61 | not_ok "version.rc FILEVERSION $tuple disagrees with SDL_version.h $ref_tuple" | ||
62 | fi | ||
63 | |||
64 | tuple=$(sed -ne 's/^ *PRODUCTVERSION *//p' src/core/windows/version.rc | tr -d '\r') | ||
65 | |||
66 | if [ "$ref_tuple" = "$tuple" ]; then | ||
67 | ok "version.rc PRODUCTVERSION $tuple" | ||
68 | else | ||
69 | not_ok "version.rc PRODUCTVERSION $tuple disagrees with SDL_version.h $ref_tuple" | ||
70 | fi | ||
71 | |||
72 | tuple=$(sed -Ene 's/^ *VALUE "FileVersion", "([0-9, ]*)\\0"\r?$/\1/p' src/core/windows/version.rc | tr -d '\r') | ||
73 | ref_tuple="${ref_major}, ${ref_minor}, ${ref_micro}, 0" | ||
74 | |||
75 | if [ "$ref_tuple" = "$tuple" ]; then | ||
76 | ok "version.rc FileVersion $tuple" | ||
77 | else | ||
78 | not_ok "version.rc FileVersion $tuple disagrees with SDL_version.h $ref_tuple" | ||
79 | fi | ||
80 | |||
81 | tuple=$(sed -Ene 's/^ *VALUE "ProductVersion", "([0-9, ]*)\\0"\r?$/\1/p' src/core/windows/version.rc | tr -d '\r') | ||
82 | |||
83 | if [ "$ref_tuple" = "$tuple" ]; then | ||
84 | ok "version.rc ProductVersion $tuple" | ||
85 | else | ||
86 | not_ok "version.rc ProductVersion $tuple disagrees with SDL_version.h $ref_tuple" | ||
87 | fi | ||
88 | |||
89 | version=$(sed -Ene '/CFBundleShortVersionString/,+1 s/.*<string>(.*)<\/string>.*/\1/p' Xcode/SDL/Info-Framework.plist) | ||
90 | |||
91 | if [ "$ref_version" = "$version" ]; then | ||
92 | ok "Info-Framework.plist CFBundleShortVersionString $version" | ||
93 | else | ||
94 | not_ok "Info-Framework.plist CFBundleShortVersionString $version disagrees with SDL_version.h $ref_version" | ||
95 | fi | ||
96 | |||
97 | version=$(sed -Ene '/CFBundleVersion/,+1 s/.*<string>(.*)<\/string>.*/\1/p' Xcode/SDL/Info-Framework.plist) | ||
98 | |||
99 | if [ "$ref_version" = "$version" ]; then | ||
100 | ok "Info-Framework.plist CFBundleVersion $version" | ||
101 | else | ||
102 | not_ok "Info-Framework.plist CFBundleVersion $version disagrees with SDL_version.h $ref_version" | ||
103 | fi | ||
104 | |||
105 | version=$(sed -Ene 's/Title SDL (.*)/\1/p' Xcode/SDL/pkg-support/SDL.info) | ||
106 | |||
107 | if [ "$ref_version" = "$version" ]; then | ||
108 | ok "SDL.info Title $version" | ||
109 | else | ||
110 | not_ok "SDL.info Title $version disagrees with SDL_version.h $ref_version" | ||
111 | fi | ||
112 | |||
113 | marketing=$(sed -Ene 's/.*MARKETING_VERSION = (.*);/\1/p' Xcode/SDL/SDL.xcodeproj/project.pbxproj) | ||
114 | |||
115 | ref="$ref_version | ||
116 | $ref_version" | ||
117 | |||
118 | if [ "$ref" = "$marketing" ]; then | ||
119 | ok "project.pbxproj MARKETING_VERSION is consistent" | ||
120 | else | ||
121 | not_ok "project.pbxproj MARKETING_VERSION is inconsistent, expected $ref, got $marketing" | ||
122 | fi | ||
123 | |||
124 | # For simplicity this assumes we'll never break ABI before SDL 3. | ||
125 | dylib_compat=$(sed -Ene 's/.*DYLIB_COMPATIBILITY_VERSION = (.*);$/\1/p' Xcode/SDL/SDL.xcodeproj/project.pbxproj) | ||
126 | |||
127 | case "$ref_minor" in | ||
128 | (*[02468]) | ||
129 | major="$(( ref_minor * 100 + 1 ))" | ||
130 | minor="0" | ||
131 | ;; | ||
132 | (*) | ||
133 | major="$(( ref_minor * 100 + ref_micro + 1 ))" | ||
134 | minor="0" | ||
135 | ;; | ||
136 | esac | ||
137 | |||
138 | ref="${major}.${minor}.0 | ||
139 | ${major}.${minor}.0" | ||
140 | |||
141 | if [ "$ref" = "$dylib_compat" ]; then | ||
142 | ok "project.pbxproj DYLIB_COMPATIBILITY_VERSION is consistent" | ||
143 | else | ||
144 | not_ok "project.pbxproj DYLIB_COMPATIBILITY_VERSION is inconsistent, expected $ref, got $dylib_compat" | ||
145 | fi | ||
146 | |||
147 | dylib_cur=$(sed -Ene 's/.*DYLIB_CURRENT_VERSION = (.*);$/\1/p' Xcode/SDL/SDL.xcodeproj/project.pbxproj) | ||
148 | |||
149 | case "$ref_minor" in | ||
150 | (*[02468]) | ||
151 | major="$(( ref_minor * 100 + 1 ))" | ||
152 | minor="$ref_micro" | ||
153 | ;; | ||
154 | (*) | ||
155 | major="$(( ref_minor * 100 + ref_micro + 1 ))" | ||
156 | minor="0" | ||
157 | ;; | ||
158 | esac | ||
159 | |||
160 | ref="${major}.${minor}.0 | ||
161 | ${major}.${minor}.0" | ||
162 | |||
163 | if [ "$ref" = "$dylib_cur" ]; then | ||
164 | ok "project.pbxproj DYLIB_CURRENT_VERSION is consistent" | ||
165 | else | ||
166 | not_ok "project.pbxproj DYLIB_CURRENT_VERSION is inconsistent, expected $ref, got $dylib_cur" | ||
167 | fi | ||
168 | |||
169 | echo "1..$tests" | ||
170 | exit "$failed" | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/update-copyright.sh b/src/contrib/SDL-3.2.20/build-scripts/update-copyright.sh new file mode 100755 index 0000000..9bb46ea --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/update-copyright.sh | |||
@@ -0,0 +1,15 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | if [ "$SED" = "" ]; then | ||
4 | if type gsed >/dev/null; then | ||
5 | SED=gsed | ||
6 | else | ||
7 | SED=sed | ||
8 | fi | ||
9 | fi | ||
10 | |||
11 | find . -type f \ | ||
12 | | grep -v \.git \ | ||
13 | | while read file; do \ | ||
14 | LC_ALL=C $SED -b -i "s/\(.*Copyright.*\)[0-9]\{4\}\( *Sam Lantinga\)/\1`date +%Y`\2/" "$file"; \ | ||
15 | done | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/update-version.sh b/src/contrib/SDL-3.2.20/build-scripts/update-version.sh new file mode 100755 index 0000000..86ae816 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/update-version.sh | |||
@@ -0,0 +1,81 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | #set -x | ||
4 | |||
5 | cd `dirname $0`/.. | ||
6 | |||
7 | ARGSOKAY=1 | ||
8 | if [ -z $1 ]; then | ||
9 | ARGSOKAY=0 | ||
10 | fi | ||
11 | if [ -z $2 ]; then | ||
12 | ARGSOKAY=0 | ||
13 | fi | ||
14 | if [ -z $3 ]; then | ||
15 | ARGSOKAY=0 | ||
16 | fi | ||
17 | |||
18 | if [ "x$ARGSOKAY" = "x0" ]; then | ||
19 | echo "USAGE: $0 <major> <minor> <patch>" 1>&2 | ||
20 | exit 1 | ||
21 | fi | ||
22 | |||
23 | MAJOR="$1" | ||
24 | MINOR="$2" | ||
25 | MICRO="$3" | ||
26 | NEWVERSION="$MAJOR.$MINOR.$MICRO" | ||
27 | |||
28 | echo "Updating version to '$NEWVERSION' ..." | ||
29 | |||
30 | perl -w -pi -e 's/\A(.* version )[0-9.]+/${1}'$NEWVERSION'/;' include/SDL3/SDL.h | ||
31 | |||
32 | # !!! FIXME: This first one is a kinda scary search/replace that might fail later if another X.Y.Z version is added to the file. | ||
33 | perl -w -pi -e 's/(\<string\>)\d+\.\d+\.\d+/${1}'$NEWVERSION'/;' Xcode/SDL/Info-Framework.plist | ||
34 | |||
35 | perl -w -pi -e 's/(Title SDL )\d+\.\d+\.\d+/${1}'$NEWVERSION'/;' Xcode/SDL/pkg-support/SDL.info | ||
36 | |||
37 | perl -w -pi -e 's/(MARKETING_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$NEWVERSION'/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
38 | |||
39 | DYVER=`expr $MINOR \* 100 + 1` | ||
40 | perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
41 | |||
42 | # Set compat to major.minor.0 by default. | ||
43 | perl -w -pi -e 's/(DYLIB_COMPATIBILITY_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
44 | |||
45 | # non-zero patch? | ||
46 | if [ "x$MICRO" != "x0" ]; then | ||
47 | if [ `expr $MINOR % 2` = "0" ]; then | ||
48 | # If patch is not zero, but minor is even, it's a bugfix release. | ||
49 | perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.'$MICRO'.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
50 | |||
51 | else | ||
52 | # If patch is not zero, but minor is odd, it's a development prerelease. | ||
53 | DYVER=`expr $MINOR \* 100 + $MICRO + 1` | ||
54 | perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
55 | perl -w -pi -e 's/(DYLIB_COMPATIBILITY_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj | ||
56 | fi | ||
57 | fi | ||
58 | |||
59 | perl -w -pi -e 's/\A(project\(SDL[0-9]+ LANGUAGES C VERSION ")[0-9.]+/${1}'$NEWVERSION'/;' CMakeLists.txt | ||
60 | |||
61 | perl -w -pi -e 's/\A(.* SDL_MAJOR_VERSION = )\d+/${1}'$MAJOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java | ||
62 | perl -w -pi -e 's/\A(.* SDL_MINOR_VERSION = )\d+/${1}'$MINOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java | ||
63 | perl -w -pi -e 's/\A(.* SDL_MICRO_VERSION = )\d+/${1}'$MICRO'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java | ||
64 | |||
65 | perl -w -pi -e 's/(\#define SDL_MAJOR_VERSION\s+)\d+/${1}'$MAJOR'/;' include/SDL3/SDL_version.h | ||
66 | perl -w -pi -e 's/(\#define SDL_MINOR_VERSION\s+)\d+/${1}'$MINOR'/;' include/SDL3/SDL_version.h | ||
67 | perl -w -pi -e 's/(\#define SDL_MICRO_VERSION\s+)\d+/${1}'$MICRO'/;' include/SDL3/SDL_version.h | ||
68 | |||
69 | perl -w -pi -e 's/(FILEVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$MICRO'/;' src/core/windows/version.rc | ||
70 | perl -w -pi -e 's/(PRODUCTVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$MICRO'/;' src/core/windows/version.rc | ||
71 | perl -w -pi -e 's/(VALUE "FileVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$MICRO'/;' src/core/windows/version.rc | ||
72 | perl -w -pi -e 's/(VALUE "ProductVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$MICRO'/;' src/core/windows/version.rc | ||
73 | |||
74 | echo "Running build-scripts/test-versioning.sh to verify changes..." | ||
75 | ./build-scripts/test-versioning.sh | ||
76 | |||
77 | echo "All done." | ||
78 | echo "Run 'git diff' and make sure this looks correct, before 'git commit'." | ||
79 | |||
80 | exit 0 | ||
81 | |||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/updaterev.sh b/src/contrib/SDL-3.2.20/build-scripts/updaterev.sh new file mode 100755 index 0000000..508c6dd --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/updaterev.sh | |||
@@ -0,0 +1,48 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Generate a header file with the current source revision | ||
4 | |||
5 | outdir=`pwd` | ||
6 | cd `dirname $0` | ||
7 | srcdir=.. | ||
8 | header=$outdir/include/SDL3/SDL_revision.h | ||
9 | dist= | ||
10 | vendor= | ||
11 | |||
12 | while [ "$#" -gt 0 ]; do | ||
13 | case "$1" in | ||
14 | (--dist) | ||
15 | dist=yes | ||
16 | shift | ||
17 | ;; | ||
18 | (--vendor) | ||
19 | vendor="$2" | ||
20 | shift 2 | ||
21 | ;; | ||
22 | (*) | ||
23 | echo "$0: Unknown option: $1" >&2 | ||
24 | exit 2 | ||
25 | ;; | ||
26 | esac | ||
27 | done | ||
28 | |||
29 | rev=`sh showrev.sh 2>/dev/null` | ||
30 | if [ "$rev" != "" ]; then | ||
31 | if [ -n "$dist" ]; then | ||
32 | echo "$rev" > "$outdir/VERSION.txt" | ||
33 | fi | ||
34 | echo "/* Generated by updaterev.sh, do not edit */" >"$header.new" | ||
35 | if [ -n "$vendor" ]; then | ||
36 | echo "#define SDL_VENDOR_INFO \"$vendor\"" >>"$header.new" | ||
37 | fi | ||
38 | echo "#ifdef SDL_VENDOR_INFO" >>"$header.new" | ||
39 | echo "#define SDL_REVISION \"SDL-$rev (\" SDL_VENDOR_INFO \")\"" >>"$header.new" | ||
40 | echo "#else" >>"$header.new" | ||
41 | echo "#define SDL_REVISION \"SDL-$rev\"" >>"$header.new" | ||
42 | echo "#endif" >>"$header.new" | ||
43 | if diff $header $header.new >/dev/null 2>&1; then | ||
44 | rm "$header.new" | ||
45 | else | ||
46 | mv "$header.new" "$header" | ||
47 | fi | ||
48 | fi | ||
diff --git a/src/contrib/SDL-3.2.20/build-scripts/wikiheaders.pl b/src/contrib/SDL-3.2.20/build-scripts/wikiheaders.pl new file mode 100755 index 0000000..d4205b8 --- /dev/null +++ b/src/contrib/SDL-3.2.20/build-scripts/wikiheaders.pl | |||
@@ -0,0 +1,3408 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | # Simple DirectMedia Layer | ||
4 | # Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
5 | # | ||
6 | # This software is provided 'as-is', without any express or implied | ||
7 | # warranty. In no event will the authors be held liable for any damages | ||
8 | # arising from the use of this software. | ||
9 | # | ||
10 | # Permission is granted to anyone to use this software for any purpose, | ||
11 | # including commercial applications, and to alter it and redistribute it | ||
12 | # freely, subject to the following restrictions: | ||
13 | # | ||
14 | # 1. The origin of this software must not be misrepresented; you must not | ||
15 | # claim that you wrote the original software. If you use this software | ||
16 | # in a product, an acknowledgment in the product documentation would be | ||
17 | # appreciated but is not required. | ||
18 | # 2. Altered source versions must be plainly marked as such, and must not be | ||
19 | # misrepresented as being the original software. | ||
20 | # 3. This notice may not be removed or altered from any source distribution. | ||
21 | |||
22 | use warnings; | ||
23 | use strict; | ||
24 | use File::Path; | ||
25 | use Text::Wrap; | ||
26 | |||
27 | $Text::Wrap::huge = 'overflow'; | ||
28 | |||
29 | my $projectfullname = 'Simple Directmedia Layer'; | ||
30 | my $projectshortname = 'SDL'; | ||
31 | my $wikisubdir = ''; | ||
32 | my $incsubdir = 'include'; | ||
33 | my $readmesubdir = undef; | ||
34 | my $apiprefixregex = undef; | ||
35 | my $versionfname = 'include/SDL_version.h'; | ||
36 | my $versionmajorregex = '\A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z'; | ||
37 | my $versionminorregex = '\A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z'; | ||
38 | my $versionmicroregex = '\A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z'; | ||
39 | my $mainincludefname = 'SDL.h'; | ||
40 | my $selectheaderregex = '\ASDL.*?\.h\Z'; | ||
41 | my $projecturl = 'https://libsdl.org/'; | ||
42 | my $wikiurl = 'https://wiki.libsdl.org'; | ||
43 | my $bugreporturl = 'https://github.com/libsdl-org/sdlwiki/issues/new'; | ||
44 | my $srcpath = undef; | ||
45 | my $wikipath = undef; | ||
46 | my $wikireadmesubdir = 'README'; | ||
47 | my $warn_about_missing = 0; | ||
48 | my $copy_direction = 0; | ||
49 | my $optionsfname = undef; | ||
50 | my $wikipreamble = undef; | ||
51 | my $wikiheaderfiletext = 'Defined in %fname%'; | ||
52 | my $manpageheaderfiletext = 'Defined in %fname%'; | ||
53 | my $manpagesymbolfilterregex = undef; | ||
54 | my $headercategoryeval = undef; | ||
55 | my $quickrefenabled = 0; | ||
56 | my @quickrefcategoryorder; | ||
57 | my $quickreftitle = undef; | ||
58 | my $quickrefurl = undef; | ||
59 | my $quickrefdesc = undef; | ||
60 | my $quickrefmacroregex = undef; | ||
61 | my $changeformat = undef; | ||
62 | my $manpath = undef; | ||
63 | my $gitrev = undef; | ||
64 | |||
65 | foreach (@ARGV) { | ||
66 | $warn_about_missing = 1, next if $_ eq '--warn-about-missing'; | ||
67 | $copy_direction = 1, next if $_ eq '--copy-to-headers'; | ||
68 | $copy_direction = 1, next if $_ eq '--copy-to-header'; | ||
69 | $copy_direction = -1, next if $_ eq '--copy-to-wiki'; | ||
70 | $copy_direction = -2, next if $_ eq '--copy-to-manpages'; | ||
71 | $copy_direction = -3, next if $_ eq '--report-coverage-gaps'; | ||
72 | $copy_direction = -4, next if $_ eq '--copy-to-latex'; | ||
73 | if (/\A--options=(.*)\Z/) { | ||
74 | $optionsfname = $1; | ||
75 | next; | ||
76 | } elsif (/\A--changeformat=(.*)\Z/) { | ||
77 | $changeformat = $1; | ||
78 | next; | ||
79 | } elsif (/\A--manpath=(.*)\Z/) { | ||
80 | $manpath = $1; | ||
81 | next; | ||
82 | } elsif (/\A--rev=(.*)\Z/) { | ||
83 | $gitrev = $1; | ||
84 | next; | ||
85 | } | ||
86 | $srcpath = $_, next if not defined $srcpath; | ||
87 | $wikipath = $_, next if not defined $wikipath; | ||
88 | } | ||
89 | |||
90 | my $default_optionsfname = '.wikiheaders-options'; | ||
91 | $default_optionsfname = "$srcpath/$default_optionsfname" if defined $srcpath; | ||
92 | |||
93 | if ((not defined $optionsfname) && (-f $default_optionsfname)) { | ||
94 | $optionsfname = $default_optionsfname; | ||
95 | } | ||
96 | |||
97 | if (defined $optionsfname) { | ||
98 | open OPTIONS, '<', $optionsfname or die("Failed to open options file '$optionsfname': $!\n"); | ||
99 | while (<OPTIONS>) { | ||
100 | next if /\A\s*\#/; # Skip lines that start with (optional whitespace, then) '#' as comments. | ||
101 | |||
102 | chomp; | ||
103 | if (/\A(.*?)\=(.*)\Z/) { | ||
104 | my $key = $1; | ||
105 | my $val = $2; | ||
106 | $key =~ s/\A\s+//; | ||
107 | $key =~ s/\s+\Z//; | ||
108 | $val =~ s/\A\s+//; | ||
109 | $val =~ s/\s+\Z//; | ||
110 | $warn_about_missing = int($val), next if $key eq 'warn_about_missing'; | ||
111 | $srcpath = $val, next if $key eq 'srcpath'; | ||
112 | $wikipath = $val, next if $key eq 'wikipath'; | ||
113 | $apiprefixregex = $val, next if $key eq 'apiprefixregex'; | ||
114 | $projectfullname = $val, next if $key eq 'projectfullname'; | ||
115 | $projectshortname = $val, next if $key eq 'projectshortname'; | ||
116 | $wikisubdir = $val, next if $key eq 'wikisubdir'; | ||
117 | $incsubdir = $val, next if $key eq 'incsubdir'; | ||
118 | $readmesubdir = $val, next if $key eq 'readmesubdir'; | ||
119 | $versionmajorregex = $val, next if $key eq 'versionmajorregex'; | ||
120 | $versionminorregex = $val, next if $key eq 'versionminorregex'; | ||
121 | $versionmicroregex = $val, next if $key eq 'versionmicroregex'; | ||
122 | $versionfname = $val, next if $key eq 'versionfname'; | ||
123 | $mainincludefname = $val, next if $key eq 'mainincludefname'; | ||
124 | $selectheaderregex = $val, next if $key eq 'selectheaderregex'; | ||
125 | $projecturl = $val, next if $key eq 'projecturl'; | ||
126 | $wikiurl = $val, next if $key eq 'wikiurl'; | ||
127 | $bugreporturl = $val, next if $key eq 'bugreporturl'; | ||
128 | $wikipreamble = $val, next if $key eq 'wikipreamble'; | ||
129 | $wikiheaderfiletext = $val, next if $key eq 'wikiheaderfiletext'; | ||
130 | $manpageheaderfiletext = $val, next if $key eq 'manpageheaderfiletext'; | ||
131 | $manpagesymbolfilterregex = $val, next if $key eq 'manpagesymbolfilterregex'; | ||
132 | $headercategoryeval = $val, next if $key eq 'headercategoryeval'; | ||
133 | $quickrefenabled = int($val), next if $key eq 'quickrefenabled'; | ||
134 | @quickrefcategoryorder = split(/,/, $val), next if $key eq 'quickrefcategoryorder'; | ||
135 | $quickreftitle = $val, next if $key eq 'quickreftitle'; | ||
136 | $quickrefurl = $val, next if $key eq 'quickrefurl'; | ||
137 | $quickrefdesc = $val, next if $key eq 'quickrefdesc'; | ||
138 | $quickrefmacroregex = $val, next if $key eq 'quickrefmacroregex'; | ||
139 | } | ||
140 | } | ||
141 | close(OPTIONS); | ||
142 | } | ||
143 | |||
144 | sub escLaTeX { | ||
145 | my $str = shift; | ||
146 | $str =~ s/([_\#\&\^])/\\$1/g; | ||
147 | return $str; | ||
148 | } | ||
149 | |||
150 | my $wordwrap_mode = 'mediawiki'; | ||
151 | sub wordwrap_atom { # don't call this directly. | ||
152 | my $str = shift; | ||
153 | my $retval = ''; | ||
154 | |||
155 | # wordwrap but leave links intact, even if they overflow. | ||
156 | if ($wordwrap_mode eq 'mediawiki') { | ||
157 | while ($str =~ s/(.*?)\s*(\[https?\:\/\/.*?\s+.*?\])\s*//ms) { | ||
158 | $retval .= fill('', '', $1); # wrap it. | ||
159 | $retval .= "\n$2\n"; # don't wrap it. | ||
160 | } | ||
161 | } elsif ($wordwrap_mode eq 'md') { | ||
162 | while ($str =~ s/(.*?)\s*(\[.*?\]\(https?\:\/\/.*?\))\s*//ms) { | ||
163 | $retval .= fill('', '', $1); # wrap it. | ||
164 | $retval .= "\n$2\n"; # don't wrap it. | ||
165 | } | ||
166 | } | ||
167 | |||
168 | return $retval . fill('', '', $str); | ||
169 | } | ||
170 | |||
171 | sub wordwrap_with_bullet_indent { # don't call this directly. | ||
172 | my $bullet = shift; | ||
173 | my $str = shift; | ||
174 | my $retval = ''; | ||
175 | |||
176 | #print("WORDWRAP BULLET ('$bullet'):\n\n$str\n\n"); | ||
177 | |||
178 | # You _can't_ (at least with Pandoc) have a bullet item with a newline in | ||
179 | # MediaWiki, so _remove_ wrapping! | ||
180 | if ($wordwrap_mode eq 'mediawiki') { | ||
181 | $retval = "$bullet$str"; | ||
182 | $retval =~ s/\n/ /gms; | ||
183 | $retval =~ s/\s+$//gms; | ||
184 | #print("WORDWRAP BULLET DONE:\n\n$retval\n\n"); | ||
185 | return "$retval\n"; | ||
186 | } | ||
187 | |||
188 | my $bulletlen = length($bullet); | ||
189 | |||
190 | # wrap it and then indent each line to be under the bullet. | ||
191 | $Text::Wrap::columns -= $bulletlen; | ||
192 | my @wrappedlines = split /\n/, wordwrap_atom($str); | ||
193 | $Text::Wrap::columns += $bulletlen; | ||
194 | |||
195 | my $prefix = $bullet; | ||
196 | my $usual_prefix = ' ' x $bulletlen; | ||
197 | |||
198 | foreach (@wrappedlines) { | ||
199 | s/\s*\Z//; | ||
200 | $retval .= "$prefix$_\n"; | ||
201 | $prefix = $usual_prefix; | ||
202 | } | ||
203 | |||
204 | return $retval; | ||
205 | } | ||
206 | |||
207 | sub wordwrap_one_paragraph { # don't call this directly. | ||
208 | my $retval = ''; | ||
209 | my $p = shift; | ||
210 | #print "\n\n\nPARAGRAPH: [$p]\n\n\n"; | ||
211 | if ($p =~ s/\A([\*\-] )//) { # bullet list, starts with "* " or "- ". | ||
212 | my $bullet = $1; | ||
213 | my $item = ''; | ||
214 | my @items = split /\n/, $p; | ||
215 | foreach (@items) { | ||
216 | if (s/\A([\*\-] )//) { | ||
217 | $retval .= wordwrap_with_bullet_indent($bullet, $item); | ||
218 | $item = ''; | ||
219 | } | ||
220 | s/\A\s*//; | ||
221 | $item .= "$_\n"; # accumulate lines until we hit the end or another bullet. | ||
222 | } | ||
223 | if ($item ne '') { | ||
224 | $retval .= wordwrap_with_bullet_indent($bullet, $item); | ||
225 | } | ||
226 | } elsif ($p =~ /\A\s*\|.*\|\s*\n/) { # Markdown table | ||
227 | $retval = "$p\n"; # don't wrap it (!!! FIXME: but maybe parse by lines until we run out of table...) | ||
228 | } else { | ||
229 | $retval = wordwrap_atom($p) . "\n"; | ||
230 | } | ||
231 | |||
232 | return $retval; | ||
233 | } | ||
234 | |||
235 | sub wordwrap_paragraphs { # don't call this directly. | ||
236 | my $str = shift; | ||
237 | my $retval = ''; | ||
238 | my @paragraphs = split /\n\n/, $str; | ||
239 | foreach (@paragraphs) { | ||
240 | next if $_ eq ''; | ||
241 | $retval .= wordwrap_one_paragraph($_); | ||
242 | $retval .= "\n"; | ||
243 | } | ||
244 | return $retval; | ||
245 | } | ||
246 | |||
247 | my $wordwrap_default_columns = 76; | ||
248 | sub wordwrap { | ||
249 | my $str = shift; | ||
250 | my $columns = shift; | ||
251 | |||
252 | $columns = $wordwrap_default_columns if not defined $columns; | ||
253 | $columns += $wordwrap_default_columns if $columns < 0; | ||
254 | $Text::Wrap::columns = $columns; | ||
255 | |||
256 | my $retval = ''; | ||
257 | |||
258 | #print("\n\nWORDWRAP:\n\n$str\n\n\n"); | ||
259 | |||
260 | $str =~ s/\A\n+//ms; | ||
261 | |||
262 | while ($str =~ s/(.*?)(\`\`\`.*?\`\`\`|\<syntaxhighlight.*?\<\/syntaxhighlight\>)//ms) { | ||
263 | #print("\n\nWORDWRAP BLOCK:\n\n$1\n\n ===\n\n$2\n\n\n"); | ||
264 | $retval .= wordwrap_paragraphs($1); # wrap it. | ||
265 | $retval .= "$2\n\n"; # don't wrap it. | ||
266 | } | ||
267 | |||
268 | $retval .= wordwrap_paragraphs($str); # wrap what's left. | ||
269 | $retval =~ s/\n+\Z//ms; | ||
270 | |||
271 | #print("\n\nWORDWRAP DONE:\n\n$retval\n\n\n"); | ||
272 | return $retval; | ||
273 | } | ||
274 | |||
275 | # This assumes you're moving from Markdown (in the Doxygen data) to Wiki, which | ||
276 | # is why the 'md' section is so sparse. | ||
277 | sub wikify_chunk { | ||
278 | my $wikitype = shift; | ||
279 | my $str = shift; | ||
280 | my $codelang = shift; | ||
281 | my $code = shift; | ||
282 | |||
283 | #print("\n\nWIKIFY CHUNK:\n\n$str\n\n\n"); | ||
284 | |||
285 | if ($wikitype eq 'mediawiki') { | ||
286 | # convert `code` things first, so they aren't mistaken for other markdown items. | ||
287 | my $codedstr = ''; | ||
288 | while ($str =~ s/\A(.*?)\`(.*?)\`//ms) { | ||
289 | my $codeblock = $2; | ||
290 | $codedstr .= wikify_chunk($wikitype, $1, undef, undef); | ||
291 | if (defined $apiprefixregex) { | ||
292 | # Convert obvious API things to wikilinks, even inside `code` blocks. | ||
293 | $codeblock =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[\[$2\]\]/gms; | ||
294 | } | ||
295 | $codedstr .= "<code>$codeblock</code>"; | ||
296 | } | ||
297 | |||
298 | # Convert obvious API things to wikilinks. | ||
299 | if (defined $apiprefixregex) { | ||
300 | $str =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[\[$2\]\]/gms; | ||
301 | } | ||
302 | |||
303 | # Make some Markdown things into MediaWiki... | ||
304 | |||
305 | # links | ||
306 | $str =~ s/\[(.*?)\]\((https?\:\/\/.*?)\)/\[$2 $1\]/g; | ||
307 | |||
308 | # bold+italic | ||
309 | $str =~ s/\*\*\*(.*?)\*\*\*/'''''$1'''''/gms; | ||
310 | |||
311 | # bold | ||
312 | $str =~ s/\*\*(.*?)\*\*/'''$1'''/gms; | ||
313 | |||
314 | # italic | ||
315 | $str =~ s/\*(.*?)\*/''$1''/gms; | ||
316 | |||
317 | # bullets | ||
318 | $str =~ s/^\- /* /gm; | ||
319 | |||
320 | $str = $codedstr . $str; | ||
321 | |||
322 | if (defined $code) { | ||
323 | $str .= "<syntaxhighlight lang='$codelang'>$code<\/syntaxhighlight>"; | ||
324 | } | ||
325 | } elsif ($wikitype eq 'md') { | ||
326 | # convert `code` things first, so they aren't mistaken for other markdown items. | ||
327 | my $codedstr = ''; | ||
328 | while ($str =~ s/\A(.*?)(\`.*?\`)//ms) { | ||
329 | my $codeblock = $2; | ||
330 | $codedstr .= wikify_chunk($wikitype, $1, undef, undef); | ||
331 | if (defined $apiprefixregex) { | ||
332 | # Convert obvious API things to wikilinks, even inside `code` blocks, | ||
333 | # BUT ONLY IF the entire code block is the API thing, | ||
334 | # So something like "just call `SDL_Whatever`" will become | ||
335 | # "just call [`SDL_Whatever`](SDL_Whatever)", but | ||
336 | # "just call `SDL_Whatever(7)`" will not. It's just the safest | ||
337 | # way to do this without resorting to wrapping things in html <code> tags. | ||
338 | $codeblock =~ s/\A\`($apiprefixregex[a-zA-Z0-9_]+)\`\Z/[`$1`]($1)/gms; | ||
339 | } | ||
340 | $codedstr .= $codeblock; | ||
341 | } | ||
342 | |||
343 | # Convert obvious API things to wikilinks. | ||
344 | if (defined $apiprefixregex) { | ||
345 | $str =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[$2\]\($2\)/gms; | ||
346 | } | ||
347 | |||
348 | $str = $codedstr . $str; | ||
349 | |||
350 | if (defined $code) { | ||
351 | $str .= "```$codelang\n$code\n```\n"; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | #print("\n\nWIKIFY CHUNK DONE:\n\n$str\n\n\n"); | ||
356 | |||
357 | return $str; | ||
358 | } | ||
359 | |||
360 | sub wikify { | ||
361 | my $wikitype = shift; | ||
362 | my $str = shift; | ||
363 | my $retval = ''; | ||
364 | |||
365 | #print("WIKIFY WHOLE:\n\n$str\n\n\n"); | ||
366 | |||
367 | while ($str =~ s/\A(.*?)\`\`\`(.*?)\n(.*?)\n\`\`\`(\n|\Z)//ms) { | ||
368 | $retval .= wikify_chunk($wikitype, $1, $2, $3); | ||
369 | } | ||
370 | $retval .= wikify_chunk($wikitype, $str, undef, undef); | ||
371 | |||
372 | #print("WIKIFY WHOLE DONE:\n\n$retval\n\n\n"); | ||
373 | |||
374 | return $retval; | ||
375 | } | ||
376 | |||
377 | |||
378 | my $dewikify_mode = 'md'; | ||
379 | my $dewikify_manpage_code_indent = 1; | ||
380 | |||
381 | sub dewikify_chunk { | ||
382 | my $wikitype = shift; | ||
383 | my $str = shift; | ||
384 | my $codelang = shift; | ||
385 | my $code = shift; | ||
386 | |||
387 | #print("\n\nDEWIKIFY CHUNK:\n\n$str\n\n\n"); | ||
388 | |||
389 | if ($dewikify_mode eq 'md') { | ||
390 | if ($wikitype eq 'mediawiki') { | ||
391 | # Doxygen supports Markdown (and it just simply looks better than MediaWiki | ||
392 | # when looking at the raw headers), so do some conversions here as necessary. | ||
393 | |||
394 | # Dump obvious wikilinks. | ||
395 | if (defined $apiprefixregex) { | ||
396 | $str =~ s/\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]/$1/gms; | ||
397 | } | ||
398 | |||
399 | # links | ||
400 | $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\[$2\]\($1\)/g; | ||
401 | |||
402 | # <code></code> is also popular. :/ | ||
403 | $str =~ s/\<code>(.*?)<\/code>/`$1`/gms; | ||
404 | |||
405 | # bold+italic | ||
406 | $str =~ s/'''''(.*?)'''''/***$1***/gms; | ||
407 | |||
408 | # bold | ||
409 | $str =~ s/'''(.*?)'''/**$1**/gms; | ||
410 | |||
411 | # italic | ||
412 | $str =~ s/''(.*?)''/*$1*/gms; | ||
413 | |||
414 | # bullets | ||
415 | $str =~ s/^\* /- /gm; | ||
416 | } elsif ($wikitype eq 'md') { | ||
417 | # Dump obvious wikilinks. The rest can just passthrough. | ||
418 | if (defined $apiprefixregex) { | ||
419 | $str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/$1/gms; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (defined $code) { | ||
424 | $str .= "\n```$codelang\n$code\n```\n"; | ||
425 | } | ||
426 | } elsif ($dewikify_mode eq 'manpage') { | ||
427 | # make sure these can't become part of roff syntax. | ||
428 | $str =~ s/\./\\[char46]/gms; | ||
429 | $str =~ s/"/\\(dq/gms; | ||
430 | $str =~ s/'/\\(aq/gms; | ||
431 | |||
432 | if ($wikitype eq 'mediawiki') { | ||
433 | # Dump obvious wikilinks. | ||
434 | if (defined $apiprefixregex) { | ||
435 | $str =~ s/\s*\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]\s*/\n.BR $1\n/gms; | ||
436 | } | ||
437 | |||
438 | # links | ||
439 | $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\n.URL "$1" "$2"\n/g; | ||
440 | |||
441 | # <code></code> is also popular. :/ | ||
442 | $str =~ s/\s*\<code>(.*?)<\/code>\s*/\n.BR $1\n/gms; | ||
443 | |||
444 | # bold+italic (this looks bad, just make it bold). | ||
445 | $str =~ s/\s*'''''(.*?)'''''\s*/\n.B $1\n/gms; | ||
446 | |||
447 | # bold | ||
448 | $str =~ s/\s*'''(.*?)'''\s*/\n.B $1\n/gms; | ||
449 | |||
450 | # italic | ||
451 | $str =~ s/\s*''(.*?)''\s*/\n.I $1\n/gms; | ||
452 | |||
453 | # bullets | ||
454 | $str =~ s/^\* /\n\\\(bu /gm; | ||
455 | } elsif ($wikitype eq 'md') { | ||
456 | # bullets | ||
457 | $str =~ s/^\- /\n\\(bu /gm; | ||
458 | # merge paragraphs | ||
459 | $str =~ s/^[ \t]+//gm; | ||
460 | $str =~ s/([^\-\n])\n([^\-\n])/$1 $2/g; | ||
461 | $str =~ s/\n\n/\n.PP\n/g; | ||
462 | |||
463 | # Dump obvious wikilinks. | ||
464 | if (defined $apiprefixregex) { | ||
465 | my $apr = $apiprefixregex; | ||
466 | if(!($apr =~ /\A\(.*\)\Z/s)) { | ||
467 | # we're relying on the apiprefixregex having a capturing group. | ||
468 | $apr = "(" . $apr . ")"; | ||
469 | } | ||
470 | $str =~ s/(\S*?)\[\`?($apr[a-zA-Z0-9_]+)\`?\]\($apr[a-zA-Z0-9_]+\)(\S*)\s*/\n.BR "" "$1" "$2" "$5"\n/gm; | ||
471 | # handle cases like "[x](x), [y](y), [z](z)" being separated. | ||
472 | while($str =~ s/(\.BR[^\n]*)\n\n\.BR/$1\n.BR/gm) {} | ||
473 | } | ||
474 | |||
475 | # links | ||
476 | $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g; | ||
477 | |||
478 | # <code></code> is also popular. :/ | ||
479 | $str =~ s/\s*(\S*?)\`([^\n]*?)\`(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms; | ||
480 | |||
481 | # bold+italic (this looks bad, just make it bold). | ||
482 | $str =~ s/\s*(\S*?)\*\*\*([^\n]*?)\*\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms; | ||
483 | |||
484 | # bold | ||
485 | $str =~ s/\s*(\S*?)\*\*([^\n]*?)\*\*(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms; | ||
486 | |||
487 | # italic | ||
488 | $str =~ s/\s*(\S*?)\*([^\n]*?)\*(\S*)\s*/\n.IR "" "$1" "$2" "$3"\n/gms; | ||
489 | } | ||
490 | |||
491 | # cleanup unnecessary quotes | ||
492 | $str =~ s/(\.[IB]R?)(.*?) ""\n/$1$2\n/gm; | ||
493 | $str =~ s/(\.[IB]R?) "" ""(.*?)\n/$1$2\n/gm; | ||
494 | $str =~ s/"(\S+)"/$1/gm; | ||
495 | # cleanup unnecessary whitespace | ||
496 | $str =~ s/ +\n/\n/gm; | ||
497 | |||
498 | if (defined $code) { | ||
499 | $code =~ s/\A\n+//gms; | ||
500 | $code =~ s/\n+\Z//gms; | ||
501 | $code =~ s/\\/\\(rs/gms; | ||
502 | if ($dewikify_manpage_code_indent) { | ||
503 | $str .= "\n.IP\n" | ||
504 | } else { | ||
505 | $str .= "\n.PP\n" | ||
506 | } | ||
507 | $str .= ".EX\n$code\n.EE\n.PP\n"; | ||
508 | } | ||
509 | } elsif ($dewikify_mode eq 'LaTeX') { | ||
510 | if ($wikitype eq 'mediawiki') { | ||
511 | # Dump obvious wikilinks. | ||
512 | if (defined $apiprefixregex) { | ||
513 | $str =~ s/\s*\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]/$1/gms; | ||
514 | } | ||
515 | |||
516 | # links | ||
517 | $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\\href{$1}{$2}/g; | ||
518 | |||
519 | # <code></code> is also popular. :/ | ||
520 | $str =~ s/\s*\<code>(.*?)<\/code>/ \\texttt{$1}/gms; | ||
521 | |||
522 | # bold+italic | ||
523 | $str =~ s/\s*'''''(.*?)'''''/ \\textbf{\\textit{$1}}/gms; | ||
524 | |||
525 | # bold | ||
526 | $str =~ s/\s*'''(.*?)'''/ \\textbf{$1}/gms; | ||
527 | |||
528 | # italic | ||
529 | $str =~ s/\s*''(.*?)''/ \\textit{$1}/gms; | ||
530 | |||
531 | # bullets | ||
532 | $str =~ s/^\*\s+/ \\item /gm; | ||
533 | } elsif ($wikitype eq 'md') { | ||
534 | # Dump obvious wikilinks. | ||
535 | if (defined $apiprefixregex) { | ||
536 | $str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/$1/gms; | ||
537 | } | ||
538 | |||
539 | # links | ||
540 | $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\\href{$2}{$1}/g; | ||
541 | |||
542 | # <code></code> is also popular. :/ | ||
543 | $str =~ s/\s*\`(.*?)\`/ \\texttt{$1}/gms; | ||
544 | |||
545 | # bold+italic | ||
546 | $str =~ s/\s*\*\*\*(.*?)\*\*\*/ \\textbf{\\textit{$1}}/gms; | ||
547 | |||
548 | # bold | ||
549 | $str =~ s/\s*\*\*(.*?)\*\*/ \\textbf{$1}/gms; | ||
550 | |||
551 | # italic | ||
552 | $str =~ s/\s*\*(.*?)\*/ \\textit{$1}/gms; | ||
553 | |||
554 | # bullets | ||
555 | $str =~ s/^\-\s+/ \\item /gm; | ||
556 | } | ||
557 | |||
558 | # Wrap bullet lists in itemize blocks... | ||
559 | $str =~ s/^(\s*\\item .*?)(\n\n|\Z)/\n\\begin{itemize}\n$1$2\n\\end{itemize}\n\n/gms; | ||
560 | |||
561 | $str = escLaTeX($str); | ||
562 | |||
563 | if (defined $code) { | ||
564 | $code =~ s/\A\n+//gms; | ||
565 | $code =~ s/\n+\Z//gms; | ||
566 | |||
567 | if (($codelang eq '') || ($codelang eq 'output')) { | ||
568 | $str .= "\\begin{verbatim}\n$code\n\\end{verbatim}\n"; | ||
569 | } else { | ||
570 | if ($codelang eq 'c') { | ||
571 | $codelang = 'C'; | ||
572 | } elsif ($codelang eq 'c++') { | ||
573 | $codelang = 'C++'; | ||
574 | } else { | ||
575 | die("Unexpected codelang '$codelang'"); | ||
576 | } | ||
577 | $str .= "\n\\lstset{language=$codelang}\n"; | ||
578 | $str .= "\\begin{lstlisting}\n$code\n\\end{lstlisting}\n"; | ||
579 | } | ||
580 | } | ||
581 | } else { | ||
582 | die("Unexpected dewikify_mode"); | ||
583 | } | ||
584 | |||
585 | #print("\n\nDEWIKIFY CHUNK DONE:\n\n$str\n\n\n"); | ||
586 | |||
587 | return $str; | ||
588 | } | ||
589 | |||
590 | sub dewikify { | ||
591 | my $wikitype = shift; | ||
592 | my $str = shift; | ||
593 | return '' if not defined $str; | ||
594 | |||
595 | #print("DEWIKIFY WHOLE:\n\n$str\n\n\n"); | ||
596 | |||
597 | $str =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
598 | $str =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
599 | |||
600 | my $retval = ''; | ||
601 | if ($wikitype eq 'mediawiki') { | ||
602 | while ($str =~ s/\A(.*?)<syntaxhighlight lang='?(.*?)'?>(.*?)<\/syntaxhighlight\>//ms) { | ||
603 | $retval .= dewikify_chunk($wikitype, $1, $2, $3); | ||
604 | } | ||
605 | } elsif ($wikitype eq 'md') { | ||
606 | while ($str =~ s/\A(.*?)\n?```(.*?)\n(.*?)\n```\n//ms) { | ||
607 | $retval .= dewikify_chunk($wikitype, $1, $2, $3); | ||
608 | } | ||
609 | } | ||
610 | $retval .= dewikify_chunk($wikitype, $str, undef, undef); | ||
611 | |||
612 | #print("DEWIKIFY WHOLE DONE:\n\n$retval\n\n\n"); | ||
613 | |||
614 | return $retval; | ||
615 | } | ||
616 | |||
617 | sub filecopy { | ||
618 | my $src = shift; | ||
619 | my $dst = shift; | ||
620 | my $endline = shift; | ||
621 | $endline = "\n" if not defined $endline; | ||
622 | |||
623 | open(COPYIN, '<', $src) or die("Failed to open '$src' for reading: $!\n"); | ||
624 | open(COPYOUT, '>', $dst) or die("Failed to open '$dst' for writing: $!\n"); | ||
625 | while (<COPYIN>) { | ||
626 | chomp; | ||
627 | s/[ \t\r\n]*\Z//; | ||
628 | print COPYOUT "$_$endline"; | ||
629 | } | ||
630 | close(COPYOUT); | ||
631 | close(COPYIN); | ||
632 | } | ||
633 | |||
634 | sub usage { | ||
635 | die("USAGE: $0 <source code git clone path> <wiki git clone path> [--copy-to-headers|--copy-to-wiki|--copy-to-manpages] [--warn-about-missing] [--manpath=<man path>]\n\n"); | ||
636 | } | ||
637 | |||
638 | usage() if not defined $srcpath; | ||
639 | usage() if not defined $wikipath; | ||
640 | #usage() if $copy_direction == 0; | ||
641 | |||
642 | if (not defined $manpath) { | ||
643 | $manpath = "$srcpath/man"; | ||
644 | } | ||
645 | |||
646 | my @standard_wiki_sections = ( | ||
647 | 'Draft', | ||
648 | '[Brief]', | ||
649 | 'Deprecated', | ||
650 | 'Header File', | ||
651 | 'Syntax', | ||
652 | 'Function Parameters', | ||
653 | 'Macro Parameters', | ||
654 | 'Fields', | ||
655 | 'Values', | ||
656 | 'Return Value', | ||
657 | 'Remarks', | ||
658 | 'Thread Safety', | ||
659 | 'Version', | ||
660 | 'Code Examples', | ||
661 | 'See Also' | ||
662 | ); | ||
663 | |||
664 | # Sections that only ever exist in the wiki and shouldn't be deleted when | ||
665 | # not found in the headers. | ||
666 | my %only_wiki_sections = ( # The ones don't mean anything, I just need to check for key existence. | ||
667 | 'Draft', 1, | ||
668 | 'Code Examples', 1, | ||
669 | 'Header File', 1 | ||
670 | ); | ||
671 | |||
672 | |||
673 | my %headers = (); # $headers{"SDL_audio.h"} -> reference to an array of all lines of text in SDL_audio.h. | ||
674 | my %headersyms = (); # $headersyms{"SDL_OpenAudio"} -> string of header documentation for SDL_OpenAudio, with comment '*' bits stripped from the start. Newlines embedded! | ||
675 | my %headerdecls = (); | ||
676 | my %headersymslocation = (); # $headersymslocation{"SDL_OpenAudio"} -> name of header holding SDL_OpenAudio define ("SDL_audio.h" in this case). | ||
677 | my %headersymschunk = (); # $headersymschunk{"SDL_OpenAudio"} -> offset in array in %headers that should be replaced for this symbol. | ||
678 | my %headersymshasdoxygen = (); # $headersymshasdoxygen{"SDL_OpenAudio"} -> 1 if there was no existing doxygen for this function. | ||
679 | my %headersymstype = (); # $headersymstype{"SDL_OpenAudio"} -> 1 (function), 2 (macro), 3 (struct), 4 (enum), 5 (other typedef) | ||
680 | my %headersymscategory = (); # $headersymscategory{"SDL_OpenAudio"} -> 'Audio' ... this is set with a `/* WIKI CATEGEORY: Audio */` comment in the headers that sets it on all symbols until a new comment changes it. So usually, once at the top of the header file. | ||
681 | my %headercategorydocs = (); # $headercategorydocs{"Audio"} -> (fake) symbol for this category's documentation. Undefined if not documented. | ||
682 | my %headersymsparaminfo = (); # $headersymsparaminfo{"SDL_OpenAudio"} -> reference to array of parameters, pushed by name, then C type string, repeating. Undef'd if void params, or not a function. | ||
683 | my %headersymsrettype = (); # $headersymsrettype{"SDL_OpenAudio"} -> string of C datatype of return value. Undef'd if not a function. | ||
684 | my %wikitypes = (); # contains string of wiki page extension, like $wikitypes{"SDL_OpenAudio"} == 'mediawiki' | ||
685 | my %wikisyms = (); # contains references to hash of strings, each string being the full contents of a section of a wiki page, like $wikisyms{"SDL_OpenAudio"}{"Remarks"}. | ||
686 | my %wikisectionorder = (); # contains references to array, each array item being a key to a wikipage section in the correct order, like $wikisectionorder{"SDL_OpenAudio"}[2] == 'Remarks' | ||
687 | my %quickreffuncorder = (); # contains references to array, each array item being a key to a category with functions in the order they appear in the headers, like $quickreffuncorder{"Audio"}[0] == 'SDL_GetNumAudioDrivers' | ||
688 | |||
689 | my %referenceonly = (); # $referenceonly{"Y"} -> symbol name that this symbol is bound to. This makes wiki pages that say "See X" where "X" is a typedef and "Y" is a define attached to it. These pages are generated in the wiki only and do not bridge to the headers or manpages. | ||
690 | |||
691 | my @coverage_gap = (); # array of strings that weren't part of documentation, or blank, or basic preprocessor logic. Lets you see what this script is missing! | ||
692 | |||
693 | sub add_coverage_gap { | ||
694 | if ($copy_direction == -3) { # --report-coverage-gaps | ||
695 | my $text = shift; | ||
696 | my $dent = shift; | ||
697 | my $lineno = shift; | ||
698 | return if $text =~ /\A\s*\Z/; # skip blank lines | ||
699 | return if $text =~ /\A\s*\#\s*(if|el|endif|include)/; # skip preprocessor floof. | ||
700 | push @coverage_gap, "$dent:$lineno: $text"; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | sub print_undocumented_section { | ||
705 | my $fh = shift; | ||
706 | my $typestr = shift; | ||
707 | my $typeval = shift; | ||
708 | |||
709 | print $fh "## $typestr defined in the headers, but not in the wiki\n\n"; | ||
710 | my $header_only_sym = 0; | ||
711 | foreach (sort keys %headersyms) { | ||
712 | my $sym = $_; | ||
713 | if ((not defined $wikisyms{$sym}) && ($headersymstype{$sym} == $typeval)) { | ||
714 | print $fh "- [$sym]($sym)\n"; | ||
715 | $header_only_sym = 1; | ||
716 | } | ||
717 | } | ||
718 | if (!$header_only_sym) { | ||
719 | print $fh "(none)\n"; | ||
720 | } | ||
721 | print $fh "\n"; | ||
722 | |||
723 | if (0) { # !!! FIXME: this lists things that _shouldn't_ be in the headers, like MigrationGuide, etc, but also we don't know if they're functions, macros, etc at this point (can we parse that from the wiki page, though?) | ||
724 | print $fh "## $typestr defined in the wiki, but not in the headers\n\n"; | ||
725 | |||
726 | my $wiki_only_sym = 0; | ||
727 | foreach (sort keys %wikisyms) { | ||
728 | my $sym = $_; | ||
729 | if ((not defined $headersyms{$sym}) && ($headersymstype{$sym} == $typeval)) { | ||
730 | print $fh "- [$sym]($sym)\n"; | ||
731 | $wiki_only_sym = 1; | ||
732 | } | ||
733 | } | ||
734 | if (!$wiki_only_sym) { | ||
735 | print $fh "(none)\n"; | ||
736 | } | ||
737 | print $fh "\n"; | ||
738 | } | ||
739 | } | ||
740 | |||
741 | sub strip_fn_declaration_metadata { | ||
742 | my $decl = shift; | ||
743 | $decl =~ s/SDL_(PRINTF|SCANF)_FORMAT_STRING\s*//; # don't want this metadata as part of the documentation. | ||
744 | $decl =~ s/SDL_ALLOC_SIZE2?\(.*?\)\s*//; # don't want this metadata as part of the documentation. | ||
745 | $decl =~ s/SDL_MALLOC\s*//; # don't want this metadata as part of the documentation. | ||
746 | $decl =~ s/SDL_(IN|OUT|INOUT)_.*?CAP\s*\(.*?\)\s*//g; # don't want this metadata as part of the documentation. | ||
747 | $decl =~ s/\)(\s*SDL_[a-zA-Z_]+(\(.*?\)|))*;/);/; # don't want this metadata as part of the documentation. | ||
748 | return $decl; | ||
749 | } | ||
750 | |||
751 | sub sanitize_c_typename { | ||
752 | my $str = shift; | ||
753 | $str =~ s/\A\s+//; | ||
754 | $str =~ s/\s+\Z//; | ||
755 | $str =~ s/const\s*(\*+)/const $1/g; # one space between `const` and pointer stars: `char const* const *` becomes `char const * const *`. | ||
756 | $str =~ s/\*\s+\*/**/g; # drop spaces between pointers: `void * *` becomes `void **`. | ||
757 | $str =~ s/\s*(\*+)\Z/ $1/; # one space between pointer stars and what it points to: `void**` becomes `void **`. | ||
758 | return $str; | ||
759 | } | ||
760 | |||
761 | my %big_ascii = ( | ||
762 | 'A' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
763 | 'B' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
764 | 'C' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
765 | 'D' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
766 | 'E' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{255D}\x{20}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
767 | 'F' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{255D}\x{20}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}\x{20}\x{20}" ], | ||
768 | 'G' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
769 | 'H' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
770 | 'I' => [ "\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}" ], | ||
771 | 'J' => [ "\x{20}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
772 | 'K' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
773 | 'L' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
774 | 'M' => [ "\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{255A}\x{2588}\x{2588}\x{2554}\x{255D}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{255A}\x{2550}\x{255D}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
775 | 'N' => [ "\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2557}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{255A}\x{2588}\x{2588}\x{2557}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
776 | 'O' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
777 | 'P' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}\x{20}\x{20}" ], | ||
778 | 'Q' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{2584}\x{2584}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2580}\x{2580}\x{2550}\x{255D}\x{20}" ], | ||
779 | 'R' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
780 | 'S' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
781 | 'T' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{255D}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}" ], | ||
782 | 'U' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
783 | 'V' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2557}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}\x{20}" ], | ||
784 | 'W' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{20}\x{2588}\x{2557}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}\x{2588}\x{2588}\x{2588}\x{2557}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{255D}\x{255A}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
785 | 'X' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2557}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{255D}\x{20}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
786 | 'Y' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2557}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{20}\x{255A}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}" ], | ||
787 | 'Z' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{20}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
788 | ' ' => [ "\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}" ], | ||
789 | '.' => [ "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{255D}" ], | ||
790 | ',' => [ "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}", "\x{2584}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{255D}" ], | ||
791 | '/' => [ "\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}\x{20}", "\x{2588}\x{2588}\x{2554}\x{255D}\x{20}\x{20}\x{20}", "\x{255A}\x{2550}\x{255D}\x{20}\x{20}\x{20}\x{20}" ], | ||
792 | '!' => [ "\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{255D}" ], | ||
793 | '_' => [ "\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
794 | '0' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{2588}\x{2588}\x{2554}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
795 | '1' => [ "\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2588}\x{2588}\x{2551}", "\x{20}\x{2588}\x{2588}\x{2551}", "\x{20}\x{2588}\x{2588}\x{2551}", "\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
796 | '2' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
797 | '3' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
798 | '4' => [ "\x{2588}\x{2588}\x{2557}\x{20}\x{20}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2551}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}", "\x{20}\x{20}\x{20}\x{20}\x{20}\x{255A}\x{2550}\x{255D}" ], | ||
799 | '5' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}" ], | ||
800 | '6' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}", "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
801 | '7' => [ "\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{20}\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2554}\x{255D}\x{20}", "\x{20}\x{20}\x{20}\x{2588}\x{2588}\x{2551}\x{20}\x{20}", "\x{20}\x{20}\x{20}\x{255A}\x{2550}\x{255D}\x{20}\x{20}" ], | ||
802 | '8' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
803 | '9' => [ "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2557}\x{20}", "\x{2588}\x{2588}\x{2554}\x{2550}\x{2550}\x{2588}\x{2588}\x{2557}", "\x{255A}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2551}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2588}\x{2588}\x{2551}", "\x{20}\x{2588}\x{2588}\x{2588}\x{2588}\x{2588}\x{2554}\x{255D}", "\x{20}\x{255A}\x{2550}\x{2550}\x{2550}\x{2550}\x{255D}\x{20}" ], | ||
804 | ); | ||
805 | |||
806 | sub print_big_ascii_string { | ||
807 | my $fh = shift; | ||
808 | my $str = shift; | ||
809 | my $comment = shift; | ||
810 | my $lowascii = shift; | ||
811 | $comment = '' if not defined $comment; | ||
812 | $lowascii = 0 if not defined $lowascii; | ||
813 | |||
814 | my @chars = split //, $str; | ||
815 | my $charcount = scalar(@chars); | ||
816 | |||
817 | binmode($fh, ":utf8"); | ||
818 | |||
819 | my $maxrows = $lowascii ? 5 : 6; | ||
820 | |||
821 | for(my $rownum = 0; $rownum < $maxrows; $rownum++){ | ||
822 | print $fh $comment; | ||
823 | my $charidx = 0; | ||
824 | foreach my $ch (@chars) { | ||
825 | my $rowsref = $big_ascii{uc($ch)}; | ||
826 | die("Don't have a big ascii entry for '$ch'!\n") if not defined $rowsref; | ||
827 | my $row = @$rowsref[$rownum]; | ||
828 | |||
829 | if ($lowascii) { | ||
830 | my @x = split //, $row; | ||
831 | foreach (@x) { | ||
832 | my $v = ($_ eq "\x{2588}") ? 'X' : ' '; | ||
833 | print $fh $v; | ||
834 | } | ||
835 | } else { | ||
836 | print $fh $row; | ||
837 | } | ||
838 | |||
839 | $charidx++; | ||
840 | |||
841 | if ($charidx < $charcount) { | ||
842 | print $fh " "; | ||
843 | } | ||
844 | } | ||
845 | print $fh "\n"; | ||
846 | } | ||
847 | } | ||
848 | |||
849 | sub generate_quickref { | ||
850 | my $briefsref = shift; | ||
851 | my $path = shift; | ||
852 | my $lowascii = shift; | ||
853 | |||
854 | # !!! FIXME: this gitrev and majorver/etc stuff is copy/pasted a few times now. | ||
855 | if (!$gitrev) { | ||
856 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
857 | chomp($gitrev); | ||
858 | } | ||
859 | |||
860 | # !!! FIXME | ||
861 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
862 | my $majorver = 0; | ||
863 | my $minorver = 0; | ||
864 | my $microver = 0; | ||
865 | while (<FH>) { | ||
866 | chomp; | ||
867 | if (/$versionmajorregex/) { | ||
868 | $majorver = int($1); | ||
869 | } elsif (/$versionminorregex/) { | ||
870 | $minorver = int($1); | ||
871 | } elsif (/$versionmicroregex/) { | ||
872 | $microver = int($1); | ||
873 | } | ||
874 | } | ||
875 | close(FH); | ||
876 | my $fullversion = "$majorver.$minorver.$microver"; | ||
877 | |||
878 | my $tmppath = "$path.tmp"; | ||
879 | open(my $fh, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
880 | |||
881 | if (not @quickrefcategoryorder) { | ||
882 | @quickrefcategoryorder = sort keys %headercategorydocs; | ||
883 | } | ||
884 | |||
885 | #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); | ||
886 | #my $datestr = sprintf("%04d-%02d-%02d %02d:%02d:%02d GMT", $year+1900, $mon+1, $mday, $hour, $min, $sec); | ||
887 | |||
888 | print $fh "<!-- DO NOT EDIT THIS PAGE ON THE WIKI. IT WILL BE OVERWRITTEN BY WIKIHEADERS AND CHANGES WILL BE LOST! -->\n\n"; | ||
889 | |||
890 | # Just something to test big_ascii output. | ||
891 | #print_big_ascii_string($fh, "ABCDEFGHIJ", '', $lowascii); | ||
892 | #print_big_ascii_string($fh, "KLMNOPQRST", '', $lowascii); | ||
893 | #print_big_ascii_string($fh, "UVWXYZ0123", '', $lowascii); | ||
894 | #print_big_ascii_string($fh, "456789JT3A", '', $lowascii); | ||
895 | #print_big_ascii_string($fh, "hello, _a.b/c_!!", '', $lowascii); | ||
896 | |||
897 | # Dan Bechard's work was on an SDL2 cheatsheet: | ||
898 | # https://blog.theprogrammingjunkie.com/post/sdl2-cheatsheet/ | ||
899 | |||
900 | if ($lowascii) { | ||
901 | print $fh "# QuickReferenceNoUnicode\n\n"; | ||
902 | print $fh "If you want to paste this into a text editor that can handle\n"; | ||
903 | print $fh "fancy Unicode section headers, try using\n"; | ||
904 | print $fh "[QuickReference](QuickReference) instead.\n\n"; | ||
905 | } else { | ||
906 | print $fh "# QuickReference\n\n"; | ||
907 | print $fh "If you want to paste this into a text editor that can't handle\n"; | ||
908 | print $fh "the fancy Unicode section headers, try using\n"; | ||
909 | print $fh "[QuickReferenceNoUnicode](QuickReferenceNoUnicode) instead.\n\n"; | ||
910 | } | ||
911 | |||
912 | print $fh "```c\n"; | ||
913 | print $fh "// $quickreftitle\n" if defined $quickreftitle; | ||
914 | print $fh "//\n"; | ||
915 | print $fh "// $quickrefurl\n//\n" if defined $quickrefurl; | ||
916 | print $fh "// $quickrefdesc\n" if defined $quickrefdesc; | ||
917 | #print $fh "// When this document was written: $datestr\n"; | ||
918 | print $fh "// Based on $projectshortname version $fullversion\n"; | ||
919 | #print $fh "// git revision $gitrev\n"; | ||
920 | print $fh "//\n"; | ||
921 | print $fh "// This can be useful in an IDE with search and syntax highlighting.\n"; | ||
922 | print $fh "//\n"; | ||
923 | print $fh "// Original idea for this document came from Dan Bechard (thanks!)\n"; | ||
924 | print $fh "// ASCII art generated by: https://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow (with modified 'S' for readability)\n\n"; | ||
925 | |||
926 | foreach (@quickrefcategoryorder) { | ||
927 | my $cat = $_; | ||
928 | my $maxlen = 0; | ||
929 | my @csigs = (); | ||
930 | my $funcorderref = $quickreffuncorder{$cat}; | ||
931 | next if not defined $funcorderref; | ||
932 | |||
933 | foreach (@$funcorderref) { | ||
934 | my $sym = $_; | ||
935 | my $csig = ''; | ||
936 | |||
937 | if ($headersymstype{$sym} == 1) { # function | ||
938 | $csig = "${headersymsrettype{$sym}} $sym"; | ||
939 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
940 | if (not defined($fnsigparams)) { | ||
941 | $csig .= '(void);'; | ||
942 | } else { | ||
943 | my $sep = '('; | ||
944 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
945 | my $paramname = @$fnsigparams[$i]; | ||
946 | my $paramtype = @$fnsigparams[$i+1]; | ||
947 | my $spc = ($paramtype =~ /\*\Z/) ? '' : ' '; | ||
948 | $csig .= "$sep$paramtype$spc$paramname"; | ||
949 | $sep = ', '; | ||
950 | } | ||
951 | $csig .= ");"; | ||
952 | } | ||
953 | } elsif ($headersymstype{$sym} == 2) { # macro | ||
954 | next if defined $quickrefmacroregex && not $sym =~ /$quickrefmacroregex/; | ||
955 | |||
956 | $csig = (split /\n/, $headerdecls{$sym})[0]; # get the first line from a multiline string. | ||
957 | if (not $csig =~ s/\A(\#define [a-zA-Z0-9_]*\(.*?\))(\s+.*)?\Z/$1/) { | ||
958 | $csig =~ s/\A(\#define [a-zA-Z0-9_]*)(\s+.*)?\Z/$1/; | ||
959 | } | ||
960 | chomp($csig); | ||
961 | } | ||
962 | |||
963 | my $len = length($csig); | ||
964 | $maxlen = $len if $len > $maxlen; | ||
965 | |||
966 | push @csigs, $sym; | ||
967 | push @csigs, $csig; | ||
968 | } | ||
969 | |||
970 | $maxlen += 2; | ||
971 | |||
972 | next if (not @csigs); | ||
973 | |||
974 | print $fh "\n"; | ||
975 | print_big_ascii_string($fh, $cat, '// ', $lowascii); | ||
976 | print $fh "\n"; | ||
977 | |||
978 | while (@csigs) { | ||
979 | my $sym = shift @csigs; | ||
980 | my $csig = shift @csigs; | ||
981 | my $brief = $$briefsref{$sym}; | ||
982 | if (defined $brief) { | ||
983 | $brief = "$brief"; | ||
984 | chomp($brief); | ||
985 | my $thiswikitype = defined $wikitypes{$sym} ? $wikitypes{$sym} : 'md'; # default to MarkDown for new stuff. | ||
986 | $brief = dewikify($thiswikitype, $brief); | ||
987 | my $spaces = ' ' x ($maxlen - length($csig)); | ||
988 | $brief = "$spaces// $brief"; | ||
989 | } else { | ||
990 | $brief = ''; | ||
991 | } | ||
992 | print $fh "$csig$brief\n"; | ||
993 | } | ||
994 | } | ||
995 | |||
996 | print $fh "```\n\n"; | ||
997 | |||
998 | close($fh); | ||
999 | |||
1000 | # # Don't overwrite the file if nothing has changed besides the timestamp | ||
1001 | # # and git revision. | ||
1002 | # my $matches = 1; | ||
1003 | # if ( not -f $path ) { | ||
1004 | # $matches = 0; # always write if the file hasn't been created yet. | ||
1005 | # } else { | ||
1006 | # open(my $fh_a, '<', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
1007 | # open(my $fh_b, '<', $path) or die("Can't open '$path': $!\n"); | ||
1008 | # while (1) { | ||
1009 | # my $a = <$fh_a>; | ||
1010 | # my $b = <$fh_b>; | ||
1011 | # $matches = 0, last if ((not defined $a) != (not defined $b)); | ||
1012 | # last if ((not defined $a) || (not defined $b)); | ||
1013 | # if ($a ne $b) { | ||
1014 | # next if ($a =~ /\A\/\/ When this document was written:/); | ||
1015 | # next if ($a =~ /\A\/\/ git revision /); | ||
1016 | # $matches = 0; | ||
1017 | # last; | ||
1018 | # } | ||
1019 | # } | ||
1020 | # | ||
1021 | # close($fh_a); | ||
1022 | # close($fh_b); | ||
1023 | # } | ||
1024 | # | ||
1025 | # if ($matches) { | ||
1026 | # unlink($tmppath); # it's the same file except maybe the date/gitrev. Don't overwrite it. | ||
1027 | # } else { | ||
1028 | # rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
1029 | # } | ||
1030 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
1031 | } | ||
1032 | |||
1033 | |||
1034 | my $incpath = "$srcpath"; | ||
1035 | $incpath .= "/$incsubdir" if $incsubdir ne ''; | ||
1036 | |||
1037 | my $wikireadmepath = "$wikipath/$wikireadmesubdir"; | ||
1038 | my $readmepath = undef; | ||
1039 | if (defined $readmesubdir) { | ||
1040 | $readmepath = "$srcpath/$readmesubdir"; | ||
1041 | } | ||
1042 | |||
1043 | opendir(DH, $incpath) or die("Can't opendir '$incpath': $!\n"); | ||
1044 | while (my $d = readdir(DH)) { | ||
1045 | my $dent = $d; | ||
1046 | next if not $dent =~ /$selectheaderregex/; # just selected headers. | ||
1047 | open(FH, '<', "$incpath/$dent") or die("Can't open '$incpath/$dent': $!\n"); | ||
1048 | |||
1049 | # You can optionally set a wiki category with Perl code in .wikiheaders-options that gets eval()'d per-header, | ||
1050 | # and also if you put `/* WIKI CATEGORY: blah */` on a line by itself, it'll change the category for any symbols | ||
1051 | # below it in the same file. If no category is set, one won't be added for the symbol (beyond the standard CategoryFunction, etc) | ||
1052 | my $current_wiki_category = undef; | ||
1053 | if (defined $headercategoryeval) { | ||
1054 | $_ = $dent; | ||
1055 | $current_wiki_category = eval($headercategoryeval); | ||
1056 | if (($current_wiki_category eq '') || ($current_wiki_category eq '-')) { | ||
1057 | $current_wiki_category = undef; | ||
1058 | } | ||
1059 | #print("CATEGORY FOR '$dent' IS " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); | ||
1060 | } | ||
1061 | |||
1062 | my @contents = (); | ||
1063 | my @function_order = (); | ||
1064 | my $ignoring_lines = 0; | ||
1065 | my $header_comment = -1; | ||
1066 | my $saw_category_doxygen = -1; | ||
1067 | my $lineno = 0; | ||
1068 | |||
1069 | while (<FH>) { | ||
1070 | chomp; | ||
1071 | $lineno++; | ||
1072 | my $symtype = 0; # nothing, yet. | ||
1073 | my $decl; | ||
1074 | my @templines; | ||
1075 | my $str; | ||
1076 | my $has_doxygen = 1; | ||
1077 | |||
1078 | # Since a lot of macros are just preprocessor logic spam and not all macros are worth documenting anyhow, we only pay attention to them when they have a Doxygen comment attached. | ||
1079 | # Functions and other things are a different story, though! | ||
1080 | |||
1081 | if ($header_comment == -1) { | ||
1082 | $header_comment = /\A\/\*\s*\Z/ ? 1 : 0; | ||
1083 | } elsif (($header_comment == 1) && (/\A\*\/\s*\Z/)) { | ||
1084 | $header_comment = 0; | ||
1085 | } | ||
1086 | |||
1087 | if ($ignoring_lines && /\A\s*\#\s*endif\s*\Z/) { | ||
1088 | $ignoring_lines = 0; | ||
1089 | push @contents, $_; | ||
1090 | next; | ||
1091 | } elsif ($ignoring_lines) { | ||
1092 | push @contents, $_; | ||
1093 | next; | ||
1094 | } elsif (/\A\s*\#\s*ifndef\s+SDL_WIKI_DOCUMENTATION_SECTION\s*\Z/) { | ||
1095 | $ignoring_lines = 1; | ||
1096 | push @contents, $_; | ||
1097 | next; | ||
1098 | } elsif (/\A\s*\/\*\s*WIKI CATEGORY:\s*(.*?)\s*\*\/\s*\Z/) { | ||
1099 | $current_wiki_category = (($1 eq '') || ($1 eq '-')) ? undef : $1; | ||
1100 | #print("CATEGORY FOR '$dent' CHANGED TO " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); | ||
1101 | push @contents, $_; | ||
1102 | next; | ||
1103 | } elsif (/\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { # a function declaration without a doxygen comment? | ||
1104 | $symtype = 1; # function declaration | ||
1105 | @templines = (); | ||
1106 | $decl = $_; | ||
1107 | $str = ''; | ||
1108 | $has_doxygen = 0; | ||
1109 | } elsif (/\A\s*SDL_FORCE_INLINE/) { # a (forced-inline) function declaration without a doxygen comment? | ||
1110 | $symtype = 1; # function declaration | ||
1111 | @templines = (); | ||
1112 | $decl = $_; | ||
1113 | $str = ''; | ||
1114 | $has_doxygen = 0; | ||
1115 | } elsif (not /\A\/\*\*\s*\Z/) { # not doxygen comment start? | ||
1116 | push @contents, $_; | ||
1117 | add_coverage_gap($_, $dent, $lineno) if ($header_comment == 0); | ||
1118 | next; | ||
1119 | } else { # Start of a doxygen comment, parse it out. | ||
1120 | my $is_category_doxygen = 0; | ||
1121 | |||
1122 | @templines = ( $_ ); | ||
1123 | while (<FH>) { | ||
1124 | chomp; | ||
1125 | $lineno++; | ||
1126 | push @templines, $_; | ||
1127 | last if /\A\s*\*\/\Z/; | ||
1128 | if (s/\A\s*\*\s*\`\`\`/```/) { # this is a hack, but a lot of other code relies on the whitespace being trimmed, but we can't trim it in code blocks... | ||
1129 | $str .= "$_\n"; | ||
1130 | while (<FH>) { | ||
1131 | chomp; | ||
1132 | $lineno++; | ||
1133 | push @templines, $_; | ||
1134 | s/\A\s*\*\s?//; | ||
1135 | if (s/\A\s*\`\`\`/```/) { | ||
1136 | $str .= "$_\n"; | ||
1137 | last; | ||
1138 | } else { | ||
1139 | $str .= "$_\n"; | ||
1140 | } | ||
1141 | } | ||
1142 | } else { | ||
1143 | s/\A\s*\*\s*//; # Strip off the " * " at the start of the comment line. | ||
1144 | |||
1145 | # To add documentation to Category Pages, the rule is it has to | ||
1146 | # be the first Doxygen comment in the header, and it must start with `# CategoryX` | ||
1147 | # (otherwise we'll treat it as documentation for whatever's below it). `X` is | ||
1148 | # the category name, which doesn't _necessarily_ have to match | ||
1149 | # $current_wiki_category, but it probably should. | ||
1150 | # | ||
1151 | # For compatibility with Doxygen, if there's a `\file` here instead of | ||
1152 | # `# CategoryName`, we'll accept it and use the $current_wiki_category if set. | ||
1153 | if ($saw_category_doxygen == -1) { | ||
1154 | $saw_category_doxygen = defined($current_wiki_category) && /\A\\file\s+/; | ||
1155 | if ($saw_category_doxygen) { | ||
1156 | $_ = "# Category$current_wiki_category"; | ||
1157 | } else { | ||
1158 | $saw_category_doxygen = /\A\# Category/; | ||
1159 | } | ||
1160 | $is_category_doxygen = $saw_category_doxygen; | ||
1161 | } | ||
1162 | |||
1163 | $str .= "$_\n"; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | if ($is_category_doxygen) { | ||
1168 | $str =~ s/\s*\Z//; | ||
1169 | $decl = ''; | ||
1170 | $symtype = -1; # not a symbol at all. | ||
1171 | } else { | ||
1172 | $decl = <FH>; | ||
1173 | $lineno++ if defined $decl; | ||
1174 | $decl = '' if not defined $decl; | ||
1175 | chomp($decl); | ||
1176 | if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { | ||
1177 | $symtype = 1; # function declaration | ||
1178 | } elsif ($decl =~ /\A\s*SDL_FORCE_INLINE/) { | ||
1179 | $symtype = 1; # (forced-inline) function declaration | ||
1180 | } elsif ($decl =~ /\A\s*\#\s*define\s+/) { | ||
1181 | $symtype = 2; # macro | ||
1182 | } elsif ($decl =~ /\A\s*(typedef\s+|)(struct|union)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { | ||
1183 | $symtype = 3; # struct or union | ||
1184 | } elsif ($decl =~ /\A\s*(typedef\s+|)enum\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { | ||
1185 | $symtype = 4; # enum | ||
1186 | } elsif ($decl =~ /\A\s*typedef\s+.*\Z/) { | ||
1187 | $symtype = 5; # other typedef | ||
1188 | } else { | ||
1189 | #print "Found doxygen but no function sig:\n$str\n\n"; | ||
1190 | foreach (@templines) { | ||
1191 | push @contents, $_; | ||
1192 | add_coverage_gap($_, $dent, $lineno); | ||
1193 | } | ||
1194 | push @contents, $decl; | ||
1195 | add_coverage_gap($decl, $dent, $lineno); | ||
1196 | next; | ||
1197 | } | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | my @paraminfo = (); | ||
1202 | my $rettype = undef; | ||
1203 | my @decllines = ( $decl ); | ||
1204 | my $sym = ''; | ||
1205 | |||
1206 | if ($symtype == -1) { # category documentation with no symbol attached. | ||
1207 | @decllines = (); | ||
1208 | if ($str =~ /^#\s*Category(.*?)\s*$/m) { | ||
1209 | $sym = "[category documentation] $1"; # make a fake, unique symbol that's not valid C. | ||
1210 | } else { | ||
1211 | die("Unexpected category documentation line '$str' in '$incpath/$dent' ...?"); | ||
1212 | } | ||
1213 | $headercategorydocs{$current_wiki_category} = $sym; | ||
1214 | } elsif ($symtype == 1) { # a function | ||
1215 | my $is_forced_inline = ($decl =~ /\A\s*SDL_FORCE_INLINE/); | ||
1216 | |||
1217 | if ($is_forced_inline) { | ||
1218 | if (not $decl =~ /\)\s*(\{.*|)\s*\Z/) { | ||
1219 | while (<FH>) { | ||
1220 | chomp; | ||
1221 | $lineno++; | ||
1222 | push @decllines, $_; | ||
1223 | s/\A\s+//; | ||
1224 | s/\s+\Z//; | ||
1225 | $decl .= " $_"; | ||
1226 | last if /\)\s*(\{.*|)\s*\Z/; | ||
1227 | } | ||
1228 | } | ||
1229 | $decl =~ s/\s*\)\s*(\{.*|)\s*\Z/);/; | ||
1230 | } else { | ||
1231 | if (not $decl =~ /;/) { | ||
1232 | while (<FH>) { | ||
1233 | chomp; | ||
1234 | $lineno++; | ||
1235 | push @decllines, $_; | ||
1236 | s/\A\s+//; | ||
1237 | s/\s+\Z//; | ||
1238 | $decl .= " $_"; | ||
1239 | last if /;/; | ||
1240 | } | ||
1241 | } | ||
1242 | $decl =~ s/\s+\);\Z/);/; | ||
1243 | $decl =~ s/\s+;\Z/;/; | ||
1244 | } | ||
1245 | |||
1246 | $decl =~ s/\s+\Z//; | ||
1247 | |||
1248 | $decl = strip_fn_declaration_metadata($decl); | ||
1249 | |||
1250 | my $paramsstr = undef; | ||
1251 | |||
1252 | if (!$is_forced_inline && $decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(\*?)\s*SDLCALL\s+(.*?)\s*\((.*?)\);/) { | ||
1253 | $sym = $8; | ||
1254 | $rettype = "$3$4$5$6"; | ||
1255 | $paramsstr = $9; | ||
1256 | } elsif ($is_forced_inline && $decl =~ /\A\s*SDL_FORCE_INLINE\s+(SDL_DEPRECATED\s+|)(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(.*?)\s*\((.*?)\);/) { | ||
1257 | $sym = $6; | ||
1258 | $rettype = "$2$3$4$5"; | ||
1259 | $paramsstr = $7; | ||
1260 | } else { | ||
1261 | #print "Found doxygen but no function sig:\n$str\n\n"; | ||
1262 | foreach (@templines) { | ||
1263 | push @contents, $_; | ||
1264 | } | ||
1265 | foreach (@decllines) { | ||
1266 | push @contents, $_; | ||
1267 | } | ||
1268 | next; | ||
1269 | } | ||
1270 | |||
1271 | $rettype = sanitize_c_typename($rettype); | ||
1272 | |||
1273 | if ($paramsstr =~ /\(/) { | ||
1274 | die("\n\n$0 FAILURE!\n" . | ||
1275 | "There's a '(' in the parameters for function '$sym' '$incpath/$dent'.\n" . | ||
1276 | "This usually means there's a parameter that's a function pointer type.\n" . | ||
1277 | "This causes problems for wikiheaders.pl and is less readable, too.\n" . | ||
1278 | "Please put that function pointer into a typedef,\n" . | ||
1279 | "and use the new type in this function's signature instead!\n\n"); | ||
1280 | } | ||
1281 | |||
1282 | my @params = split(/,/, $paramsstr); | ||
1283 | my $dotdotdot = 0; | ||
1284 | foreach (@params) { | ||
1285 | my $p = $_; | ||
1286 | $p =~ s/\A\s+//; | ||
1287 | $p =~ s/\s+\Z//; | ||
1288 | if (($p eq 'void') || ($p eq '')) { | ||
1289 | die("Void parameter in a function with multiple params?! ('$sym' in '$incpath/$dent')") if (scalar(@params) != 1); | ||
1290 | } elsif ($p eq '...') { | ||
1291 | die("Mutiple '...' params?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); | ||
1292 | $dotdotdot = 1; | ||
1293 | push @paraminfo, '...'; | ||
1294 | push @paraminfo, '...'; | ||
1295 | } elsif ($p =~ /\A(.*)\s+([a-zA-Z0-9_\*\[\]]+)\Z/) { | ||
1296 | die("Parameter after '...' param?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); | ||
1297 | my $t = $1; | ||
1298 | my $n = $2; | ||
1299 | if ($n =~ s/\A(\*+)//) { | ||
1300 | $t .= $1; # move any `*` that stuck to the name over. | ||
1301 | } | ||
1302 | if ($n =~ s/\[\]\Z//) { | ||
1303 | $t = "$t*"; # move any `[]` that stuck to the name over, as a pointer. | ||
1304 | } | ||
1305 | $t = sanitize_c_typename($t); | ||
1306 | #print("$t\n"); | ||
1307 | #print("$n\n"); | ||
1308 | push @paraminfo, $n; | ||
1309 | push @paraminfo, $t; | ||
1310 | } else { | ||
1311 | die("Unexpected parameter '$p' in function '$sym' in '$incpath/$dent'!"); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | if (!$is_forced_inline) { # don't do with forced-inline because we don't want the implementation inserted in the wiki. | ||
1316 | my $shrink_length = 0; | ||
1317 | |||
1318 | $decl = ''; # rebuild this with the line breaks, since it looks better for syntax highlighting. | ||
1319 | foreach (@decllines) { | ||
1320 | if ($decl eq '') { | ||
1321 | my $temp; | ||
1322 | |||
1323 | $decl = $_; | ||
1324 | $temp = $decl; | ||
1325 | $temp =~ s/\Aextern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(.*?)\s+(\*?)SDLCALL\s+/$3$4 /; | ||
1326 | $shrink_length = length($decl) - length($temp); | ||
1327 | $decl = $temp; | ||
1328 | } else { | ||
1329 | my $trimmed = $_; | ||
1330 | $trimmed =~ s/\A\s{$shrink_length}//; # shrink to match the removed "extern SDL_DECLSPEC SDLCALL " | ||
1331 | $decl .= $trimmed; | ||
1332 | } | ||
1333 | $decl .= "\n"; | ||
1334 | } | ||
1335 | } | ||
1336 | |||
1337 | $decl = strip_fn_declaration_metadata($decl); | ||
1338 | |||
1339 | # !!! FIXME: code duplication with typedef processing, below. | ||
1340 | # We assume any `#define`s directly after the function are related to it: probably bitflags for an integer typedef. | ||
1341 | # We'll also allow some other basic preprocessor lines. | ||
1342 | # Blank lines are allowed, anything else, even comments, are not. | ||
1343 | my $blank_lines = 0; | ||
1344 | my $lastpos = tell(FH); | ||
1345 | my $lastlineno = $lineno; | ||
1346 | my $additional_decl = ''; | ||
1347 | my $saw_define = 0; | ||
1348 | while (<FH>) { | ||
1349 | chomp; | ||
1350 | |||
1351 | $lineno++; | ||
1352 | |||
1353 | if (/\A\s*\Z/) { | ||
1354 | $blank_lines++; | ||
1355 | } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { | ||
1356 | if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { | ||
1357 | $referenceonly{$1} = $sym; | ||
1358 | $saw_define = 1; | ||
1359 | } elsif (!$saw_define) { | ||
1360 | # if the first non-blank thing isn't a #define, assume we're done. | ||
1361 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
1362 | $lineno = $lastlineno; | ||
1363 | last; | ||
1364 | } | ||
1365 | |||
1366 | # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. | ||
1367 | |||
1368 | # At Sam's request, don't list property defines with functions. (See #9440) | ||
1369 | my $is_property = /\A\s*\#\s*define\s+SDL_PROP_/; | ||
1370 | if (!$is_property) { | ||
1371 | if ($blank_lines > 0) { | ||
1372 | while ($blank_lines > 0) { | ||
1373 | $additional_decl .= "\n"; | ||
1374 | push @decllines, ''; | ||
1375 | $blank_lines--; | ||
1376 | } | ||
1377 | } | ||
1378 | $additional_decl .= "\n$_"; | ||
1379 | push @decllines, $_; | ||
1380 | $lastpos = tell(FH); | ||
1381 | } | ||
1382 | } else { | ||
1383 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
1384 | $lineno = $lastlineno; | ||
1385 | last; | ||
1386 | } | ||
1387 | } | ||
1388 | $decl .= $additional_decl; | ||
1389 | } elsif ($symtype == 2) { # a macro | ||
1390 | if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)\s+/) { | ||
1391 | $sym = $1; | ||
1392 | } else { | ||
1393 | #print "Found doxygen but no macro:\n$str\n\n"; | ||
1394 | foreach (@templines) { | ||
1395 | push @contents, $_; | ||
1396 | } | ||
1397 | foreach (@decllines) { | ||
1398 | push @contents, $_; | ||
1399 | } | ||
1400 | next; | ||
1401 | } | ||
1402 | |||
1403 | while ($decl =~ /\\\Z/) { | ||
1404 | my $l = <FH>; | ||
1405 | last if not $l; | ||
1406 | $lineno++; | ||
1407 | chomp($l); | ||
1408 | push @decllines, $l; | ||
1409 | #$l =~ s/\A\s+//; | ||
1410 | $l =~ s/\s+\Z//; | ||
1411 | $decl .= "\n$l"; | ||
1412 | } | ||
1413 | } elsif (($symtype == 3) || ($symtype == 4)) { # struct or union or enum | ||
1414 | my $has_definition = 0; | ||
1415 | if ($decl =~ /\A\s*(typedef\s+|)(struct|union|enum)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\;|\Z)/) { | ||
1416 | my $ctype = $2; | ||
1417 | my $origsym = $3; | ||
1418 | my $ending = $4; | ||
1419 | $sym = $origsym; | ||
1420 | if ($sym =~ s/\A(.*?)(\s+)(.*?)\Z/$1/) { | ||
1421 | die("Failed to parse '$origsym' correctly!") if ($sym ne $1); # Thought this was "typedef struct MySym MySym;" ... it was not. :( This is a hack! | ||
1422 | } | ||
1423 | if ($sym eq '') { | ||
1424 | die("\n\n$0 FAILURE!\n" . | ||
1425 | "There's a 'typedef $ctype' in $incpath/$dent without a name at the top.\n" . | ||
1426 | "Instead of `typedef $ctype {} x;`, this should be `typedef $ctype x {} x;`.\n" . | ||
1427 | "This causes problems for wikiheaders.pl and scripting language bindings.\n" . | ||
1428 | "Please fix it!\n\n"); | ||
1429 | } | ||
1430 | $has_definition = ($ending ne ';'); | ||
1431 | } else { | ||
1432 | #print "Found doxygen but no datatype:\n$str\n\n"; | ||
1433 | foreach (@templines) { | ||
1434 | push @contents, $_; | ||
1435 | } | ||
1436 | foreach (@decllines) { | ||
1437 | push @contents, $_; | ||
1438 | } | ||
1439 | next; | ||
1440 | } | ||
1441 | |||
1442 | # This block attempts to find the whole struct/union/enum definition by counting matching brackets. Kind of yucky. | ||
1443 | # It also "parses" enums enough to find out the elements of it. | ||
1444 | if ($has_definition) { | ||
1445 | my $started = 0; | ||
1446 | my $brackets = 0; | ||
1447 | my $pending = $decl; | ||
1448 | my $skipping_comment = 0; | ||
1449 | |||
1450 | $decl = ''; | ||
1451 | while (!$started || ($brackets != 0)) { | ||
1452 | foreach my $seg (split(/([{}])/, $pending)) { # (this will pick up brackets in comments! Be careful!) | ||
1453 | $decl .= $seg; | ||
1454 | if ($seg eq '{') { | ||
1455 | $started = 1; | ||
1456 | $brackets++; | ||
1457 | } elsif ($seg eq '}') { | ||
1458 | die("Something is wrong with header $incpath/$dent while parsing $sym; is a bracket missing?\n") if ($brackets <= 0); | ||
1459 | $brackets--; | ||
1460 | } | ||
1461 | } | ||
1462 | |||
1463 | if ($skipping_comment) { | ||
1464 | if ($pending =~ s/\A.*?\*\///) { | ||
1465 | $skipping_comment = 0; | ||
1466 | } | ||
1467 | } | ||
1468 | |||
1469 | if (!$skipping_comment && $started && ($symtype == 4)) { # Pick out elements of an enum. | ||
1470 | my $stripped = "$pending"; | ||
1471 | $stripped =~ s/\/\*.*?\*\///g; # dump /* comments */ that exist fully on one line. | ||
1472 | if ($stripped =~ /\/\*/) { # uhoh, a /* comment */ that crosses newlines. | ||
1473 | $skipping_comment = 1; | ||
1474 | } elsif ($stripped =~ /\A\s*([a-zA-Z0-9_]+)(.*)\Z/) { #\s*(\=\s*.*?|)\s*,?(.*?)\Z/) { | ||
1475 | if ($1 ne 'typedef') { # make sure we didn't just eat the first line by accident. :/ | ||
1476 | #print("ENUM [$1] $incpath/$dent:$lineno\n"); | ||
1477 | $referenceonly{$1} = $sym; | ||
1478 | } | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | if (!$started || ($brackets != 0)) { | ||
1483 | $pending = <FH>; | ||
1484 | die("EOF/error reading $incpath/$dent while parsing $sym\n") if not $pending; | ||
1485 | $lineno++; | ||
1486 | chomp($pending); | ||
1487 | push @decllines, $pending; | ||
1488 | $decl .= "\n"; | ||
1489 | } | ||
1490 | } | ||
1491 | # this currently assumes the struct/union/enum ends on the line with the final bracket. I'm not writing a C parser here, fix the header! | ||
1492 | } | ||
1493 | } elsif ($symtype == 5) { # other typedef | ||
1494 | if ($decl =~ /\A\s*typedef\s+(.*)\Z/) { | ||
1495 | my $tdstr = $1; | ||
1496 | |||
1497 | if (not $decl =~ /;/) { | ||
1498 | while (<FH>) { | ||
1499 | chomp; | ||
1500 | $lineno++; | ||
1501 | push @decllines, $_; | ||
1502 | s/\A\s+//; | ||
1503 | s/\s+\Z//; | ||
1504 | $decl .= " $_"; | ||
1505 | last if /;/; | ||
1506 | } | ||
1507 | } | ||
1508 | $decl =~ s/\s+(\))?;\Z/$1;/; | ||
1509 | |||
1510 | $tdstr =~ s/;\s*\Z//; | ||
1511 | |||
1512 | #my $datatype; | ||
1513 | if ($tdstr =~ /\A(.*?)\s*\((.*?)\s*\*\s*(.*?)\)\s*\((.*?)(\))?/) { # a function pointer type | ||
1514 | $sym = $3; | ||
1515 | #$datatype = "$1 ($2 *$sym)($4)"; | ||
1516 | } elsif ($tdstr =~ /\A(.*[\s\*]+)(.*?)\s*\Z/) { | ||
1517 | $sym = $2; | ||
1518 | #$datatype = $1; | ||
1519 | } else { | ||
1520 | die("Failed to parse typedef '$tdstr' in $incpath/$dent!\n"); # I'm hitting a C grammar nail with a regexp hammer here, y'all. | ||
1521 | } | ||
1522 | |||
1523 | $sym =~ s/\A\s+//; | ||
1524 | $sym =~ s/\s+\Z//; | ||
1525 | #$datatype =~ s/\A\s+//; | ||
1526 | #$datatype =~ s/\s+\Z//; | ||
1527 | } else { | ||
1528 | #print "Found doxygen but no datatype:\n$str\n\n"; | ||
1529 | foreach (@templines) { | ||
1530 | push @contents, $_; | ||
1531 | } | ||
1532 | foreach (@decllines) { | ||
1533 | push @contents, $_; | ||
1534 | } | ||
1535 | next; | ||
1536 | } | ||
1537 | |||
1538 | # We assume any `#define`s directly after the typedef are related to it: probably bitflags for an integer typedef. | ||
1539 | # We'll also allow some other basic preprocessor lines. | ||
1540 | # Blank lines are allowed, anything else, even comments, are not. | ||
1541 | my $blank_lines = 0; | ||
1542 | my $lastpos = tell(FH); | ||
1543 | my $lastlineno = $lineno; | ||
1544 | my $additional_decl = ''; | ||
1545 | my $saw_define = 0; | ||
1546 | while (<FH>) { | ||
1547 | chomp; | ||
1548 | |||
1549 | $lineno++; | ||
1550 | |||
1551 | if (/\A\s*\Z/) { | ||
1552 | $blank_lines++; | ||
1553 | } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { | ||
1554 | if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { | ||
1555 | $referenceonly{$1} = $sym; | ||
1556 | $saw_define = 1; | ||
1557 | } elsif (!$saw_define) { | ||
1558 | # if the first non-blank thing isn't a #define, assume we're done. | ||
1559 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
1560 | $lineno = $lastlineno; | ||
1561 | last; | ||
1562 | } | ||
1563 | # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. | ||
1564 | if ($blank_lines > 0) { | ||
1565 | while ($blank_lines > 0) { | ||
1566 | $additional_decl .= "\n"; | ||
1567 | push @decllines, ''; | ||
1568 | $blank_lines--; | ||
1569 | } | ||
1570 | } | ||
1571 | $additional_decl .= "\n$_"; | ||
1572 | push @decllines, $_; | ||
1573 | $lastpos = tell(FH); | ||
1574 | } else { | ||
1575 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
1576 | $lineno = $lastlineno; | ||
1577 | last; | ||
1578 | } | ||
1579 | } | ||
1580 | $decl .= $additional_decl; | ||
1581 | } else { | ||
1582 | die("Unexpected symtype $symtype"); | ||
1583 | } | ||
1584 | |||
1585 | #print("DECL: [$decl]\n"); | ||
1586 | |||
1587 | #print("$sym:\n$str\n\n"); | ||
1588 | |||
1589 | # There might be multiple declarations of a function due to #ifdefs, | ||
1590 | # and only one of them will have documentation. If we hit an | ||
1591 | # undocumented one before, delete the placeholder line we left for | ||
1592 | # it so it doesn't accumulate a new blank line on each run. | ||
1593 | my $skipsym = 0; | ||
1594 | if (defined $headersymshasdoxygen{$sym}) { | ||
1595 | if ($headersymshasdoxygen{$sym} == 0) { # An undocumented declaration already exists, nuke its placeholder line. | ||
1596 | delete $contents[$headersymschunk{$sym}]; # delete DOES NOT RENUMBER existing elements! | ||
1597 | } else { # documented function already existed? | ||
1598 | $skipsym = 1; # don't add this copy to the list of functions. | ||
1599 | if ($has_doxygen) { | ||
1600 | print STDERR "WARNING: Symbol '$sym' appears to be documented in multiple locations. Only keeping the first one we saw!\n"; | ||
1601 | } | ||
1602 | push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); # just put the existing declation in as-is. | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | if (!$skipsym) { | ||
1607 | $headersymscategory{$sym} = $current_wiki_category if defined $current_wiki_category; | ||
1608 | $headersyms{$sym} = $str; | ||
1609 | $headerdecls{$sym} = $decl; | ||
1610 | $headersymslocation{$sym} = $dent; | ||
1611 | $headersymschunk{$sym} = scalar(@contents); | ||
1612 | $headersymshasdoxygen{$sym} = $has_doxygen; | ||
1613 | $headersymstype{$sym} = $symtype; | ||
1614 | $headersymsparaminfo{$sym} = \@paraminfo if (scalar(@paraminfo) > 0); | ||
1615 | $headersymsrettype{$sym} = $rettype if (defined($rettype)); | ||
1616 | push @function_order, $sym if ($symtype == 1) || ($symtype == 2); | ||
1617 | push @contents, join("\n", @templines); | ||
1618 | push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); | ||
1619 | } | ||
1620 | |||
1621 | } | ||
1622 | close(FH); | ||
1623 | |||
1624 | $headers{$dent} = \@contents; | ||
1625 | $quickreffuncorder{$current_wiki_category} = \@function_order if defined $current_wiki_category; | ||
1626 | } | ||
1627 | closedir(DH); | ||
1628 | |||
1629 | |||
1630 | opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n"); | ||
1631 | while (my $d = readdir(DH)) { | ||
1632 | my $dent = $d; | ||
1633 | my $type = ''; | ||
1634 | if ($dent =~ /\.(md|mediawiki)\Z/) { | ||
1635 | $type = $1; | ||
1636 | } else { | ||
1637 | next; # only dealing with wiki pages. | ||
1638 | } | ||
1639 | |||
1640 | my $sym = $dent; | ||
1641 | $sym =~ s/\..*\Z//; | ||
1642 | |||
1643 | # (There are other pages to ignore, but these are known ones to not bother parsing.) | ||
1644 | # Ignore FrontPage. | ||
1645 | next if $sym eq 'FrontPage'; | ||
1646 | |||
1647 | open(FH, '<', "$wikipath/$dent") or die("Can't open '$wikipath/$dent': $!\n"); | ||
1648 | |||
1649 | if ($sym =~ /\ACategory(.*?)\Z/) { # Special case for Category pages. | ||
1650 | # Find the end of the category documentation in the existing file and append everything else to the new file. | ||
1651 | my $cat = $1; | ||
1652 | my $docstr = ''; | ||
1653 | my $notdocstr = ''; | ||
1654 | my $docs = 1; | ||
1655 | while (<FH>) { | ||
1656 | chomp; | ||
1657 | if ($docs) { | ||
1658 | $docs = 0 if /\A\-\-\-\-\Z/; # Hit a footer? We're done. | ||
1659 | $docs = 0 if /\A<!\-\-/; # Hit an HTML comment? We're done. | ||
1660 | } | ||
1661 | if ($docs) { | ||
1662 | $docstr .= "$_\n"; | ||
1663 | } else { | ||
1664 | $notdocstr .= "$_\n"; | ||
1665 | } | ||
1666 | } | ||
1667 | close(FH); | ||
1668 | |||
1669 | $docstr =~ s/\s*\Z//; | ||
1670 | |||
1671 | $sym = "[category documentation] $cat"; # make a fake, unique symbol that's not valid C. | ||
1672 | $wikitypes{$sym} = $type; | ||
1673 | my %sections = (); | ||
1674 | $sections{'Remarks'} = $docstr; | ||
1675 | $sections{'[footer]'} = $notdocstr; | ||
1676 | $wikisyms{$sym} = \%sections; | ||
1677 | my @section_order = ( 'Remarks', '[footer]' ); | ||
1678 | $wikisectionorder{$sym} = \@section_order; | ||
1679 | next; | ||
1680 | } | ||
1681 | |||
1682 | my $current_section = '[start]'; | ||
1683 | my @section_order = ( $current_section ); | ||
1684 | my %sections = (); | ||
1685 | $sections{$current_section} = ''; | ||
1686 | |||
1687 | my $firstline = 1; | ||
1688 | |||
1689 | while (<FH>) { | ||
1690 | chomp; | ||
1691 | my $orig = $_; | ||
1692 | s/\A\s*//; | ||
1693 | s/\s*\Z//; | ||
1694 | |||
1695 | if ($type eq 'mediawiki') { | ||
1696 | if (defined($wikipreamble) && $firstline && /\A\=\=\=\=\=\= (.*?) \=\=\=\=\=\=\Z/ && ($1 eq $wikipreamble)) { | ||
1697 | $firstline = 0; # skip this. | ||
1698 | next; | ||
1699 | } elsif (/\A\= (.*?) \=\Z/) { | ||
1700 | $firstline = 0; | ||
1701 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
1702 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
1703 | push @section_order, $current_section; | ||
1704 | $sections{$current_section} = ''; | ||
1705 | } elsif (/\A\=\= (.*?) \=\=\Z/) { | ||
1706 | $firstline = 0; | ||
1707 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
1708 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
1709 | push @section_order, $current_section; | ||
1710 | $sections{$current_section} = ''; | ||
1711 | next; | ||
1712 | } elsif (/\A\-\-\-\-\Z/) { | ||
1713 | $firstline = 0; | ||
1714 | $current_section = '[footer]'; | ||
1715 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
1716 | push @section_order, $current_section; | ||
1717 | $sections{$current_section} = ''; | ||
1718 | next; | ||
1719 | } | ||
1720 | } elsif ($type eq 'md') { | ||
1721 | if (defined($wikipreamble) && $firstline && /\A\#\#\#\#\#\# (.*?)\Z/ && ($1 eq $wikipreamble)) { | ||
1722 | $firstline = 0; # skip this. | ||
1723 | next; | ||
1724 | } elsif (/\A\#+ (.*?)\Z/) { | ||
1725 | $firstline = 0; | ||
1726 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
1727 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
1728 | push @section_order, $current_section; | ||
1729 | $sections{$current_section} = ''; | ||
1730 | next; | ||
1731 | } elsif (/\A\-\-\-\-\Z/) { | ||
1732 | $firstline = 0; | ||
1733 | $current_section = '[footer]'; | ||
1734 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
1735 | push @section_order, $current_section; | ||
1736 | $sections{$current_section} = ''; | ||
1737 | next; | ||
1738 | } | ||
1739 | } else { | ||
1740 | die("Unexpected wiki file type. Fixme!"); | ||
1741 | } | ||
1742 | |||
1743 | if ($firstline) { | ||
1744 | $firstline = ($_ ne ''); | ||
1745 | } | ||
1746 | if (!$firstline) { | ||
1747 | $sections{$current_section} .= "$orig\n"; | ||
1748 | } | ||
1749 | } | ||
1750 | close(FH); | ||
1751 | |||
1752 | foreach (keys %sections) { | ||
1753 | $sections{$_} =~ s/\A\n+//; | ||
1754 | $sections{$_} =~ s/\n+\Z//; | ||
1755 | $sections{$_} .= "\n"; | ||
1756 | } | ||
1757 | |||
1758 | # older section name we used, migrate over from it. | ||
1759 | if (defined $sections{'Related Functions'}) { | ||
1760 | if (not defined $sections{'See Also'}) { | ||
1761 | $sections{'See Also'} = $sections{'Related Functions'}; | ||
1762 | } | ||
1763 | delete $sections{'Related Functions'}; | ||
1764 | } | ||
1765 | |||
1766 | if (0) { | ||
1767 | foreach (@section_order) { | ||
1768 | print("$sym SECTION '$_':\n"); | ||
1769 | print($sections{$_}); | ||
1770 | print("\n\n"); | ||
1771 | } | ||
1772 | } | ||
1773 | |||
1774 | $wikitypes{$sym} = $type; | ||
1775 | $wikisyms{$sym} = \%sections; | ||
1776 | $wikisectionorder{$sym} = \@section_order; | ||
1777 | } | ||
1778 | closedir(DH); | ||
1779 | |||
1780 | delete $wikisyms{"Undocumented"}; | ||
1781 | |||
1782 | { | ||
1783 | my $path = "$wikipath/Undocumented.md"; | ||
1784 | open(my $fh, '>', $path) or die("Can't open '$path': $!\n"); | ||
1785 | |||
1786 | print $fh "# Undocumented\n\n"; | ||
1787 | print_undocumented_section($fh, 'Functions', 1); | ||
1788 | #print_undocumented_section($fh, 'Macros', 2); | ||
1789 | |||
1790 | close($fh); | ||
1791 | } | ||
1792 | |||
1793 | if ($warn_about_missing) { | ||
1794 | foreach (keys %wikisyms) { | ||
1795 | my $sym = $_; | ||
1796 | if (not defined $headersyms{$sym}) { | ||
1797 | print STDERR "WARNING: $sym defined in the wiki but not the headers!\n"; | ||
1798 | } | ||
1799 | } | ||
1800 | |||
1801 | foreach (keys %headersyms) { | ||
1802 | my $sym = $_; | ||
1803 | if (not defined $wikisyms{$sym}) { | ||
1804 | print STDERR "WARNING: $sym defined in the headers but not the wiki!\n"; | ||
1805 | } | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | if ($copy_direction == 1) { # --copy-to-headers | ||
1810 | my %changed_headers = (); | ||
1811 | |||
1812 | $dewikify_mode = 'md'; | ||
1813 | $wordwrap_mode = 'md'; # the headers use Markdown format. | ||
1814 | |||
1815 | foreach (keys %headersyms) { | ||
1816 | my $sym = $_; | ||
1817 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
1818 | my $symtype = $headersymstype{$sym}; | ||
1819 | my $wikitype = $wikitypes{$sym}; | ||
1820 | my $sectionsref = $wikisyms{$sym}; | ||
1821 | my $remarks = $sectionsref->{'Remarks'}; | ||
1822 | my $returns = $sectionsref->{'Return Value'}; | ||
1823 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
1824 | my $version = $sectionsref->{'Version'}; | ||
1825 | my $related = $sectionsref->{'See Also'}; | ||
1826 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
1827 | my $brief = $sectionsref->{'[Brief]'}; | ||
1828 | my $addblank = 0; | ||
1829 | my $str = ''; | ||
1830 | |||
1831 | my $params = undef; | ||
1832 | my $paramstr = undef; | ||
1833 | |||
1834 | if ($symtype == -1) { # category documentation block. | ||
1835 | # nothing to be done here. | ||
1836 | } elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef. | ||
1837 | $params = $sectionsref->{'Function Parameters'}; | ||
1838 | $paramstr = '\param'; | ||
1839 | } elsif ($symtype == 2) { | ||
1840 | $params = $sectionsref->{'Macro Parameters'}; | ||
1841 | $paramstr = '\param'; | ||
1842 | } elsif ($symtype == 3) { | ||
1843 | $params = $sectionsref->{'Fields'}; | ||
1844 | $paramstr = '\field'; | ||
1845 | } elsif ($symtype == 4) { | ||
1846 | $params = $sectionsref->{'Values'}; | ||
1847 | $paramstr = '\value'; | ||
1848 | } else { | ||
1849 | die("Unexpected symtype $symtype"); | ||
1850 | } | ||
1851 | |||
1852 | $headersymshasdoxygen{$sym} = 1; # Added/changed doxygen for this header. | ||
1853 | |||
1854 | $brief = dewikify($wikitype, $brief); | ||
1855 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
1856 | my @briefsplit = split /\n/, $brief; | ||
1857 | $brief = shift @briefsplit; | ||
1858 | |||
1859 | if (defined $remarks) { | ||
1860 | $remarks = join("\n", @briefsplit) . dewikify($wikitype, $remarks); | ||
1861 | } | ||
1862 | |||
1863 | if (defined $brief) { | ||
1864 | $str .= "\n" if $addblank; $addblank = 1; | ||
1865 | $str .= wordwrap($brief) . "\n"; | ||
1866 | } | ||
1867 | |||
1868 | if (defined $remarks) { | ||
1869 | $str .= "\n" if $addblank; $addblank = 1; | ||
1870 | $str .= wordwrap($remarks) . "\n"; | ||
1871 | } | ||
1872 | |||
1873 | if (defined $deprecated) { | ||
1874 | # !!! FIXME: lots of code duplication in all of these. | ||
1875 | $str .= "\n" if $addblank; $addblank = 1; | ||
1876 | my $v = dewikify($wikitype, $deprecated); | ||
1877 | my $whitespacelen = length("\\deprecated") + 1; | ||
1878 | my $whitespace = ' ' x $whitespacelen; | ||
1879 | $v = wordwrap($v, -$whitespacelen); | ||
1880 | my @desclines = split /\n/, $v; | ||
1881 | my $firstline = shift @desclines; | ||
1882 | $str .= "\\deprecated $firstline\n"; | ||
1883 | foreach (@desclines) { | ||
1884 | $str .= "${whitespace}$_\n"; | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | if (defined $params) { | ||
1889 | $str .= "\n" if $addblank; $addblank = (defined $returns) ? 0 : 1; | ||
1890 | my @lines = split /\n/, dewikify($wikitype, $params); | ||
1891 | if ($wikitype eq 'mediawiki') { | ||
1892 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
1893 | while (scalar(@lines) >= 3) { | ||
1894 | my $c_datatype = shift @lines; | ||
1895 | my $name = shift @lines; | ||
1896 | my $desc = shift @lines; | ||
1897 | my $terminator; # the '|-' or '|}' line. | ||
1898 | |||
1899 | if (($desc eq '|-') or ($desc eq '|}') or (not $desc =~ /\A\|/)) { # we seem to be out of cells, which means there was no datatype column on this one. | ||
1900 | $terminator = $desc; | ||
1901 | $desc = $name; | ||
1902 | $name = $c_datatype; | ||
1903 | $c_datatype = ''; | ||
1904 | } else { | ||
1905 | $terminator = shift @lines; | ||
1906 | } | ||
1907 | |||
1908 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
1909 | $name =~ s/\A\|\s*//; | ||
1910 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
1911 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
1912 | $desc =~ s/\A\|\s*//; | ||
1913 | #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; | ||
1914 | my $whitespacelen = length($name) + 8; | ||
1915 | my $whitespace = ' ' x $whitespacelen; | ||
1916 | $desc = wordwrap($desc, -$whitespacelen); | ||
1917 | my @desclines = split /\n/, $desc; | ||
1918 | my $firstline = shift @desclines; | ||
1919 | $str .= "$paramstr $name $firstline\n"; | ||
1920 | foreach (@desclines) { | ||
1921 | $str .= "${whitespace}$_\n"; | ||
1922 | } | ||
1923 | } | ||
1924 | } elsif ($wikitype eq 'md') { | ||
1925 | my $l; | ||
1926 | $l = shift @lines; | ||
1927 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
1928 | $l = shift @lines; | ||
1929 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
1930 | while (scalar(@lines) >= 1) { | ||
1931 | $l = shift @lines; | ||
1932 | my $name; | ||
1933 | my $desc; | ||
1934 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
1935 | # c datatype is $1, but we don't care about it here. | ||
1936 | $name = $2; | ||
1937 | $desc = $3; | ||
1938 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
1939 | $name = $1; | ||
1940 | $desc = $2; | ||
1941 | } else { | ||
1942 | last; # we seem to have run out of table. | ||
1943 | } | ||
1944 | |||
1945 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
1946 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
1947 | #print STDERR "SYM: $sym NAME: $name DESC: $desc\n"; | ||
1948 | my $whitespacelen = length($name) + 8; | ||
1949 | my $whitespace = ' ' x $whitespacelen; | ||
1950 | $desc = wordwrap($desc, -$whitespacelen); | ||
1951 | my @desclines = split /\n/, $desc; | ||
1952 | my $firstline = shift @desclines; | ||
1953 | $str .= "$paramstr $name $firstline\n"; | ||
1954 | foreach (@desclines) { | ||
1955 | $str .= "${whitespace}$_\n"; | ||
1956 | } | ||
1957 | } | ||
1958 | } else { | ||
1959 | die("write me"); | ||
1960 | } | ||
1961 | } | ||
1962 | |||
1963 | if (defined $returns) { | ||
1964 | $str .= "\n" if $addblank; $addblank = 1; | ||
1965 | my $r = dewikify($wikitype, $returns); | ||
1966 | $r =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. | ||
1967 | my $retstr = "\\returns"; | ||
1968 | if ($r =~ s/\AReturn(s?)\s+//) { | ||
1969 | $retstr = "\\return$1"; | ||
1970 | } | ||
1971 | |||
1972 | my $whitespacelen = length($retstr) + 1; | ||
1973 | my $whitespace = ' ' x $whitespacelen; | ||
1974 | $r = wordwrap($r, -$whitespacelen); | ||
1975 | my @desclines = split /\n/, $r; | ||
1976 | my $firstline = shift @desclines; | ||
1977 | $str .= "$retstr $firstline\n"; | ||
1978 | foreach (@desclines) { | ||
1979 | $str .= "${whitespace}$_\n"; | ||
1980 | } | ||
1981 | } | ||
1982 | |||
1983 | if (defined $threadsafety) { | ||
1984 | # !!! FIXME: lots of code duplication in all of these. | ||
1985 | $str .= "\n" if $addblank; $addblank = 1; | ||
1986 | my $v = dewikify($wikitype, $threadsafety); | ||
1987 | my $whitespacelen = length("\\threadsafety") + 1; | ||
1988 | my $whitespace = ' ' x $whitespacelen; | ||
1989 | $v = wordwrap($v, -$whitespacelen); | ||
1990 | my @desclines = split /\n/, $v; | ||
1991 | my $firstline = shift @desclines; | ||
1992 | $str .= "\\threadsafety $firstline\n"; | ||
1993 | foreach (@desclines) { | ||
1994 | $str .= "${whitespace}$_\n"; | ||
1995 | } | ||
1996 | } | ||
1997 | |||
1998 | if (defined $version) { | ||
1999 | # !!! FIXME: lots of code duplication in all of these. | ||
2000 | $str .= "\n" if $addblank; $addblank = 1; | ||
2001 | my $v = dewikify($wikitype, $version); | ||
2002 | my $whitespacelen = length("\\since") + 1; | ||
2003 | my $whitespace = ' ' x $whitespacelen; | ||
2004 | $v = wordwrap($v, -$whitespacelen); | ||
2005 | my @desclines = split /\n/, $v; | ||
2006 | my $firstline = shift @desclines; | ||
2007 | $str .= "\\since $firstline\n"; | ||
2008 | foreach (@desclines) { | ||
2009 | $str .= "${whitespace}$_\n"; | ||
2010 | } | ||
2011 | } | ||
2012 | |||
2013 | if (defined $related) { | ||
2014 | # !!! FIXME: lots of code duplication in all of these. | ||
2015 | $str .= "\n" if $addblank; $addblank = 1; | ||
2016 | my $v = dewikify($wikitype, $related); | ||
2017 | my @desclines = split /\n/, $v; | ||
2018 | foreach (@desclines) { | ||
2019 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
2020 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
2021 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
2022 | s/\A\/*//; | ||
2023 | s/\A\s*[\:\*\-]\s*//; | ||
2024 | s/\A\s+//; | ||
2025 | s/\s+\Z//; | ||
2026 | $str .= "\\sa $_\n"; | ||
2027 | } | ||
2028 | } | ||
2029 | |||
2030 | my $header = $headersymslocation{$sym}; | ||
2031 | my $contentsref = $headers{$header}; | ||
2032 | my $chunk = $headersymschunk{$sym}; | ||
2033 | |||
2034 | my @lines = split /\n/, $str; | ||
2035 | |||
2036 | my $addnewline = (($chunk > 0) && ($$contentsref[$chunk-1] ne '')) ? "\n" : ''; | ||
2037 | |||
2038 | my $output = "$addnewline/**\n"; | ||
2039 | foreach (@lines) { | ||
2040 | chomp; | ||
2041 | s/\s*\Z//; | ||
2042 | if ($_ eq '') { | ||
2043 | $output .= " *\n"; | ||
2044 | } else { | ||
2045 | $output .= " * $_\n"; | ||
2046 | } | ||
2047 | } | ||
2048 | $output .= " */"; | ||
2049 | |||
2050 | #print("$sym:\n[$output]\n\n"); | ||
2051 | |||
2052 | $$contentsref[$chunk] = $output; | ||
2053 | #$$contentsref[$chunk+1] = $headerdecls{$sym}; | ||
2054 | |||
2055 | $changed_headers{$header} = 1; | ||
2056 | } | ||
2057 | |||
2058 | foreach (keys %changed_headers) { | ||
2059 | my $header = $_; | ||
2060 | |||
2061 | # this is kinda inefficient, but oh well. | ||
2062 | my @removelines = (); | ||
2063 | foreach (keys %headersymslocation) { | ||
2064 | my $sym = $_; | ||
2065 | next if $headersymshasdoxygen{$sym}; | ||
2066 | next if $headersymslocation{$sym} ne $header; | ||
2067 | # the index of the blank line we put before the function declaration in case we needed to replace it with new content from the wiki. | ||
2068 | push @removelines, $headersymschunk{$sym}; | ||
2069 | } | ||
2070 | |||
2071 | my $contentsref = $headers{$header}; | ||
2072 | foreach (@removelines) { | ||
2073 | delete $$contentsref[$_]; # delete DOES NOT RENUMBER existing elements! | ||
2074 | } | ||
2075 | |||
2076 | my $path = "$incpath/$header.tmp"; | ||
2077 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
2078 | foreach (@$contentsref) { | ||
2079 | print FH "$_\n" if defined $_; | ||
2080 | } | ||
2081 | close(FH); | ||
2082 | rename($path, "$incpath/$header") or die("Can't rename '$path' to '$incpath/$header': $!\n"); | ||
2083 | } | ||
2084 | |||
2085 | if (defined $readmepath) { | ||
2086 | if ( -d $wikireadmepath ) { | ||
2087 | mkdir($readmepath); # just in case | ||
2088 | opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n"); | ||
2089 | while (readdir(DH)) { | ||
2090 | my $dent = $_; | ||
2091 | if ($dent =~ /\A(.*?)\.md\Z/) { # we only bridge Markdown files here. | ||
2092 | next if $1 eq 'FrontPage'; | ||
2093 | filecopy("$wikireadmepath/$dent", "$readmepath/README-$dent", "\n"); | ||
2094 | } | ||
2095 | } | ||
2096 | closedir(DH); | ||
2097 | } | ||
2098 | } | ||
2099 | |||
2100 | } elsif ($copy_direction == -1) { # --copy-to-wiki | ||
2101 | |||
2102 | my %briefs = (); # $briefs{'SDL_OpenAudio'} -> the \brief string for the function. | ||
2103 | |||
2104 | if (defined $changeformat) { | ||
2105 | $dewikify_mode = $changeformat; | ||
2106 | $wordwrap_mode = $changeformat; | ||
2107 | } | ||
2108 | |||
2109 | foreach (keys %headersyms) { | ||
2110 | my $sym = $_; | ||
2111 | next if not $headersymshasdoxygen{$sym}; | ||
2112 | next if $sym =~ /\A\[category documentation\]/; # not real symbols, we handle this elsewhere. | ||
2113 | my $symtype = $headersymstype{$sym}; | ||
2114 | my $origwikitype = defined $wikitypes{$sym} ? $wikitypes{$sym} : 'md'; # default to MarkDown for new stuff. | ||
2115 | my $wikitype = (defined $changeformat) ? $changeformat : $origwikitype; | ||
2116 | die("Unexpected wikitype '$wikitype'") if (($wikitype ne 'mediawiki') and ($wikitype ne 'md') and ($wikitype ne 'manpage')); | ||
2117 | |||
2118 | #print("$sym\n"); next; | ||
2119 | |||
2120 | $wordwrap_mode = $wikitype; | ||
2121 | |||
2122 | my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. | ||
2123 | next if not defined $raw; | ||
2124 | $raw =~ s/\A\s*\\brief\s+//; # Technically we don't need \brief (please turn on JAVADOC_AUTOBRIEF if you use Doxygen), so just in case one is present, strip it. | ||
2125 | |||
2126 | my @doxygenlines = split /\n/, $raw; | ||
2127 | my $brief = ''; | ||
2128 | while (@doxygenlines) { | ||
2129 | last if $doxygenlines[0] =~ /\A\\/; # some sort of doxygen command, assume we're past the general remarks. | ||
2130 | last if $doxygenlines[0] =~ /\A\s*\Z/; # blank line? End of paragraph, done. | ||
2131 | my $l = shift @doxygenlines; | ||
2132 | chomp($l); | ||
2133 | $l =~ s/\A\s*//; | ||
2134 | $l =~ s/\s*\Z//; | ||
2135 | $brief .= "$l "; | ||
2136 | } | ||
2137 | |||
2138 | $brief =~ s/\s+\Z//; | ||
2139 | $brief =~ s/\A(.*?\.) /$1\n\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
2140 | my @briefsplit = split /\n/, $brief; | ||
2141 | |||
2142 | next if not defined $briefsplit[0]; # No brief text? Probably a bogus Doxygen comment, skip it. | ||
2143 | |||
2144 | $brief = wikify($wikitype, shift @briefsplit) . "\n"; | ||
2145 | @doxygenlines = (@briefsplit, @doxygenlines); | ||
2146 | |||
2147 | my $remarks = ''; | ||
2148 | while (@doxygenlines) { | ||
2149 | last if $doxygenlines[0] =~ /\A\\/; # some sort of doxygen command, assume we're past the general remarks. | ||
2150 | my $l = shift @doxygenlines; | ||
2151 | $remarks .= "$l\n"; | ||
2152 | } | ||
2153 | |||
2154 | #print("REMARKS:\n\n $remarks\n\n"); | ||
2155 | |||
2156 | $remarks = wordwrap(wikify($wikitype, $remarks)); | ||
2157 | $remarks =~ s/\A\s*//; | ||
2158 | $remarks =~ s/\s*\Z//; | ||
2159 | |||
2160 | my $decl = $headerdecls{$sym}; | ||
2161 | |||
2162 | my $syntax = ''; | ||
2163 | if ($wikitype eq 'mediawiki') { | ||
2164 | $syntax = "<syntaxhighlight lang='c'>\n$decl</syntaxhighlight>\n"; | ||
2165 | } elsif ($wikitype eq 'md') { | ||
2166 | $decl =~ s/\n+\Z//; | ||
2167 | $syntax = "```c\n$decl\n```\n"; | ||
2168 | } else { die("Expected wikitype '$wikitype'"); } | ||
2169 | |||
2170 | my %sections = (); | ||
2171 | $sections{'[Brief]'} = $brief; # include this section even if blank so we get a title line. | ||
2172 | $sections{'Remarks'} = "$remarks\n" if $remarks ne ''; | ||
2173 | $sections{'Syntax'} = $syntax; | ||
2174 | |||
2175 | $briefs{$sym} = $brief; | ||
2176 | |||
2177 | my %params = (); # have to parse these and build up the wiki tables after, since Markdown needs to know the length of the largest string. :/ | ||
2178 | my @paramsorder = (); | ||
2179 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
2180 | my $has_returns = 0; | ||
2181 | my $has_threadsafety = 0; | ||
2182 | |||
2183 | while (@doxygenlines) { | ||
2184 | my $l = shift @doxygenlines; | ||
2185 | # We allow param/field/value interchangeably, even if it doesn't make sense. The next --copy-to-headers will correct it anyhow. | ||
2186 | if ($l =~ /\A\\(param|field|value)\s+(.*?)\s+(.*)\Z/) { | ||
2187 | my $arg = $2; | ||
2188 | my $desc = $3; | ||
2189 | while (@doxygenlines) { | ||
2190 | my $subline = $doxygenlines[0]; | ||
2191 | $subline =~ s/\A\s*//; | ||
2192 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
2193 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
2194 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
2195 | $desc .= "\n"; | ||
2196 | } else { | ||
2197 | $desc .= " $subline"; | ||
2198 | } | ||
2199 | } | ||
2200 | |||
2201 | $desc =~ s/[\s\n]+\Z//ms; | ||
2202 | |||
2203 | if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. | ||
2204 | if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { | ||
2205 | print STDERR "WARNING: $sym\'s '\\param $arg' text starts with a capital letter: '$desc'. Fixing.\n"; | ||
2206 | $desc = lcfirst($desc); | ||
2207 | } | ||
2208 | } | ||
2209 | |||
2210 | if (not $desc =~ /[\.\!]\Z/) { | ||
2211 | print STDERR "WARNING: $sym\'s '\\param $arg' text doesn't end with punctuation: '$desc'. Fixing.\n"; | ||
2212 | $desc .= '.'; | ||
2213 | } | ||
2214 | |||
2215 | # Validate this param. | ||
2216 | if (defined($params{$arg})) { | ||
2217 | print STDERR "WARNING: Symbol '$sym' has multiple '\\param $arg' declarations! Only keeping the first one!\n"; | ||
2218 | } elsif (defined $fnsigparams) { | ||
2219 | my $found = 0; | ||
2220 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
2221 | $found = 1, last if (@$fnsigparams[$i] eq $arg); | ||
2222 | } | ||
2223 | if (!$found) { | ||
2224 | print STDERR "WARNING: Symbol '$sym' has a '\\param $arg' for a param that doesn't exist. It will be removed!\n"; | ||
2225 | } | ||
2226 | } | ||
2227 | |||
2228 | # We need to know the length of the longest string to make Markdown tables, so we just store these off until everything is parsed. | ||
2229 | $params{$arg} = $desc; | ||
2230 | push @paramsorder, $arg; | ||
2231 | } elsif ($l =~ /\A\\r(eturns?)\s+(.*)\Z/) { | ||
2232 | $has_returns = 1; | ||
2233 | # !!! FIXME: complain if this isn't a function or macro. | ||
2234 | my $retstr = "R$1"; # "Return" or "Returns" | ||
2235 | my $desc = $2; | ||
2236 | |||
2237 | while (@doxygenlines) { | ||
2238 | my $subline = $doxygenlines[0]; | ||
2239 | $subline =~ s/\A\s*//; | ||
2240 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
2241 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
2242 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
2243 | $desc .= "\n"; | ||
2244 | } else { | ||
2245 | $desc .= " $subline"; | ||
2246 | } | ||
2247 | } | ||
2248 | $desc =~ s/[\s\n]+\Z//ms; | ||
2249 | |||
2250 | if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. | ||
2251 | if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { | ||
2252 | print STDERR "WARNING: $sym\'s '\\returns' text starts with a capital letter: '$desc'. Fixing.\n"; | ||
2253 | $desc = lcfirst($desc); | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2257 | if (not $desc =~ /[\.\!]\Z/) { | ||
2258 | print STDERR "WARNING: $sym\'s '\\returns' text doesn't end with punctuation: '$desc'. Fixing.\n"; | ||
2259 | $desc .= '.'; | ||
2260 | } | ||
2261 | |||
2262 | # Make sure the \returns info is valid. | ||
2263 | my $rettype = $headersymsrettype{$sym}; | ||
2264 | die("Don't have a rettype for '$sym' for some reason!") if (($symtype == 1) && (not defined($rettype))); | ||
2265 | if (defined($sections{'Return Value'})) { | ||
2266 | print STDERR "WARNING: Symbol '$sym' has multiple '\\return' declarations! Only keeping the first one!\n"; | ||
2267 | } elsif (($symtype != 1) && ($symtype != 2) && ($symtype != 5)) { # !!! FIXME: if 5, make sure it's a function pointer typedef! | ||
2268 | print STDERR "WARNING: Symbol '$sym' has a '\\return' declaration but isn't a function or macro! Removing it!\n"; | ||
2269 | } elsif (($symtype == 1) && ($headersymsrettype{$sym} eq 'void')) { | ||
2270 | print STDERR "WARNING: Function '$sym' has a '\\returns' declaration but function returns void! Removing it!\n"; | ||
2271 | } else { | ||
2272 | my $rettypestr = defined($rettype) ? ('(' . wikify($wikitype, $rettype) . ') ') : ''; | ||
2273 | $sections{'Return Value'} = wordwrap("$rettypestr$retstr ". wikify($wikitype, $desc)) . "\n"; | ||
2274 | } | ||
2275 | } elsif ($l =~ /\A\\deprecated\s+(.*)\Z/) { | ||
2276 | my $desc = $1; | ||
2277 | while (@doxygenlines) { | ||
2278 | my $subline = $doxygenlines[0]; | ||
2279 | $subline =~ s/\A\s*//; | ||
2280 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
2281 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
2282 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
2283 | $desc .= "\n"; | ||
2284 | } else { | ||
2285 | $desc .= " $subline"; | ||
2286 | } | ||
2287 | } | ||
2288 | $desc =~ s/[\s\n]+\Z//ms; | ||
2289 | $sections{'Deprecated'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
2290 | } elsif ($l =~ /\A\\since\s+(.*)\Z/) { | ||
2291 | my $desc = $1; | ||
2292 | while (@doxygenlines) { | ||
2293 | my $subline = $doxygenlines[0]; | ||
2294 | $subline =~ s/\A\s*//; | ||
2295 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
2296 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
2297 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
2298 | $desc .= "\n"; | ||
2299 | } else { | ||
2300 | $desc .= " $subline"; | ||
2301 | } | ||
2302 | } | ||
2303 | $desc =~ s/[\s\n]+\Z//ms; | ||
2304 | $sections{'Version'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
2305 | } elsif ($l =~ /\A\\threadsafety\s+(.*)\Z/) { | ||
2306 | my $desc = $1; | ||
2307 | while (@doxygenlines) { | ||
2308 | my $subline = $doxygenlines[0]; | ||
2309 | $subline =~ s/\A\s*//; | ||
2310 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
2311 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
2312 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
2313 | $desc .= "\n"; | ||
2314 | } else { | ||
2315 | $desc .= " $subline"; | ||
2316 | } | ||
2317 | } | ||
2318 | $desc =~ s/[\s\n]+\Z//ms; | ||
2319 | $sections{'Thread Safety'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
2320 | $has_threadsafety = 1; | ||
2321 | } elsif ($l =~ /\A\\sa\s+(.*)\Z/) { | ||
2322 | my $sa = $1; | ||
2323 | $sa =~ s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
2324 | $sections{'See Also'} = '' if not defined $sections{'See Also'}; | ||
2325 | if ($wikitype eq 'mediawiki') { | ||
2326 | $sections{'See Also'} .= ":[[$sa]]\n"; | ||
2327 | } elsif ($wikitype eq 'md') { | ||
2328 | $sections{'See Also'} .= "- [$sa]($sa)\n"; | ||
2329 | } else { die("Expected wikitype '$wikitype'"); } | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | if (($symtype == 1) && ($headersymsrettype{$sym} ne 'void') && !$has_returns) { | ||
2334 | print STDERR "WARNING: Function '$sym' has a non-void return type but no '\\returns' declaration\n"; | ||
2335 | } | ||
2336 | |||
2337 | # !!! FIXME: uncomment this when we're trying to clean this up in the headers. | ||
2338 | #if (($symtype == 1) && !$has_threadsafety) { | ||
2339 | # print STDERR "WARNING: Function '$sym' doesn't have a '\\threadsafety' declaration\n"; | ||
2340 | #} | ||
2341 | |||
2342 | # Make sure %params is in the same order as the actual function signature and add C datatypes... | ||
2343 | my $params_has_c_datatype = 0; | ||
2344 | my @final_params = (); | ||
2345 | if (($symtype == 1) && (defined($headersymsparaminfo{$sym}))) { # is a function and we have param info for it... | ||
2346 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
2347 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
2348 | my $paramname = @$fnsigparams[$i]; | ||
2349 | my $paramdesc = $params{$paramname}; | ||
2350 | if (defined($paramdesc)) { | ||
2351 | push @final_params, $paramname; # name | ||
2352 | push @final_params, @$fnsigparams[$i+1]; # C datatype | ||
2353 | push @final_params, $paramdesc; # description | ||
2354 | $params_has_c_datatype = 1 if (defined(@$fnsigparams[$i+1])); | ||
2355 | } else { | ||
2356 | print STDERR "WARNING: Symbol '$sym' is missing a '\\param $paramname' declaration!\n"; | ||
2357 | } | ||
2358 | } | ||
2359 | } else { | ||
2360 | foreach (@paramsorder) { | ||
2361 | my $paramname = $_; | ||
2362 | my $paramdesc = $params{$paramname}; | ||
2363 | if (defined($paramdesc)) { | ||
2364 | push @final_params, $_; | ||
2365 | push @final_params, undef; | ||
2366 | push @final_params, $paramdesc; | ||
2367 | } | ||
2368 | } | ||
2369 | } | ||
2370 | |||
2371 | my $hfiletext = $wikiheaderfiletext; | ||
2372 | $hfiletext =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
2373 | $sections{'Header File'} = "$hfiletext\n"; | ||
2374 | |||
2375 | # Make sure this ends with a double-newline. | ||
2376 | $sections{'See Also'} .= "\n" if defined $sections{'See Also'}; | ||
2377 | |||
2378 | if (0) { # !!! FIXME: this was a useful hack, but this needs to be generalized if we're going to do this always. | ||
2379 | # Plug in a \since section if one wasn't listed. | ||
2380 | if (not defined $sections{'Version'}) { | ||
2381 | my $symtypename; | ||
2382 | if ($symtype == 1) { | ||
2383 | $symtypename = 'function'; | ||
2384 | } elsif ($symtype == 2) { | ||
2385 | $symtypename = 'macro'; | ||
2386 | } elsif ($symtype == 3) { | ||
2387 | $symtypename = 'struct'; | ||
2388 | } elsif ($symtype == 4) { | ||
2389 | $symtypename = 'enum'; | ||
2390 | } elsif ($symtype == 5) { | ||
2391 | $symtypename = 'datatype'; | ||
2392 | } else { | ||
2393 | die("Unexpected symbol type $symtype!"); | ||
2394 | } | ||
2395 | my $str = "This $symtypename is available since SDL 3.0.0."; | ||
2396 | $sections{'Version'} = wordwrap(wikify($wikitype, $str)) . "\n"; | ||
2397 | } | ||
2398 | } | ||
2399 | |||
2400 | # We can build the wiki table now that we have all the data. | ||
2401 | if (scalar(@final_params) > 0) { | ||
2402 | my $str = ''; | ||
2403 | if ($wikitype eq 'mediawiki') { | ||
2404 | while (scalar(@final_params) > 0) { | ||
2405 | my $arg = shift @final_params; | ||
2406 | my $c_datatype = shift @final_params; | ||
2407 | my $desc = wikify($wikitype, shift @final_params); | ||
2408 | $c_datatype = '' if not defined $c_datatype; | ||
2409 | $str .= ($str eq '') ? "{|\n" : "|-\n"; | ||
2410 | $str .= "|$c_datatype\n" if $params_has_c_datatype; | ||
2411 | $str .= "|'''$arg'''\n"; | ||
2412 | $str .= "|$desc\n"; | ||
2413 | } | ||
2414 | $str .= "|}\n"; | ||
2415 | } elsif ($wikitype eq 'md') { | ||
2416 | my $longest_arg = 0; | ||
2417 | my $longest_c_datatype = 0; | ||
2418 | my $longest_desc = 0; | ||
2419 | my $which = 0; | ||
2420 | foreach (@final_params) { | ||
2421 | if ($which == 0) { | ||
2422 | my $len = length($_); | ||
2423 | $longest_arg = $len if ($len > $longest_arg); | ||
2424 | $which = 1; | ||
2425 | } elsif ($which == 1) { | ||
2426 | if (defined($_)) { | ||
2427 | my $len = length(wikify($wikitype, $_)); | ||
2428 | $longest_c_datatype = $len if ($len > $longest_c_datatype); | ||
2429 | } | ||
2430 | $which = 2; | ||
2431 | } else { | ||
2432 | my $len = length(wikify($wikitype, $_)); | ||
2433 | $longest_desc = $len if ($len > $longest_desc); | ||
2434 | $which = 0; | ||
2435 | } | ||
2436 | } | ||
2437 | |||
2438 | # Markdown tables are sort of obnoxious. | ||
2439 | my $c_datatype_cell; | ||
2440 | $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . (' ' x ($longest_c_datatype)) . ' ') : ''; | ||
2441 | $str .= $c_datatype_cell . '| ' . (' ' x ($longest_arg+4)) . ' | ' . (' ' x $longest_desc) . " |\n"; | ||
2442 | $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . ('-' x ($longest_c_datatype)) . ' ') : ''; | ||
2443 | $str .= $c_datatype_cell . '| ' . ('-' x ($longest_arg+4)) . ' | ' . ('-' x $longest_desc) . " |\n"; | ||
2444 | |||
2445 | while (@final_params) { | ||
2446 | my $arg = shift @final_params; | ||
2447 | my $c_datatype = shift @final_params; | ||
2448 | $c_datatype_cell = ''; | ||
2449 | if ($params_has_c_datatype) { | ||
2450 | $c_datatype = defined($c_datatype) ? wikify($wikitype, $c_datatype) : ''; | ||
2451 | $c_datatype_cell = ($longest_c_datatype > 0) ? ("| $c_datatype " . (' ' x ($longest_c_datatype - length($c_datatype)))) : ''; | ||
2452 | } | ||
2453 | my $desc = wikify($wikitype, shift @final_params); | ||
2454 | $str .= $c_datatype_cell . "| **$arg** " . (' ' x ($longest_arg - length($arg))) . "| $desc" . (' ' x ($longest_desc - length($desc))) . " |\n"; | ||
2455 | } | ||
2456 | } else { | ||
2457 | die("Unexpected wikitype!"); # should have checked this elsewhere. | ||
2458 | } | ||
2459 | $sections{'Function Parameters'} = $str; | ||
2460 | } | ||
2461 | |||
2462 | my $path = "$wikipath/$sym.${wikitype}.tmp"; | ||
2463 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
2464 | |||
2465 | my $sectionsref = $wikisyms{$sym}; | ||
2466 | |||
2467 | foreach (@standard_wiki_sections) { | ||
2468 | # drop sections we either replaced or removed from the original wiki's contents. | ||
2469 | if (not defined $only_wiki_sections{$_}) { | ||
2470 | delete($$sectionsref{$_}); | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | my $wikisectionorderref = $wikisectionorder{$sym}; | ||
2475 | |||
2476 | # Make sure there's a footer in the wiki that puts this function in CategoryAPI... | ||
2477 | if (not $$sectionsref{'[footer]'}) { | ||
2478 | $$sectionsref{'[footer]'} = ''; | ||
2479 | push @$wikisectionorderref, '[footer]'; | ||
2480 | } | ||
2481 | |||
2482 | # If changing format, convert things that otherwise are passed through unmolested. | ||
2483 | if (defined $changeformat) { | ||
2484 | if (($dewikify_mode eq 'md') and ($origwikitype eq 'mediawiki')) { | ||
2485 | $$sectionsref{'[footer]'} =~ s/\[\[(Category[a-zA-Z0-9_]+)\]\]/[$1]($1)/g; | ||
2486 | } elsif (($dewikify_mode eq 'mediawiki') and ($origwikitype eq 'md')) { | ||
2487 | $$sectionsref{'[footer]'} =~ s/\[(Category[a-zA-Z0-9_]+)\]\(.*?\)/[[$1]]/g; | ||
2488 | } | ||
2489 | |||
2490 | foreach (keys %only_wiki_sections) { | ||
2491 | my $sect = $_; | ||
2492 | if (defined $$sectionsref{$sect}) { | ||
2493 | $$sectionsref{$sect} = wikify($wikitype, dewikify($origwikitype, $$sectionsref{$sect})); | ||
2494 | } | ||
2495 | } | ||
2496 | } | ||
2497 | |||
2498 | if ($symtype != -1) { # Don't do these in category documentation block | ||
2499 | my $footer = $$sectionsref{'[footer]'}; | ||
2500 | |||
2501 | my $symtypename; | ||
2502 | if ($symtype == 1) { | ||
2503 | $symtypename = 'Function'; | ||
2504 | } elsif ($symtype == 2) { | ||
2505 | $symtypename = 'Macro'; | ||
2506 | } elsif ($symtype == 3) { | ||
2507 | $symtypename = 'Struct'; | ||
2508 | } elsif ($symtype == 4) { | ||
2509 | $symtypename = 'Enum'; | ||
2510 | } elsif ($symtype == 5) { | ||
2511 | $symtypename = 'Datatype'; | ||
2512 | } else { | ||
2513 | die("Unexpected symbol type $symtype!"); | ||
2514 | } | ||
2515 | |||
2516 | my $symcategory = $headersymscategory{$sym}; | ||
2517 | if ($wikitype eq 'mediawiki') { | ||
2518 | $footer =~ s/\[\[CategoryAPI\]\],?\s*//g; | ||
2519 | $footer =~ s/\[\[CategoryAPI${symtypename}\]\],?\s*//g; | ||
2520 | $footer =~ s/\[\[Category${symcategory}\]\],?\s*//g if defined $symcategory; | ||
2521 | $footer = "[[CategoryAPI]], [[CategoryAPI$symtypename]]" . (defined $symcategory ? ", [[Category$symcategory]]" : '') . (($footer eq '') ? "\n" : ", $footer"); | ||
2522 | } elsif ($wikitype eq 'md') { | ||
2523 | $footer =~ s/\[CategoryAPI\]\(CategoryAPI\),?\s*//g; | ||
2524 | $footer =~ s/\[CategoryAPI${symtypename}\]\(CategoryAPI${symtypename}\),?\s*//g; | ||
2525 | $footer =~ s/\[Category${symcategory}\]\(Category${symcategory}\),?\s*//g if defined $symcategory; | ||
2526 | $footer = "[CategoryAPI](CategoryAPI), [CategoryAPI$symtypename](CategoryAPI$symtypename)" . (defined $symcategory ? ", [Category$symcategory](Category$symcategory)" : '') . (($footer eq '') ? '' : ', ') . $footer; | ||
2527 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
2528 | $$sectionsref{'[footer]'} = $footer; | ||
2529 | |||
2530 | if (defined $wikipreamble) { | ||
2531 | my $wikified_preamble = wikify($wikitype, $wikipreamble); | ||
2532 | if ($wikitype eq 'mediawiki') { | ||
2533 | print FH "====== $wikified_preamble ======\n"; | ||
2534 | } elsif ($wikitype eq 'md') { | ||
2535 | print FH "###### $wikified_preamble\n"; | ||
2536 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | my $prevsectstr = ''; | ||
2541 | my @ordered_sections = (@standard_wiki_sections, defined $wikisectionorderref ? @$wikisectionorderref : ()); # this copies the arrays into one. | ||
2542 | foreach (@ordered_sections) { | ||
2543 | my $sect = $_; | ||
2544 | next if $sect eq '[start]'; | ||
2545 | next if (not defined $sections{$sect} and not defined $$sectionsref{$sect}); | ||
2546 | my $section = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; | ||
2547 | |||
2548 | if ($sect eq '[footer]') { | ||
2549 | # Make sure previous section ends with two newlines. | ||
2550 | if (substr($prevsectstr, -1) ne "\n") { | ||
2551 | print FH "\n\n"; | ||
2552 | } elsif (substr($prevsectstr, -2) ne "\n\n") { | ||
2553 | print FH "\n"; | ||
2554 | } | ||
2555 | print FH "----\n"; # It's the same in Markdown and MediaWiki. | ||
2556 | } elsif ($sect eq '[Brief]') { | ||
2557 | if ($wikitype eq 'mediawiki') { | ||
2558 | print FH "= $sym =\n\n"; | ||
2559 | } elsif ($wikitype eq 'md') { | ||
2560 | print FH "# $sym\n\n"; | ||
2561 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
2562 | } else { | ||
2563 | my $sectname = $sect; | ||
2564 | if ($sectname eq 'Function Parameters') { # We use this same table for different things depending on what we're documenting, so rename it now. | ||
2565 | if (($symtype == 1) || ($symtype == 5)) { # function (or typedef, in case it's a function pointer type). | ||
2566 | } elsif ($symtype == 2) { # macro | ||
2567 | $sectname = 'Macro Parameters'; | ||
2568 | } elsif ($symtype == 3) { # struct/union | ||
2569 | $sectname = 'Fields'; | ||
2570 | } elsif ($symtype == 4) { # enum | ||
2571 | $sectname = 'Values'; | ||
2572 | } else { | ||
2573 | die("Unexpected symtype $symtype"); | ||
2574 | } | ||
2575 | } | ||
2576 | |||
2577 | if ($symtype != -1) { # Not for category documentation block | ||
2578 | if ($wikitype eq 'mediawiki') { | ||
2579 | print FH "\n== $sectname ==\n\n"; | ||
2580 | } elsif ($wikitype eq 'md') { | ||
2581 | print FH "\n## $sectname\n\n"; | ||
2582 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
2583 | } | ||
2584 | } | ||
2585 | |||
2586 | my $sectstr = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; | ||
2587 | print FH $sectstr; | ||
2588 | |||
2589 | $prevsectstr = $sectstr; | ||
2590 | |||
2591 | # make sure these don't show up twice. | ||
2592 | delete($sections{$sect}); | ||
2593 | delete($$sectionsref{$sect}); | ||
2594 | } | ||
2595 | |||
2596 | print FH "\n\n"; | ||
2597 | close(FH); | ||
2598 | |||
2599 | if (defined $changeformat and ($origwikitype ne $wikitype)) { | ||
2600 | system("cd '$wikipath' ; git mv '$_.${origwikitype}' '$_.${wikitype}'"); | ||
2601 | unlink("$wikipath/$_.${origwikitype}"); | ||
2602 | } | ||
2603 | |||
2604 | rename($path, "$wikipath/$_.${wikitype}") or die("Can't rename '$path' to '$wikipath/$_.${wikitype}': $!\n"); | ||
2605 | } | ||
2606 | |||
2607 | # Write out simple redirector pages if they don't already exist. | ||
2608 | foreach (keys %referenceonly) { | ||
2609 | my $sym = $_; | ||
2610 | my $refersto = $referenceonly{$sym}; | ||
2611 | my $path = "$wikipath/$sym.md"; # we only do Markdown for these. | ||
2612 | next if (-f $path); # don't overwrite if it already exists. Delete the file if you need a rebuild! | ||
2613 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
2614 | |||
2615 | if (defined $wikipreamble) { | ||
2616 | my $wikified_preamble = wikify('md', $wikipreamble); | ||
2617 | print FH "###### $wikified_preamble\n"; | ||
2618 | } | ||
2619 | |||
2620 | my $category = 'CategoryAPIMacro'; | ||
2621 | if ($headersymstype{$refersto} == 4) { | ||
2622 | $category = 'CategoryAPIEnumerators'; # NOT CategoryAPIEnum! | ||
2623 | } | ||
2624 | |||
2625 | print FH "# $sym\n\nPlease refer to [$refersto]($refersto) for details.\n\n"; | ||
2626 | print FH "----\n"; | ||
2627 | print FH "[CategoryAPI](CategoryAPI), [$category]($category)\n\n"; | ||
2628 | |||
2629 | close(FH); | ||
2630 | } | ||
2631 | |||
2632 | # Write out Category pages... | ||
2633 | foreach (keys %headercategorydocs) { | ||
2634 | my $cat = $_; | ||
2635 | my $sym = $headercategorydocs{$cat}; # fake symbol | ||
2636 | my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. | ||
2637 | my $wikitype = defined($wikitypes{$sym}) ? $wikitypes{$sym} : 'md'; | ||
2638 | my $path = "$wikipath/Category$cat.$wikitype"; | ||
2639 | |||
2640 | $raw = wordwrap(wikify($wikitype, $raw)); | ||
2641 | |||
2642 | my $tmppath = "$path.tmp"; | ||
2643 | open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
2644 | print FH "$raw\n\n"; | ||
2645 | |||
2646 | if (! -f $path) { # Doesn't exist at all? Write out a template file. | ||
2647 | # If writing from scratch, it's always a Markdown file. | ||
2648 | die("Unexpected wikitype '$wikitype'!") if $wikitype ne 'md'; | ||
2649 | print FH <<__EOF__ | ||
2650 | |||
2651 | <!-- END CATEGORY DOCUMENTATION --> | ||
2652 | |||
2653 | ## Functions | ||
2654 | |||
2655 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
2656 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIFunction --> | ||
2657 | <!-- END CATEGORY LIST --> | ||
2658 | |||
2659 | ## Datatypes | ||
2660 | |||
2661 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
2662 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIDatatype --> | ||
2663 | <!-- END CATEGORY LIST --> | ||
2664 | |||
2665 | ## Structs | ||
2666 | |||
2667 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
2668 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIStruct --> | ||
2669 | <!-- END CATEGORY LIST --> | ||
2670 | |||
2671 | ## Enums | ||
2672 | |||
2673 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
2674 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIEnum --> | ||
2675 | <!-- END CATEGORY LIST --> | ||
2676 | |||
2677 | ## Macros | ||
2678 | |||
2679 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
2680 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIMacro --> | ||
2681 | <!-- END CATEGORY LIST --> | ||
2682 | |||
2683 | ---- | ||
2684 | [CategoryAPICategory](CategoryAPICategory) | ||
2685 | |||
2686 | __EOF__ | ||
2687 | ; | ||
2688 | } else { | ||
2689 | my $endstr = $wikisyms{$sym}->{'[footer]'}; | ||
2690 | if (defined($endstr)) { | ||
2691 | print FH $endstr; | ||
2692 | } | ||
2693 | } | ||
2694 | |||
2695 | close(FH); | ||
2696 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
2697 | } | ||
2698 | |||
2699 | # Write out READMEs... | ||
2700 | if (defined $readmepath) { | ||
2701 | if ( -d $readmepath ) { | ||
2702 | mkdir($wikireadmepath); # just in case | ||
2703 | opendir(DH, $readmepath) or die("Can't opendir '$readmepath': $!\n"); | ||
2704 | while (my $d = readdir(DH)) { | ||
2705 | my $dent = $d; | ||
2706 | if ($dent =~ /\AREADME\-(.*?\.md)\Z/) { # we only bridge Markdown files here. | ||
2707 | my $wikifname = $1; | ||
2708 | next if $wikifname eq 'FrontPage.md'; | ||
2709 | filecopy("$readmepath/$dent", "$wikireadmepath/$wikifname", "\n"); | ||
2710 | } | ||
2711 | } | ||
2712 | closedir(DH); | ||
2713 | |||
2714 | my @pages = (); | ||
2715 | opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n"); | ||
2716 | while (my $d = readdir(DH)) { | ||
2717 | my $dent = $d; | ||
2718 | if ($dent =~ /\A(.*?)\.(mediawiki|md)\Z/) { | ||
2719 | my $wikiname = $1; | ||
2720 | next if $wikiname eq 'FrontPage'; | ||
2721 | push @pages, $wikiname; | ||
2722 | } | ||
2723 | } | ||
2724 | closedir(DH); | ||
2725 | |||
2726 | open(FH, '>', "$wikireadmepath/FrontPage.md") or die("Can't open '$wikireadmepath/FrontPage.md': $!\n"); | ||
2727 | print FH "# All READMEs available here\n\n"; | ||
2728 | foreach (sort @pages) { | ||
2729 | my $wikiname = $_; | ||
2730 | print FH "- [$wikiname]($wikiname)\n"; | ||
2731 | } | ||
2732 | close(FH); | ||
2733 | } | ||
2734 | } | ||
2735 | |||
2736 | # Write out quick reference pages... | ||
2737 | if ($quickrefenabled) { | ||
2738 | generate_quickref(\%briefs, "$wikipath/QuickReference.md", 0); | ||
2739 | generate_quickref(\%briefs, "$wikipath/QuickReferenceNoUnicode.md", 1); | ||
2740 | } | ||
2741 | } elsif ($copy_direction == -2) { # --copy-to-manpages | ||
2742 | # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. | ||
2743 | |||
2744 | File::Path::make_path("$manpath/man3"); | ||
2745 | |||
2746 | $dewikify_mode = 'manpage'; | ||
2747 | $wordwrap_mode = 'manpage'; | ||
2748 | |||
2749 | my $introtxt = ''; | ||
2750 | if (0) { | ||
2751 | open(FH, '<', "$srcpath/LICENSE.txt") or die("Can't open '$srcpath/LICENSE.txt': $!\n"); | ||
2752 | while (<FH>) { | ||
2753 | chomp; | ||
2754 | $introtxt .= ".\\\" $_\n"; | ||
2755 | } | ||
2756 | close(FH); | ||
2757 | } | ||
2758 | |||
2759 | if (!$gitrev) { | ||
2760 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
2761 | chomp($gitrev); | ||
2762 | } | ||
2763 | |||
2764 | # !!! FIXME | ||
2765 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
2766 | my $majorver = 0; | ||
2767 | my $minorver = 0; | ||
2768 | my $microver = 0; | ||
2769 | while (<FH>) { | ||
2770 | chomp; | ||
2771 | if (/$versionmajorregex/) { | ||
2772 | $majorver = int($1); | ||
2773 | } elsif (/$versionminorregex/) { | ||
2774 | $minorver = int($1); | ||
2775 | } elsif (/$versionmicroregex/) { | ||
2776 | $microver = int($1); | ||
2777 | } | ||
2778 | } | ||
2779 | close(FH); | ||
2780 | my $fullversion = "$majorver.$minorver.$microver"; | ||
2781 | |||
2782 | foreach (keys %headersyms) { | ||
2783 | my $sym = $_; | ||
2784 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
2785 | next if $sym =~ /\A\[category documentation\]/; # not real symbols | ||
2786 | next if (defined $manpagesymbolfilterregex) && ($sym =~ /$manpagesymbolfilterregex/); | ||
2787 | my $symtype = $headersymstype{$sym}; | ||
2788 | my $wikitype = $wikitypes{$sym}; | ||
2789 | my $sectionsref = $wikisyms{$sym}; | ||
2790 | my $remarks = $sectionsref->{'Remarks'}; | ||
2791 | my $returns = $sectionsref->{'Return Value'}; | ||
2792 | my $version = $sectionsref->{'Version'}; | ||
2793 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
2794 | my $related = $sectionsref->{'See Also'}; | ||
2795 | my $examples = $sectionsref->{'Code Examples'}; | ||
2796 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
2797 | my $headerfile = $manpageheaderfiletext; | ||
2798 | |||
2799 | my $params = undef; | ||
2800 | |||
2801 | if ($symtype == -1) { # category documentation block. | ||
2802 | # nothing to be done here. | ||
2803 | } elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef. | ||
2804 | $params = $sectionsref->{'Function Parameters'}; | ||
2805 | } elsif ($symtype == 2) { | ||
2806 | $params = $sectionsref->{'Macro Parameters'}; | ||
2807 | } elsif ($symtype == 3) { | ||
2808 | $params = $sectionsref->{'Fields'}; | ||
2809 | } elsif ($symtype == 4) { | ||
2810 | $params = $sectionsref->{'Values'}; | ||
2811 | } else { | ||
2812 | die("Unexpected symtype $symtype"); | ||
2813 | } | ||
2814 | |||
2815 | $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
2816 | $headerfile .= "\n"; | ||
2817 | |||
2818 | my $mansection; | ||
2819 | my $mansectionname; | ||
2820 | if (($symtype == 1) || ($symtype == 2)) { # functions or macros | ||
2821 | $mansection = '3'; | ||
2822 | $mansectionname = 'FUNCTIONS'; | ||
2823 | } elsif (($symtype >= 3) && ($symtype <= 5)) { # struct/union/enum/typedef | ||
2824 | $mansection = '3type'; | ||
2825 | $mansectionname = 'DATATYPES'; | ||
2826 | } else { | ||
2827 | die("Unexpected symtype $symtype"); | ||
2828 | } | ||
2829 | |||
2830 | my $brief = $sectionsref->{'[Brief]'}; | ||
2831 | my $decl = $headerdecls{$sym}; | ||
2832 | my $str = ''; | ||
2833 | |||
2834 | # the "$brief" makes sure this is a copy of the string, which is doing some weird reference thing otherwise. | ||
2835 | $brief = defined $brief ? "$brief" : ''; | ||
2836 | $brief =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
2837 | $brief =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
2838 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
2839 | my @briefsplit = split /\n/, $brief; | ||
2840 | $brief = shift @briefsplit; | ||
2841 | $brief = dewikify($wikitype, $brief); | ||
2842 | |||
2843 | if (defined $remarks) { | ||
2844 | $remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks); | ||
2845 | } | ||
2846 | |||
2847 | $str .= $introtxt; | ||
2848 | |||
2849 | $str .= ".\\\" This manpage content is licensed under Creative Commons\n"; | ||
2850 | $str .= ".\\\" Attribution 4.0 International (CC BY 4.0)\n"; | ||
2851 | $str .= ".\\\" https://creativecommons.org/licenses/by/4.0/\n"; | ||
2852 | $str .= ".\\\" This manpage was generated from ${projectshortname}'s wiki page for $sym:\n"; | ||
2853 | $str .= ".\\\" $wikiurl/$sym\n"; | ||
2854 | $str .= ".\\\" Generated with SDL/build-scripts/wikiheaders.pl\n"; | ||
2855 | $str .= ".\\\" revision $gitrev\n" if $gitrev ne ''; | ||
2856 | $str .= ".\\\" Please report issues in this manpage's content at:\n"; | ||
2857 | $str .= ".\\\" $bugreporturl\n"; | ||
2858 | $str .= ".\\\" Please report issues in the generation of this manpage from the wiki at:\n"; | ||
2859 | $str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$sym\n"; | ||
2860 | $str .= ".\\\" $projectshortname can be found at $projecturl\n"; | ||
2861 | |||
2862 | # Define a .URL macro. The "www.tmac" thing decides if we're using GNU roff (which has a .URL macro already), and if so, overrides the macro we just created. | ||
2863 | # This wizadry is from https://web.archive.org/web/20060102165607/http://people.debian.org/~branden/talks/wtfm/wtfm.pdf | ||
2864 | $str .= ".de URL\n"; | ||
2865 | $str .= '\\$2 \(laURL: \\$1 \(ra\\$3' . "\n"; | ||
2866 | $str .= "..\n"; | ||
2867 | $str .= '.if \n[.g] .mso www.tmac' . "\n"; | ||
2868 | |||
2869 | $str .= ".TH $sym $mansection \"$projectshortname $fullversion\" \"$projectfullname\" \"$projectshortname$majorver $mansectionname\"\n"; | ||
2870 | $str .= ".SH NAME\n"; | ||
2871 | |||
2872 | $str .= "$sym"; | ||
2873 | $str .= " \\- $brief" if (defined $brief); | ||
2874 | $str .= "\n"; | ||
2875 | |||
2876 | if (defined $deprecated) { | ||
2877 | $str .= ".SH DEPRECATED\n"; | ||
2878 | $str .= dewikify($wikitype, $deprecated) . "\n"; | ||
2879 | } | ||
2880 | |||
2881 | my $incfile = $mainincludefname; | ||
2882 | if (defined $headerfile) { | ||
2883 | if($headerfile =~ /Defined in (.*)/) { | ||
2884 | $incfile = $1; | ||
2885 | } | ||
2886 | } | ||
2887 | |||
2888 | $str .= ".SH SYNOPSIS\n"; | ||
2889 | $str .= ".nf\n"; | ||
2890 | $str .= ".B #include <$incfile>\n"; | ||
2891 | $str .= ".PP\n"; | ||
2892 | |||
2893 | my @decllines = split /\n/, $decl; | ||
2894 | foreach (@decllines) { | ||
2895 | $_ =~ s/\\/\\(rs/g; # fix multiline macro defs | ||
2896 | $_ =~ s/"/\\(dq/g; | ||
2897 | $str .= ".BI \"$_\n"; | ||
2898 | } | ||
2899 | $str .= ".fi\n"; | ||
2900 | |||
2901 | if (defined $remarks) { | ||
2902 | $str .= ".SH DESCRIPTION\n"; | ||
2903 | $str .= $remarks . "\n"; | ||
2904 | } | ||
2905 | |||
2906 | if (defined $params) { | ||
2907 | if (($symtype == 1) || ($symtype == 5)) { | ||
2908 | $str .= ".SH FUNCTION PARAMETERS\n"; | ||
2909 | } elsif ($symtype == 2) { # macro | ||
2910 | $str .= ".SH MACRO PARAMETERS\n"; | ||
2911 | } elsif ($symtype == 3) { # struct/union | ||
2912 | $str .= ".SH FIELDS\n"; | ||
2913 | } elsif ($symtype == 4) { # enum | ||
2914 | $str .= ".SH VALUES\n"; | ||
2915 | } else { | ||
2916 | die("Unexpected symtype $symtype"); | ||
2917 | } | ||
2918 | |||
2919 | my @lines = split /\n/, $params; | ||
2920 | if ($wikitype eq 'mediawiki') { | ||
2921 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
2922 | while (scalar(@lines) >= 3) { | ||
2923 | my $c_datatype = shift @lines; | ||
2924 | my $name = shift @lines; | ||
2925 | my $desc = shift @lines; | ||
2926 | my $terminator; # the '|-' or '|}' line. | ||
2927 | |||
2928 | if (($desc eq '|-') or ($desc eq '|}') or (not $desc =~ /\A\|/)) { # we seem to be out of cells, which means there was no datatype column on this one. | ||
2929 | $terminator = $desc; | ||
2930 | $desc = $name; | ||
2931 | $name = $c_datatype; | ||
2932 | $c_datatype = ''; | ||
2933 | } else { | ||
2934 | $terminator = shift @lines; | ||
2935 | } | ||
2936 | |||
2937 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
2938 | $name =~ s/\A\|\s*//; | ||
2939 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
2940 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
2941 | $desc =~ s/\A\|\s*//; | ||
2942 | $desc = dewikify($wikitype, $desc); | ||
2943 | #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; | ||
2944 | |||
2945 | $str .= ".TP\n"; | ||
2946 | $str .= ".I $name\n"; | ||
2947 | $str .= "$desc\n"; | ||
2948 | } | ||
2949 | } elsif ($wikitype eq 'md') { | ||
2950 | my $l; | ||
2951 | $l = shift @lines; | ||
2952 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
2953 | $l = shift @lines; | ||
2954 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
2955 | while (scalar(@lines) >= 1) { | ||
2956 | $l = shift @lines; | ||
2957 | my $name; | ||
2958 | my $desc; | ||
2959 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
2960 | # c datatype is $1, but we don't care about it here. | ||
2961 | $name = $2; | ||
2962 | $desc = $3; | ||
2963 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
2964 | $name = $1; | ||
2965 | $desc = $2; | ||
2966 | } else { | ||
2967 | last; # we seem to have run out of table. | ||
2968 | } | ||
2969 | |||
2970 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
2971 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
2972 | $desc = dewikify($wikitype, $desc); | ||
2973 | |||
2974 | $str .= ".TP\n"; | ||
2975 | $str .= ".I $name\n"; | ||
2976 | $str .= "$desc\n"; | ||
2977 | } | ||
2978 | } else { | ||
2979 | die("write me"); | ||
2980 | } | ||
2981 | } | ||
2982 | |||
2983 | if (defined $returns) { | ||
2984 | # Chop datatype in parentheses off the front. | ||
2985 | if(!($returns =~ s/\A\([^\[]*\[[^\]]*\]\([^\)]*\)[^\)]*\) //ms)) { | ||
2986 | $returns =~ s/\A\([^\)]*\) //ms; | ||
2987 | } | ||
2988 | $returns = dewikify($wikitype, $returns); | ||
2989 | $str .= ".SH RETURN VALUE\n"; | ||
2990 | $str .= "$returns\n"; | ||
2991 | } | ||
2992 | |||
2993 | if (defined $examples) { | ||
2994 | $str .= ".SH CODE EXAMPLES\n"; | ||
2995 | $dewikify_manpage_code_indent = 0; | ||
2996 | $str .= dewikify($wikitype, $examples) . "\n"; | ||
2997 | $dewikify_manpage_code_indent = 1; | ||
2998 | } | ||
2999 | |||
3000 | if (defined $threadsafety) { | ||
3001 | $str .= ".SH THREAD SAFETY\n"; | ||
3002 | $str .= dewikify($wikitype, $threadsafety) . "\n"; | ||
3003 | } | ||
3004 | |||
3005 | if (defined $version) { | ||
3006 | $str .= ".SH AVAILABILITY\n"; | ||
3007 | $str .= dewikify($wikitype, $version) . "\n"; | ||
3008 | } | ||
3009 | |||
3010 | if (defined $related) { | ||
3011 | $str .= ".SH SEE ALSO\n"; | ||
3012 | # !!! FIXME: lots of code duplication in all of these. | ||
3013 | my $v = dewikify($wikitype, $related); | ||
3014 | my @desclines = split /\n/, $v; | ||
3015 | my $nextstr = ''; | ||
3016 | foreach (@desclines) { | ||
3017 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
3018 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
3019 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
3020 | s/\A\*\s*\Z//; | ||
3021 | s/\A\/*//; | ||
3022 | s/\A\.BR\s+//; # dewikify added this, but we want to handle it. | ||
3023 | s/\A\.I\s+//; # dewikify added this, but we want to handle it. | ||
3024 | s/\A\.PP\s*//; # dewikify added this, but we want to handle it. | ||
3025 | s/\\\(bu//; # dewikify added this, but we want to handle it. | ||
3026 | s/\A\s*[\:\*\-]\s*//; | ||
3027 | s/\A\s+//; | ||
3028 | s/\s+\Z//; | ||
3029 | next if $_ eq ''; | ||
3030 | my $seealso_symtype = $headersymstype{$_}; | ||
3031 | my $seealso_mansection = '3'; | ||
3032 | if (defined($seealso_symtype) && ($seealso_symtype >= 3) && ($seealso_symtype <= 5)) { # struct/union/enum/typedef | ||
3033 | $seealso_mansection = '3type'; | ||
3034 | } | ||
3035 | $str .= "$nextstr.BR $_ ($seealso_mansection)"; | ||
3036 | $nextstr = ",\n"; | ||
3037 | } | ||
3038 | $str .= "\n"; | ||
3039 | } | ||
3040 | |||
3041 | if (0) { | ||
3042 | $str .= ".SH COPYRIGHT\n"; | ||
3043 | $str .= "This manpage is licensed under\n"; | ||
3044 | $str .= ".UR https://creativecommons.org/licenses/by/4.0/\n"; | ||
3045 | $str .= "Creative Commons Attribution 4.0 International (CC BY 4.0)\n"; | ||
3046 | $str .= ".UE\n"; | ||
3047 | $str .= ".PP\n"; | ||
3048 | $str .= "This manpage was generated from\n"; | ||
3049 | $str .= ".UR $wikiurl/$sym\n"; | ||
3050 | $str .= "${projectshortname}'s wiki\n"; | ||
3051 | $str .= ".UE\n"; | ||
3052 | $str .= "using SDL/build-scripts/wikiheaders.pl"; | ||
3053 | $str .= " revision $gitrev" if $gitrev ne ''; | ||
3054 | $str .= ".\n"; | ||
3055 | $str .= "Please report issues in this manpage at\n"; | ||
3056 | $str .= ".UR $bugreporturl\n"; | ||
3057 | $str .= "our bugtracker!\n"; | ||
3058 | $str .= ".UE\n"; | ||
3059 | } | ||
3060 | |||
3061 | my $path = "$manpath/man3/$_.$mansection"; | ||
3062 | my $tmppath = "$path.tmp"; | ||
3063 | open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
3064 | print FH $str; | ||
3065 | close(FH); | ||
3066 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
3067 | } | ||
3068 | |||
3069 | } elsif ($copy_direction == -4) { # --copy-to-latex | ||
3070 | # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. | ||
3071 | |||
3072 | print STDERR "\n(The --copy-to-latex code is known to not be ready for serious use; send patches, not bug reports, please.)\n\n"; | ||
3073 | |||
3074 | $dewikify_mode = 'LaTeX'; | ||
3075 | $wordwrap_mode = 'LaTeX'; | ||
3076 | |||
3077 | # !!! FIXME: code duplication with --copy-to-manpages section. | ||
3078 | |||
3079 | my $introtxt = ''; | ||
3080 | if (0) { | ||
3081 | open(FH, '<', "$srcpath/LICENSE.txt") or die("Can't open '$srcpath/LICENSE.txt': $!\n"); | ||
3082 | while (<FH>) { | ||
3083 | chomp; | ||
3084 | $introtxt .= ".\\\" $_\n"; | ||
3085 | } | ||
3086 | close(FH); | ||
3087 | } | ||
3088 | |||
3089 | if (!$gitrev) { | ||
3090 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
3091 | chomp($gitrev); | ||
3092 | } | ||
3093 | |||
3094 | # !!! FIXME | ||
3095 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
3096 | my $majorver = 0; | ||
3097 | my $minorver = 0; | ||
3098 | my $microver = 0; | ||
3099 | while (<FH>) { | ||
3100 | chomp; | ||
3101 | if (/$versionmajorregex/) { | ||
3102 | $majorver = int($1); | ||
3103 | } elsif (/$versionminorregex/) { | ||
3104 | $minorver = int($1); | ||
3105 | } elsif (/$versionmicroregex/) { | ||
3106 | $microver = int($1); | ||
3107 | } | ||
3108 | } | ||
3109 | close(FH); | ||
3110 | my $fullversion = "$majorver.$minorver.$microver"; | ||
3111 | |||
3112 | my $latex_fname = "$srcpath/$projectshortname.tex"; | ||
3113 | my $latex_tmpfname = "$latex_fname.tmp"; | ||
3114 | open(TEXFH, '>', "$latex_tmpfname") or die("Can't open '$latex_tmpfname' for writing: $!\n"); | ||
3115 | |||
3116 | print TEXFH <<__EOF__ | ||
3117 | \\documentclass{book} | ||
3118 | |||
3119 | \\usepackage{listings} | ||
3120 | \\usepackage{color} | ||
3121 | \\usepackage{hyperref} | ||
3122 | |||
3123 | \\definecolor{dkgreen}{rgb}{0,0.6,0} | ||
3124 | \\definecolor{gray}{rgb}{0.5,0.5,0.5} | ||
3125 | \\definecolor{mauve}{rgb}{0.58,0,0.82} | ||
3126 | |||
3127 | \\setcounter{secnumdepth}{0} | ||
3128 | |||
3129 | \\lstset{frame=tb, | ||
3130 | language=C, | ||
3131 | aboveskip=3mm, | ||
3132 | belowskip=3mm, | ||
3133 | showstringspaces=false, | ||
3134 | columns=flexible, | ||
3135 | basicstyle={\\small\\ttfamily}, | ||
3136 | numbers=none, | ||
3137 | numberstyle=\\tiny\\color{gray}, | ||
3138 | keywordstyle=\\color{blue}, | ||
3139 | commentstyle=\\color{dkgreen}, | ||
3140 | stringstyle=\\color{mauve}, | ||
3141 | breaklines=true, | ||
3142 | breakatwhitespace=true, | ||
3143 | tabsize=3 | ||
3144 | } | ||
3145 | |||
3146 | \\begin{document} | ||
3147 | \\frontmatter | ||
3148 | |||
3149 | \\title{$projectfullname $majorver.$minorver.$microver Reference Manual} | ||
3150 | \\author{The $projectshortname Developers} | ||
3151 | \\maketitle | ||
3152 | |||
3153 | \\mainmatter | ||
3154 | |||
3155 | __EOF__ | ||
3156 | ; | ||
3157 | |||
3158 | # !!! FIXME: Maybe put this in the book intro? print TEXFH $introtxt; | ||
3159 | |||
3160 | # Sort symbols by symbol type, then alphabetically. | ||
3161 | my @headersymskeys = sort { | ||
3162 | my $symtypea = $headersymstype{$a}; | ||
3163 | my $symtypeb = $headersymstype{$b}; | ||
3164 | $symtypea = 3 if ($symtypea > 3); | ||
3165 | $symtypeb = 3 if ($symtypeb > 3); | ||
3166 | my $rc = $symtypea <=> $symtypeb; | ||
3167 | if ($rc == 0) { | ||
3168 | $rc = lc($a) cmp lc($b); | ||
3169 | } | ||
3170 | return $rc; | ||
3171 | } keys %headersyms; | ||
3172 | |||
3173 | my $current_symtype = 0; | ||
3174 | my $current_chapter = ''; | ||
3175 | |||
3176 | foreach (@headersymskeys) { | ||
3177 | my $sym = $_; | ||
3178 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
3179 | next if $sym =~ /\A\[category documentation\]/; # not real symbols. | ||
3180 | my $symtype = $headersymstype{$sym}; | ||
3181 | my $wikitype = $wikitypes{$sym}; | ||
3182 | my $sectionsref = $wikisyms{$sym}; | ||
3183 | my $remarks = $sectionsref->{'Remarks'}; | ||
3184 | my $params = $sectionsref->{'Function Parameters'}; | ||
3185 | my $returns = $sectionsref->{'Return Value'}; | ||
3186 | my $version = $sectionsref->{'Version'}; | ||
3187 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
3188 | my $related = $sectionsref->{'See Also'}; | ||
3189 | my $examples = $sectionsref->{'Code Examples'}; | ||
3190 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
3191 | my $headerfile = $manpageheaderfiletext; | ||
3192 | $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
3193 | $headerfile .= "\n"; | ||
3194 | |||
3195 | my $brief = $sectionsref->{'[Brief]'}; | ||
3196 | my $decl = $headerdecls{$sym}; | ||
3197 | my $str = ''; | ||
3198 | |||
3199 | if ($current_symtype != $symtype) { | ||
3200 | my $newchapter = ''; | ||
3201 | if ($symtype == 1) { | ||
3202 | $newchapter = 'Functions'; | ||
3203 | } elsif ($symtype == 2) { | ||
3204 | $newchapter = 'Macros'; | ||
3205 | } else { | ||
3206 | $newchapter = 'Datatypes'; | ||
3207 | } | ||
3208 | |||
3209 | if ($current_chapter ne $newchapter) { | ||
3210 | $str .= "\n\n\\chapter{$projectshortname $newchapter}\n\n\\clearpage\n\n"; | ||
3211 | $current_chapter = $newchapter; | ||
3212 | } | ||
3213 | $current_symtype = $symtype; | ||
3214 | } | ||
3215 | |||
3216 | $brief = "$brief"; | ||
3217 | $brief =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
3218 | $brief =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
3219 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
3220 | my @briefsplit = split /\n/, $brief; | ||
3221 | $brief = shift @briefsplit; | ||
3222 | $brief = dewikify($wikitype, $brief); | ||
3223 | |||
3224 | if (defined $remarks) { | ||
3225 | $remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks); | ||
3226 | } | ||
3227 | |||
3228 | my $escapedsym = escLaTeX($sym); | ||
3229 | $str .= "\\hypertarget{$sym}{%\n\\section{$escapedsym}\\label{$sym}}\n\n"; | ||
3230 | $str .= $brief if (defined $brief); | ||
3231 | $str .= "\n\n"; | ||
3232 | |||
3233 | if (defined $deprecated) { | ||
3234 | $str .= "\\subsection{Deprecated}\n\n"; | ||
3235 | $str .= dewikify($wikitype, $deprecated) . "\n"; | ||
3236 | } | ||
3237 | |||
3238 | if (defined $headerfile) { | ||
3239 | $str .= "\\subsection{Header File}\n\n"; | ||
3240 | $str .= dewikify($wikitype, $headerfile) . "\n"; | ||
3241 | } | ||
3242 | |||
3243 | $str .= "\\subsection{Syntax}\n\n"; | ||
3244 | $str .= "\\begin{lstlisting}\n$decl\n\\end{lstlisting}\n"; | ||
3245 | |||
3246 | if (defined $params) { | ||
3247 | if (($symtype == 1) || ($symtype == 5)) { | ||
3248 | $str .= "\\subsection{Function Parameters}\n\n"; | ||
3249 | } elsif ($symtype == 2) { # macro | ||
3250 | $str .= "\\subsection{Macro Parameters}\n\n"; | ||
3251 | } elsif ($symtype == 3) { # struct/union | ||
3252 | $str .= "\\subsection{Fields}\n\n"; | ||
3253 | } elsif ($symtype == 4) { # enum | ||
3254 | $str .= "\\subsection{Values}\n\n"; | ||
3255 | } else { | ||
3256 | die("Unexpected symtype $symtype"); | ||
3257 | } | ||
3258 | |||
3259 | $str .= "\\begin{center}\n"; | ||
3260 | $str .= " \\begin{tabular}{ | l | p{0.75\\textwidth} |}\n"; | ||
3261 | $str .= " \\hline\n"; | ||
3262 | |||
3263 | # !!! FIXME: this table parsing has gotten complicated and is pasted three times in this file; move it to a subroutine! | ||
3264 | my @lines = split /\n/, $params; | ||
3265 | if ($wikitype eq 'mediawiki') { | ||
3266 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
3267 | while (scalar(@lines) >= 3) { | ||
3268 | my $name = shift @lines; | ||
3269 | my $desc = shift @lines; | ||
3270 | my $terminator = shift @lines; # the '|-' or '|}' line. | ||
3271 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
3272 | $name =~ s/\A\|\s*//; | ||
3273 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
3274 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
3275 | $name = escLaTeX($name); | ||
3276 | $desc =~ s/\A\|\s*//; | ||
3277 | $desc = dewikify($wikitype, $desc); | ||
3278 | #print STDERR "FN: $sym NAME: $name DESC: $desc TERM: $terminator\n"; | ||
3279 | $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; | ||
3280 | } | ||
3281 | } elsif ($wikitype eq 'md') { | ||
3282 | my $l; | ||
3283 | $l = shift @lines; | ||
3284 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
3285 | $l = shift @lines; | ||
3286 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
3287 | while (scalar(@lines) >= 1) { | ||
3288 | $l = shift @lines; | ||
3289 | my $name; | ||
3290 | my $desc; | ||
3291 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
3292 | # c datatype is $1, but we don't care about it here. | ||
3293 | $name = $2; | ||
3294 | $desc = $3; | ||
3295 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
3296 | $name = $1; | ||
3297 | $desc = $2; | ||
3298 | } else { | ||
3299 | last; # we seem to have run out of table. | ||
3300 | } | ||
3301 | |||
3302 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
3303 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
3304 | $name = escLaTeX($name); | ||
3305 | $desc = dewikify($wikitype, $desc); | ||
3306 | $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; | ||
3307 | } | ||
3308 | } else { | ||
3309 | die("write me"); | ||
3310 | } | ||
3311 | |||
3312 | $str .= " \\end{tabular}\n"; | ||
3313 | $str .= "\\end{center}\n"; | ||
3314 | } | ||
3315 | |||
3316 | if (defined $returns) { | ||
3317 | $returns = dewikify($wikitype, $returns); | ||
3318 | $returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. | ||
3319 | $str .= "\\subsection{Return Value}\n\n"; | ||
3320 | $str .= "$returns\n"; | ||
3321 | } | ||
3322 | |||
3323 | if (defined $remarks) { | ||
3324 | $str .= "\\subsection{Remarks}\n\n"; | ||
3325 | $str .= $remarks . "\n"; | ||
3326 | } | ||
3327 | |||
3328 | if (defined $examples) { | ||
3329 | $str .= "\\subsection{Code Examples}\n\n"; | ||
3330 | $dewikify_manpage_code_indent = 0; | ||
3331 | $str .= dewikify($wikitype, $examples) . "\n"; | ||
3332 | $dewikify_manpage_code_indent = 1; | ||
3333 | } | ||
3334 | |||
3335 | if (defined $threadsafety) { | ||
3336 | $str .= "\\subsection{Thread Safety}\n\n"; | ||
3337 | $str .= dewikify($wikitype, $threadsafety) . "\n"; | ||
3338 | } | ||
3339 | |||
3340 | if (defined $version) { | ||
3341 | $str .= "\\subsection{Version}\n\n"; | ||
3342 | $str .= dewikify($wikitype, $version) . "\n"; | ||
3343 | } | ||
3344 | |||
3345 | if (defined $related) { | ||
3346 | $str .= "\\subsection{See Also}\n\n"; | ||
3347 | $str .= "\\begin{itemize}\n"; | ||
3348 | # !!! FIXME: lots of code duplication in all of these. | ||
3349 | my $v = dewikify($wikitype, $related); | ||
3350 | my @desclines = split /\n/, $v; | ||
3351 | my $nextstr = ''; | ||
3352 | foreach (@desclines) { | ||
3353 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
3354 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
3355 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
3356 | s/\A\*\s*\Z//; | ||
3357 | s/\A\s*\\item\s*//; | ||
3358 | s/\A\/*//; | ||
3359 | s/\A\s*[\:\*\-]\s*//; | ||
3360 | s/\A\s+//; | ||
3361 | s/\s+\Z//; | ||
3362 | next if $_ eq ''; | ||
3363 | next if $_ eq '\begin{itemize}'; | ||
3364 | next if $_ eq '\end{itemize}'; | ||
3365 | $str .= " \\item $_\n"; | ||
3366 | } | ||
3367 | $str .= "\\end{itemize}\n"; | ||
3368 | $str .= "\n"; | ||
3369 | } | ||
3370 | |||
3371 | # !!! FIXME: Maybe put copyright in the book intro? | ||
3372 | if (0) { | ||
3373 | $str .= ".SH COPYRIGHT\n"; | ||
3374 | $str .= "This manpage is licensed under\n"; | ||
3375 | $str .= ".UR https://creativecommons.org/licenses/by/4.0/\n"; | ||
3376 | $str .= "Creative Commons Attribution 4.0 International (CC BY 4.0)\n"; | ||
3377 | $str .= ".UE\n"; | ||
3378 | $str .= ".PP\n"; | ||
3379 | $str .= "This manpage was generated from\n"; | ||
3380 | $str .= ".UR $wikiurl/$sym\n"; | ||
3381 | $str .= "${projectshortname}'s wiki\n"; | ||
3382 | $str .= ".UE\n"; | ||
3383 | $str .= "using SDL/build-scripts/wikiheaders.pl"; | ||
3384 | $str .= " revision $gitrev" if $gitrev ne ''; | ||
3385 | $str .= ".\n"; | ||
3386 | $str .= "Please report issues in this manpage at\n"; | ||
3387 | $str .= ".UR $bugreporturl\n"; | ||
3388 | $str .= "our bugtracker!\n"; | ||
3389 | $str .= ".UE\n"; | ||
3390 | } | ||
3391 | |||
3392 | $str .= "\\clearpage\n\n"; | ||
3393 | |||
3394 | print TEXFH $str; | ||
3395 | } | ||
3396 | |||
3397 | print TEXFH "\\end{document}\n\n"; | ||
3398 | close(TEXFH); | ||
3399 | rename($latex_tmpfname, $latex_fname) or die("Can't rename '$latex_tmpfname' to '$latex_fname': $!\n"); | ||
3400 | |||
3401 | } elsif ($copy_direction == -3) { # --report-coverage-gaps | ||
3402 | foreach (@coverage_gap) { | ||
3403 | print("$_\n"); | ||
3404 | } | ||
3405 | } | ||
3406 | |||
3407 | # end of wikiheaders.pl ... | ||
3408 | |||