diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/build-scripts | |
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/build-scripts')
50 files changed, 16059 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/build-scripts/SDL_migration.cocci b/contrib/SDL-3.2.8/build-scripts/SDL_migration.cocci new file mode 100644 index 0000000..38655af --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/add-source-to-projects.pl b/contrib/SDL-3.2.8/build-scripts/add-source-to-projects.pl new file mode 100755 index 0000000..5ba0a69 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/androidbuildlibs.sh b/contrib/SDL-3.2.8/build-scripts/androidbuildlibs.sh new file mode 100755 index 0000000..a903f36 --- /dev/null +++ b/contrib/SDL-3.2.8/build-scripts/androidbuildlibs.sh | |||
| @@ -0,0 +1,78 @@ | |||
| 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 | |||
| 34 | # Allow an external caller to specify locations and platform. | ||
| 35 | while [ $# -gt 0 ]; do | ||
| 36 | arg=$1 | ||
| 37 | if [ "${arg:0:8}" == "NDK_OUT=" ]; then | ||
| 38 | obj=${arg#NDK_OUT=} | ||
| 39 | elif [ "${arg:0:13}" == "NDK_LIBS_OUT=" ]; then | ||
| 40 | lib=${arg#NDK_LIBS_OUT=} | ||
| 41 | elif [ "${arg:0:13}" == "APP_PLATFORM=" ]; then | ||
| 42 | platform=${arg#APP_PLATFORM=} | ||
| 43 | elif [ "${arg:0:8}" == "APP_ABI=" ]; then | ||
| 44 | abi=${arg#APP_ABI=} | ||
| 45 | else | ||
| 46 | ndk_args="$ndk_args $arg" | ||
| 47 | fi | ||
| 48 | shift | ||
| 49 | done | ||
| 50 | |||
| 51 | if [ -z $obj ]; then | ||
| 52 | obj=$buildandroid/obj | ||
| 53 | fi | ||
| 54 | if [ -z $lib ]; then | ||
| 55 | lib=$buildandroid/lib | ||
| 56 | fi | ||
| 57 | |||
| 58 | for dir in $build $buildandroid $obj $lib; do | ||
| 59 | if test -d $dir; then | ||
| 60 | : | ||
| 61 | else | ||
| 62 | mkdir $dir || exit 1 | ||
| 63 | fi | ||
| 64 | done | ||
| 65 | |||
| 66 | |||
| 67 | # APP_* variables set in the environment here will not be seen by the | ||
| 68 | # ndk-build makefile segments that use them, e.g., default-application.mk. | ||
| 69 | # For consistency, pass all values on the command line. | ||
| 70 | ndk-build \ | ||
| 71 | NDK_PROJECT_PATH=null \ | ||
| 72 | NDK_OUT=$obj \ | ||
| 73 | NDK_LIBS_OUT=$lib \ | ||
| 74 | APP_BUILD_SCRIPT=Android.mk \ | ||
| 75 | APP_ABI="$abi" \ | ||
| 76 | APP_PLATFORM="$platform" \ | ||
| 77 | APP_MODULES="SDL3" \ | ||
| 78 | $ndk_args | ||
diff --git a/contrib/SDL-3.2.8/build-scripts/build-release.py b/contrib/SDL-3.2.8/build-scripts/build-release.py new file mode 100755 index 0000000..f3faa06 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/build-web-examples.pl b/contrib/SDL-3.2.8/build-scripts/build-web-examples.pl new file mode 100755 index 0000000..c255ea3 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/casefolding.txt b/contrib/SDL-3.2.8/build-scripts/casefolding.txt new file mode 100644 index 0000000..69c5c64 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/check_android_jni.py b/contrib/SDL-3.2.8/build-scripts/check_android_jni.py new file mode 100755 index 0000000..9e519fb --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/check_stdlib_usage.py b/contrib/SDL-3.2.8/build-scripts/check_stdlib_usage.py new file mode 100755 index 0000000..0994130 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/clang-format-src.sh b/contrib/SDL-3.2.8/build-scripts/clang-format-src.sh new file mode 100755 index 0000000..bc0defc --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-mingw64-i686.cmake b/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-mingw64-i686.cmake new file mode 100644 index 0000000..8be7b3a --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-mingw64-x86_64.cmake b/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-mingw64-x86_64.cmake new file mode 100644 index 0000000..8bf4366 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-qnx-aarch64le.cmake b/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-qnx-aarch64le.cmake new file mode 100644 index 0000000..26f5da4 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-qnx-x86_64.cmake b/contrib/SDL-3.2.8/build-scripts/cmake-toolchain-qnx-x86_64.cmake new file mode 100644 index 0000000..29f795a --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/codechecker-buildbot.sh b/contrib/SDL-3.2.8/build-scripts/codechecker-buildbot.sh new file mode 100755 index 0000000..76b7853 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/create-android-project.py b/contrib/SDL-3.2.8/build-scripts/create-android-project.py new file mode 100755 index 0000000..0b8994f --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/create-release.py b/contrib/SDL-3.2.8/build-scripts/create-release.py new file mode 100755 index 0000000..14916fa --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/fnsince.pl b/contrib/SDL-3.2.8/build-scripts/fnsince.pl new file mode 100755 index 0000000..9d987fc --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/gen_audio_channel_conversion.c b/contrib/SDL-3.2.8/build-scripts/gen_audio_channel_conversion.c new file mode 100644 index 0000000..85a856e --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/git-pre-push-hook.pl b/contrib/SDL-3.2.8/build-scripts/git-pre-push-hook.pl new file mode 100755 index 0000000..63596b6 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/makecasefoldhashtable.pl b/contrib/SDL-3.2.8/build-scripts/makecasefoldhashtable.pl new file mode 100755 index 0000000..efe3534 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/mkinstalldirs b/contrib/SDL-3.2.8/build-scripts/mkinstalldirs new file mode 100755 index 0000000..c364f3d --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/android/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/android/INSTALL.md.in new file mode 100644 index 0000000..80321c2 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/__main__.py.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/__main__.py.in new file mode 100755 index 0000000..344cf71 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/cmake/SDL3ConfigVersion.cmake.in new file mode 100644 index 0000000..3268da7 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/description.json.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/android/aar/description.json.in new file mode 100644 index 0000000..e75ef38 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/mingw/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/mingw/INSTALL.md.in new file mode 100644 index 0000000..f1a6a78 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/mingw/Makefile b/contrib/SDL-3.2.8/build-scripts/pkg-support/mingw/Makefile new file mode 100644 index 0000000..9b6cd55 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/Directory.Build.props b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/Directory.Build.props new file mode 100644 index 0000000..24033f4 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/INSTALL.md.in new file mode 100644 index 0000000..671f524 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/arm64/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/arm64/INSTALL.md.in new file mode 100644 index 0000000..c185171 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/cmake/SDL3Config.cmake.in new file mode 100644 index 0000000..6387376 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/cmake/SDL3ConfigVersion.cmake.in new file mode 100644 index 0000000..82b6af0 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/x64/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/x64/INSTALL.md.in new file mode 100644 index 0000000..74cd678 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/x86/INSTALL.md.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/msvc/x86/INSTALL.md.in new file mode 100644 index 0000000..041c116 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/source/SDL_revision.h.cmake.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/source/SDL_revision.h.cmake.in new file mode 100644 index 0000000..99e9f80 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/pkg-support/source/SDL_revision.h.in b/contrib/SDL-3.2.8/build-scripts/pkg-support/source/SDL_revision.h.in new file mode 100644 index 0000000..7dd6bc1 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/release-info.json b/contrib/SDL-3.2.8/build-scripts/release-info.json new file mode 100644 index 0000000..8ba213a --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/rename_api.py b/contrib/SDL-3.2.8/build-scripts/rename_api.py new file mode 100755 index 0000000..605ffa0 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/rename_headers.py b/contrib/SDL-3.2.8/build-scripts/rename_headers.py new file mode 100755 index 0000000..b61e477 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/rename_macros.py b/contrib/SDL-3.2.8/build-scripts/rename_macros.py new file mode 100755 index 0000000..978120c --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/rename_symbols.py b/contrib/SDL-3.2.8/build-scripts/rename_symbols.py new file mode 100755 index 0000000..33a92dd --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/rename_types.py b/contrib/SDL-3.2.8/build-scripts/rename_types.py new file mode 100755 index 0000000..137b409 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/setup-gdk-desktop.py b/contrib/SDL-3.2.8/build-scripts/setup-gdk-desktop.py new file mode 100755 index 0000000..d2309a0 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/showrev.sh b/contrib/SDL-3.2.8/build-scripts/showrev.sh new file mode 100755 index 0000000..764d3a4 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/strip_fPIC.sh b/contrib/SDL-3.2.8/build-scripts/strip_fPIC.sh new file mode 100755 index 0000000..8719b89 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/test-versioning.sh b/contrib/SDL-3.2.8/build-scripts/test-versioning.sh new file mode 100755 index 0000000..55e29a3 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/update-copyright.sh b/contrib/SDL-3.2.8/build-scripts/update-copyright.sh new file mode 100755 index 0000000..9bb46ea --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/update-version.sh b/contrib/SDL-3.2.8/build-scripts/update-version.sh new file mode 100755 index 0000000..86ae816 --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/updaterev.sh b/contrib/SDL-3.2.8/build-scripts/updaterev.sh new file mode 100755 index 0000000..508c6dd --- /dev/null +++ b/contrib/SDL-3.2.8/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/contrib/SDL-3.2.8/build-scripts/wikiheaders.pl b/contrib/SDL-3.2.8/build-scripts/wikiheaders.pl new file mode 100755 index 0000000..9859149 --- /dev/null +++ b/contrib/SDL-3.2.8/build-scripts/wikiheaders.pl | |||
| @@ -0,0 +1,3360 @@ | |||
| 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 | $str =~ s/\./\\[char46]/gms; # make sure these can't become control codes. | ||
| 428 | if ($wikitype eq 'mediawiki') { | ||
| 429 | # Dump obvious wikilinks. | ||
| 430 | if (defined $apiprefixregex) { | ||
| 431 | $str =~ s/\s*\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]\s*/\n.BR $1\n/gms; | ||
| 432 | } | ||
| 433 | |||
| 434 | # links | ||
| 435 | $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\n.URL "$1" "$2"\n/g; | ||
| 436 | |||
| 437 | # <code></code> is also popular. :/ | ||
| 438 | $str =~ s/\s*\<code>(.*?)<\/code>\s*/\n.BR $1\n/gms; | ||
| 439 | |||
| 440 | # bold+italic (this looks bad, just make it bold). | ||
| 441 | $str =~ s/\s*'''''(.*?)'''''\s*/\n.B $1\n/gms; | ||
| 442 | |||
| 443 | # bold | ||
| 444 | $str =~ s/\s*'''(.*?)'''\s*/\n.B $1\n/gms; | ||
| 445 | |||
| 446 | # italic | ||
| 447 | $str =~ s/\s*''(.*?)''\s*/\n.I $1\n/gms; | ||
| 448 | |||
| 449 | # bullets | ||
| 450 | $str =~ s/^\* /\n\\\(bu /gm; | ||
| 451 | } elsif ($wikitype eq 'md') { | ||
| 452 | # Dump obvious wikilinks. | ||
| 453 | if (defined $apiprefixregex) { | ||
| 454 | $str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/\n.BR $1\n/gms; | ||
| 455 | } | ||
| 456 | |||
| 457 | # links | ||
| 458 | $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g; | ||
| 459 | |||
| 460 | # <code></code> is also popular. :/ | ||
| 461 | $str =~ s/\s*\`(.*?)\`\s*/\n.BR $1\n/gms; | ||
| 462 | |||
| 463 | # bold+italic (this looks bad, just make it bold). | ||
| 464 | $str =~ s/\s*\*\*\*(.*?)\*\*\*\s*/\n.B $1\n/gms; | ||
| 465 | |||
| 466 | # bold | ||
| 467 | $str =~ s/\s*\*\*(.*?)\*\*\s*/\n.B $1\n/gms; | ||
| 468 | |||
| 469 | # italic | ||
| 470 | $str =~ s/\s*\*(.*?)\*\s*/\n.I $1\n/gms; | ||
| 471 | |||
| 472 | # bullets | ||
| 473 | $str =~ s/^\- /\n\\\(bu /gm; | ||
| 474 | } | ||
| 475 | |||
| 476 | if (defined $code) { | ||
| 477 | $code =~ s/\A\n+//gms; | ||
| 478 | $code =~ s/\n+\Z//gms; | ||
| 479 | if ($dewikify_manpage_code_indent) { | ||
| 480 | $str .= "\n.IP\n" | ||
| 481 | } else { | ||
| 482 | $str .= "\n.PP\n" | ||
| 483 | } | ||
| 484 | $str .= ".EX\n$code\n.EE\n.PP\n"; | ||
| 485 | } | ||
| 486 | } elsif ($dewikify_mode eq 'LaTeX') { | ||
| 487 | if ($wikitype eq 'mediawiki') { | ||
| 488 | # Dump obvious wikilinks. | ||
| 489 | if (defined $apiprefixregex) { | ||
| 490 | $str =~ s/\s*\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]/$1/gms; | ||
| 491 | } | ||
| 492 | |||
| 493 | # links | ||
| 494 | $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\\href{$1}{$2}/g; | ||
| 495 | |||
| 496 | # <code></code> is also popular. :/ | ||
| 497 | $str =~ s/\s*\<code>(.*?)<\/code>/ \\texttt{$1}/gms; | ||
| 498 | |||
| 499 | # bold+italic | ||
| 500 | $str =~ s/\s*'''''(.*?)'''''/ \\textbf{\\textit{$1}}/gms; | ||
| 501 | |||
| 502 | # bold | ||
| 503 | $str =~ s/\s*'''(.*?)'''/ \\textbf{$1}/gms; | ||
| 504 | |||
| 505 | # italic | ||
| 506 | $str =~ s/\s*''(.*?)''/ \\textit{$1}/gms; | ||
| 507 | |||
| 508 | # bullets | ||
| 509 | $str =~ s/^\*\s+/ \\item /gm; | ||
| 510 | } elsif ($wikitype eq 'md') { | ||
| 511 | # Dump obvious wikilinks. | ||
| 512 | if (defined $apiprefixregex) { | ||
| 513 | $str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/$1/gms; | ||
| 514 | } | ||
| 515 | |||
| 516 | # links | ||
| 517 | $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\\href{$2}{$1}/g; | ||
| 518 | |||
| 519 | # <code></code> is also popular. :/ | ||
| 520 | $str =~ s/\s*\`(.*?)\`/ \\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 | } | ||
| 534 | |||
| 535 | # Wrap bullet lists in itemize blocks... | ||
| 536 | $str =~ s/^(\s*\\item .*?)(\n\n|\Z)/\n\\begin{itemize}\n$1$2\n\\end{itemize}\n\n/gms; | ||
| 537 | |||
| 538 | $str = escLaTeX($str); | ||
| 539 | |||
| 540 | if (defined $code) { | ||
| 541 | $code =~ s/\A\n+//gms; | ||
| 542 | $code =~ s/\n+\Z//gms; | ||
| 543 | |||
| 544 | if (($codelang eq '') || ($codelang eq 'output')) { | ||
| 545 | $str .= "\\begin{verbatim}\n$code\n\\end{verbatim}\n"; | ||
| 546 | } else { | ||
| 547 | if ($codelang eq 'c') { | ||
| 548 | $codelang = 'C'; | ||
| 549 | } elsif ($codelang eq 'c++') { | ||
| 550 | $codelang = 'C++'; | ||
| 551 | } else { | ||
| 552 | die("Unexpected codelang '$codelang'"); | ||
| 553 | } | ||
| 554 | $str .= "\n\\lstset{language=$codelang}\n"; | ||
| 555 | $str .= "\\begin{lstlisting}\n$code\n\\end{lstlisting}\n"; | ||
| 556 | } | ||
| 557 | } | ||
| 558 | } else { | ||
| 559 | die("Unexpected dewikify_mode"); | ||
| 560 | } | ||
| 561 | |||
| 562 | #print("\n\nDEWIKIFY CHUNK DONE:\n\n$str\n\n\n"); | ||
| 563 | |||
| 564 | return $str; | ||
| 565 | } | ||
| 566 | |||
| 567 | sub dewikify { | ||
| 568 | my $wikitype = shift; | ||
| 569 | my $str = shift; | ||
| 570 | return '' if not defined $str; | ||
| 571 | |||
| 572 | #print("DEWIKIFY WHOLE:\n\n$str\n\n\n"); | ||
| 573 | |||
| 574 | $str =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
| 575 | $str =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
| 576 | |||
| 577 | my $retval = ''; | ||
| 578 | if ($wikitype eq 'mediawiki') { | ||
| 579 | while ($str =~ s/\A(.*?)<syntaxhighlight lang='?(.*?)'?>(.*?)<\/syntaxhighlight\>//ms) { | ||
| 580 | $retval .= dewikify_chunk($wikitype, $1, $2, $3); | ||
| 581 | } | ||
| 582 | } elsif ($wikitype eq 'md') { | ||
| 583 | while ($str =~ s/\A(.*?)\n```(.*?)\n(.*?)\n```\n//ms) { | ||
| 584 | $retval .= dewikify_chunk($wikitype, $1, $2, $3); | ||
| 585 | } | ||
| 586 | } | ||
| 587 | $retval .= dewikify_chunk($wikitype, $str, undef, undef); | ||
| 588 | |||
| 589 | #print("DEWIKIFY WHOLE DONE:\n\n$retval\n\n\n"); | ||
| 590 | |||
| 591 | return $retval; | ||
| 592 | } | ||
| 593 | |||
| 594 | sub filecopy { | ||
| 595 | my $src = shift; | ||
| 596 | my $dst = shift; | ||
| 597 | my $endline = shift; | ||
| 598 | $endline = "\n" if not defined $endline; | ||
| 599 | |||
| 600 | open(COPYIN, '<', $src) or die("Failed to open '$src' for reading: $!\n"); | ||
| 601 | open(COPYOUT, '>', $dst) or die("Failed to open '$dst' for writing: $!\n"); | ||
| 602 | while (<COPYIN>) { | ||
| 603 | chomp; | ||
| 604 | s/[ \t\r\n]*\Z//; | ||
| 605 | print COPYOUT "$_$endline"; | ||
| 606 | } | ||
| 607 | close(COPYOUT); | ||
| 608 | close(COPYIN); | ||
| 609 | } | ||
| 610 | |||
| 611 | sub usage { | ||
| 612 | 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"); | ||
| 613 | } | ||
| 614 | |||
| 615 | usage() if not defined $srcpath; | ||
| 616 | usage() if not defined $wikipath; | ||
| 617 | #usage() if $copy_direction == 0; | ||
| 618 | |||
| 619 | if (not defined $manpath) { | ||
| 620 | $manpath = "$srcpath/man"; | ||
| 621 | } | ||
| 622 | |||
| 623 | my @standard_wiki_sections = ( | ||
| 624 | 'Draft', | ||
| 625 | '[Brief]', | ||
| 626 | 'Deprecated', | ||
| 627 | 'Header File', | ||
| 628 | 'Syntax', | ||
| 629 | 'Function Parameters', | ||
| 630 | 'Macro Parameters', | ||
| 631 | 'Fields', | ||
| 632 | 'Values', | ||
| 633 | 'Return Value', | ||
| 634 | 'Remarks', | ||
| 635 | 'Thread Safety', | ||
| 636 | 'Version', | ||
| 637 | 'Code Examples', | ||
| 638 | 'See Also' | ||
| 639 | ); | ||
| 640 | |||
| 641 | # Sections that only ever exist in the wiki and shouldn't be deleted when | ||
| 642 | # not found in the headers. | ||
| 643 | my %only_wiki_sections = ( # The ones don't mean anything, I just need to check for key existence. | ||
| 644 | 'Draft', 1, | ||
| 645 | 'Code Examples', 1, | ||
| 646 | 'Header File', 1 | ||
| 647 | ); | ||
| 648 | |||
| 649 | |||
| 650 | my %headers = (); # $headers{"SDL_audio.h"} -> reference to an array of all lines of text in SDL_audio.h. | ||
| 651 | my %headersyms = (); # $headersyms{"SDL_OpenAudio"} -> string of header documentation for SDL_OpenAudio, with comment '*' bits stripped from the start. Newlines embedded! | ||
| 652 | my %headerdecls = (); | ||
| 653 | my %headersymslocation = (); # $headersymslocation{"SDL_OpenAudio"} -> name of header holding SDL_OpenAudio define ("SDL_audio.h" in this case). | ||
| 654 | my %headersymschunk = (); # $headersymschunk{"SDL_OpenAudio"} -> offset in array in %headers that should be replaced for this symbol. | ||
| 655 | my %headersymshasdoxygen = (); # $headersymshasdoxygen{"SDL_OpenAudio"} -> 1 if there was no existing doxygen for this function. | ||
| 656 | my %headersymstype = (); # $headersymstype{"SDL_OpenAudio"} -> 1 (function), 2 (macro), 3 (struct), 4 (enum), 5 (other typedef) | ||
| 657 | 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. | ||
| 658 | my %headercategorydocs = (); # $headercategorydocs{"Audio"} -> (fake) symbol for this category's documentation. Undefined if not documented. | ||
| 659 | 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. | ||
| 660 | my %headersymsrettype = (); # $headersymsrettype{"SDL_OpenAudio"} -> string of C datatype of return value. Undef'd if not a function. | ||
| 661 | my %wikitypes = (); # contains string of wiki page extension, like $wikitypes{"SDL_OpenAudio"} == 'mediawiki' | ||
| 662 | 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"}. | ||
| 663 | 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' | ||
| 664 | 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' | ||
| 665 | |||
| 666 | 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. | ||
| 667 | |||
| 668 | 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! | ||
| 669 | |||
| 670 | sub add_coverage_gap { | ||
| 671 | if ($copy_direction == -3) { # --report-coverage-gaps | ||
| 672 | my $text = shift; | ||
| 673 | my $dent = shift; | ||
| 674 | my $lineno = shift; | ||
| 675 | return if $text =~ /\A\s*\Z/; # skip blank lines | ||
| 676 | return if $text =~ /\A\s*\#\s*(if|el|endif|include)/; # skip preprocessor floof. | ||
| 677 | push @coverage_gap, "$dent:$lineno: $text"; | ||
| 678 | } | ||
| 679 | } | ||
| 680 | |||
| 681 | sub print_undocumented_section { | ||
| 682 | my $fh = shift; | ||
| 683 | my $typestr = shift; | ||
| 684 | my $typeval = shift; | ||
| 685 | |||
| 686 | print $fh "## $typestr defined in the headers, but not in the wiki\n\n"; | ||
| 687 | my $header_only_sym = 0; | ||
| 688 | foreach (sort keys %headersyms) { | ||
| 689 | my $sym = $_; | ||
| 690 | if ((not defined $wikisyms{$sym}) && ($headersymstype{$sym} == $typeval)) { | ||
| 691 | print $fh "- [$sym]($sym)\n"; | ||
| 692 | $header_only_sym = 1; | ||
| 693 | } | ||
| 694 | } | ||
| 695 | if (!$header_only_sym) { | ||
| 696 | print $fh "(none)\n"; | ||
| 697 | } | ||
| 698 | print $fh "\n"; | ||
| 699 | |||
| 700 | 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?) | ||
| 701 | print $fh "## $typestr defined in the wiki, but not in the headers\n\n"; | ||
| 702 | |||
| 703 | my $wiki_only_sym = 0; | ||
| 704 | foreach (sort keys %wikisyms) { | ||
| 705 | my $sym = $_; | ||
| 706 | if ((not defined $headersyms{$sym}) && ($headersymstype{$sym} == $typeval)) { | ||
| 707 | print $fh "- [$sym]($sym)\n"; | ||
| 708 | $wiki_only_sym = 1; | ||
| 709 | } | ||
| 710 | } | ||
| 711 | if (!$wiki_only_sym) { | ||
| 712 | print $fh "(none)\n"; | ||
| 713 | } | ||
| 714 | print $fh "\n"; | ||
| 715 | } | ||
| 716 | } | ||
| 717 | |||
| 718 | sub strip_fn_declaration_metadata { | ||
| 719 | my $decl = shift; | ||
| 720 | $decl =~ s/SDL_(PRINTF|SCANF)_FORMAT_STRING\s*//; # don't want this metadata as part of the documentation. | ||
| 721 | $decl =~ s/SDL_ALLOC_SIZE2?\(.*?\)\s*//; # don't want this metadata as part of the documentation. | ||
| 722 | $decl =~ s/SDL_MALLOC\s*//; # don't want this metadata as part of the documentation. | ||
| 723 | $decl =~ s/SDL_(IN|OUT|INOUT)_.*?CAP\s*\(.*?\)\s*//g; # don't want this metadata as part of the documentation. | ||
| 724 | $decl =~ s/\)(\s*SDL_[a-zA-Z_]+(\(.*?\)|))*;/);/; # don't want this metadata as part of the documentation. | ||
| 725 | return $decl; | ||
| 726 | } | ||
| 727 | |||
| 728 | sub sanitize_c_typename { | ||
| 729 | my $str = shift; | ||
| 730 | $str =~ s/\A\s+//; | ||
| 731 | $str =~ s/\s+\Z//; | ||
| 732 | $str =~ s/const\s*(\*+)/const $1/g; # one space between `const` and pointer stars: `char const* const *` becomes `char const * const *`. | ||
| 733 | $str =~ s/\*\s+\*/**/g; # drop spaces between pointers: `void * *` becomes `void **`. | ||
| 734 | $str =~ s/\s*(\*+)\Z/ $1/; # one space between pointer stars and what it points to: `void**` becomes `void **`. | ||
| 735 | return $str; | ||
| 736 | } | ||
| 737 | |||
| 738 | my %big_ascii = ( | ||
| 739 | '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}" ], | ||
| 740 | '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}" ], | ||
| 741 | '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}" ], | ||
| 742 | '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}" ], | ||
| 743 | '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}" ], | ||
| 744 | '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}" ], | ||
| 745 | '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}" ], | ||
| 746 | '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}" ], | ||
| 747 | '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}" ], | ||
| 748 | '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}" ], | ||
| 749 | '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}" ], | ||
| 750 | '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}" ], | ||
| 751 | '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}" ], | ||
| 752 | '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}" ], | ||
| 753 | '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}" ], | ||
| 754 | '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}" ], | ||
| 755 | '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}" ], | ||
| 756 | '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}" ], | ||
| 757 | '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}" ], | ||
| 758 | '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}" ], | ||
| 759 | '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}" ], | ||
| 760 | '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}" ], | ||
| 761 | '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}" ], | ||
| 762 | '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}" ], | ||
| 763 | '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}" ], | ||
| 764 | '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}" ], | ||
| 765 | ' ' => [ "\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}" ], | ||
| 766 | '.' => [ "\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}" ], | ||
| 767 | ',' => [ "\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}" ], | ||
| 768 | '/' => [ "\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}" ], | ||
| 769 | '!' => [ "\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}" ], | ||
| 770 | '_' => [ "\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}" ], | ||
| 771 | '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}" ], | ||
| 772 | '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}" ], | ||
| 773 | '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}" ], | ||
| 774 | '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}" ], | ||
| 775 | '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}" ], | ||
| 776 | '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}" ], | ||
| 777 | '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}" ], | ||
| 778 | '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}" ], | ||
| 779 | '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}" ], | ||
| 780 | '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}" ], | ||
| 781 | ); | ||
| 782 | |||
| 783 | sub print_big_ascii_string { | ||
| 784 | my $fh = shift; | ||
| 785 | my $str = shift; | ||
| 786 | my $comment = shift; | ||
| 787 | my $lowascii = shift; | ||
| 788 | $comment = '' if not defined $comment; | ||
| 789 | $lowascii = 0 if not defined $lowascii; | ||
| 790 | |||
| 791 | my @chars = split //, $str; | ||
| 792 | my $charcount = scalar(@chars); | ||
| 793 | |||
| 794 | binmode($fh, ":utf8"); | ||
| 795 | |||
| 796 | my $maxrows = $lowascii ? 5 : 6; | ||
| 797 | |||
| 798 | for(my $rownum = 0; $rownum < $maxrows; $rownum++){ | ||
| 799 | print $fh $comment; | ||
| 800 | my $charidx = 0; | ||
| 801 | foreach my $ch (@chars) { | ||
| 802 | my $rowsref = $big_ascii{uc($ch)}; | ||
| 803 | die("Don't have a big ascii entry for '$ch'!\n") if not defined $rowsref; | ||
| 804 | my $row = @$rowsref[$rownum]; | ||
| 805 | |||
| 806 | if ($lowascii) { | ||
| 807 | my @x = split //, $row; | ||
| 808 | foreach (@x) { | ||
| 809 | my $v = ($_ eq "\x{2588}") ? 'X' : ' '; | ||
| 810 | print $fh $v; | ||
| 811 | } | ||
| 812 | } else { | ||
| 813 | print $fh $row; | ||
| 814 | } | ||
| 815 | |||
| 816 | $charidx++; | ||
| 817 | |||
| 818 | if ($charidx < $charcount) { | ||
| 819 | print $fh " "; | ||
| 820 | } | ||
| 821 | } | ||
| 822 | print $fh "\n"; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 826 | sub generate_quickref { | ||
| 827 | my $briefsref = shift; | ||
| 828 | my $path = shift; | ||
| 829 | my $lowascii = shift; | ||
| 830 | |||
| 831 | # !!! FIXME: this gitrev and majorver/etc stuff is copy/pasted a few times now. | ||
| 832 | if (!$gitrev) { | ||
| 833 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
| 834 | chomp($gitrev); | ||
| 835 | } | ||
| 836 | |||
| 837 | # !!! FIXME | ||
| 838 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
| 839 | my $majorver = 0; | ||
| 840 | my $minorver = 0; | ||
| 841 | my $microver = 0; | ||
| 842 | while (<FH>) { | ||
| 843 | chomp; | ||
| 844 | if (/$versionmajorregex/) { | ||
| 845 | $majorver = int($1); | ||
| 846 | } elsif (/$versionminorregex/) { | ||
| 847 | $minorver = int($1); | ||
| 848 | } elsif (/$versionmicroregex/) { | ||
| 849 | $microver = int($1); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | close(FH); | ||
| 853 | my $fullversion = "$majorver.$minorver.$microver"; | ||
| 854 | |||
| 855 | my $tmppath = "$path.tmp"; | ||
| 856 | open(my $fh, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
| 857 | |||
| 858 | if (not @quickrefcategoryorder) { | ||
| 859 | @quickrefcategoryorder = sort keys %headercategorydocs; | ||
| 860 | } | ||
| 861 | |||
| 862 | #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); | ||
| 863 | #my $datestr = sprintf("%04d-%02d-%02d %02d:%02d:%02d GMT", $year+1900, $mon+1, $mday, $hour, $min, $sec); | ||
| 864 | |||
| 865 | print $fh "<!-- DO NOT EDIT THIS PAGE ON THE WIKI. IT WILL BE OVERWRITTEN BY WIKIHEADERS AND CHANGES WILL BE LOST! -->\n\n"; | ||
| 866 | |||
| 867 | # Just something to test big_ascii output. | ||
| 868 | #print_big_ascii_string($fh, "ABCDEFGHIJ", '', $lowascii); | ||
| 869 | #print_big_ascii_string($fh, "KLMNOPQRST", '', $lowascii); | ||
| 870 | #print_big_ascii_string($fh, "UVWXYZ0123", '', $lowascii); | ||
| 871 | #print_big_ascii_string($fh, "456789JT3A", '', $lowascii); | ||
| 872 | #print_big_ascii_string($fh, "hello, _a.b/c_!!", '', $lowascii); | ||
| 873 | |||
| 874 | # Dan Bechard's work was on an SDL2 cheatsheet: | ||
| 875 | # https://blog.theprogrammingjunkie.com/post/sdl2-cheatsheet/ | ||
| 876 | |||
| 877 | if ($lowascii) { | ||
| 878 | print $fh "# QuickReferenceNoUnicode\n\n"; | ||
| 879 | print $fh "If you want to paste this into a text editor that can handle\n"; | ||
| 880 | print $fh "fancy Unicode section headers, try using\n"; | ||
| 881 | print $fh "[QuickReference](QuickReference) instead.\n\n"; | ||
| 882 | } else { | ||
| 883 | print $fh "# QuickReference\n\n"; | ||
| 884 | print $fh "If you want to paste this into a text editor that can't handle\n"; | ||
| 885 | print $fh "the fancy Unicode section headers, try using\n"; | ||
| 886 | print $fh "[QuickReferenceNoUnicode](QuickReferenceNoUnicode) instead.\n\n"; | ||
| 887 | } | ||
| 888 | |||
| 889 | print $fh "```c\n"; | ||
| 890 | print $fh "// $quickreftitle\n" if defined $quickreftitle; | ||
| 891 | print $fh "//\n"; | ||
| 892 | print $fh "// $quickrefurl\n//\n" if defined $quickrefurl; | ||
| 893 | print $fh "// $quickrefdesc\n" if defined $quickrefdesc; | ||
| 894 | #print $fh "// When this document was written: $datestr\n"; | ||
| 895 | print $fh "// Based on $projectshortname version $fullversion\n"; | ||
| 896 | #print $fh "// git revision $gitrev\n"; | ||
| 897 | print $fh "//\n"; | ||
| 898 | print $fh "// This can be useful in an IDE with search and syntax highlighting.\n"; | ||
| 899 | print $fh "//\n"; | ||
| 900 | print $fh "// Original idea for this document came from Dan Bechard (thanks!)\n"; | ||
| 901 | print $fh "// ASCII art generated by: https://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow (with modified 'S' for readability)\n\n"; | ||
| 902 | |||
| 903 | foreach (@quickrefcategoryorder) { | ||
| 904 | my $cat = $_; | ||
| 905 | my $maxlen = 0; | ||
| 906 | my @csigs = (); | ||
| 907 | my $funcorderref = $quickreffuncorder{$cat}; | ||
| 908 | next if not defined $funcorderref; | ||
| 909 | |||
| 910 | foreach (@$funcorderref) { | ||
| 911 | my $sym = $_; | ||
| 912 | my $csig = ''; | ||
| 913 | |||
| 914 | if ($headersymstype{$sym} == 1) { # function | ||
| 915 | $csig = "${headersymsrettype{$sym}} $sym"; | ||
| 916 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
| 917 | if (not defined($fnsigparams)) { | ||
| 918 | $csig .= '(void);'; | ||
| 919 | } else { | ||
| 920 | my $sep = '('; | ||
| 921 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
| 922 | my $paramname = @$fnsigparams[$i]; | ||
| 923 | my $paramtype = @$fnsigparams[$i+1]; | ||
| 924 | my $spc = ($paramtype =~ /\*\Z/) ? '' : ' '; | ||
| 925 | $csig .= "$sep$paramtype$spc$paramname"; | ||
| 926 | $sep = ', '; | ||
| 927 | } | ||
| 928 | $csig .= ");"; | ||
| 929 | } | ||
| 930 | } elsif ($headersymstype{$sym} == 2) { # macro | ||
| 931 | next if defined $quickrefmacroregex && not $sym =~ /$quickrefmacroregex/; | ||
| 932 | |||
| 933 | $csig = (split /\n/, $headerdecls{$sym})[0]; # get the first line from a multiline string. | ||
| 934 | if (not $csig =~ s/\A(\#define [a-zA-Z0-9_]*\(.*?\))(\s+.*)?\Z/$1/) { | ||
| 935 | $csig =~ s/\A(\#define [a-zA-Z0-9_]*)(\s+.*)?\Z/$1/; | ||
| 936 | } | ||
| 937 | chomp($csig); | ||
| 938 | } | ||
| 939 | |||
| 940 | my $len = length($csig); | ||
| 941 | $maxlen = $len if $len > $maxlen; | ||
| 942 | |||
| 943 | push @csigs, $sym; | ||
| 944 | push @csigs, $csig; | ||
| 945 | } | ||
| 946 | |||
| 947 | $maxlen += 2; | ||
| 948 | |||
| 949 | next if (not @csigs); | ||
| 950 | |||
| 951 | print $fh "\n"; | ||
| 952 | print_big_ascii_string($fh, $cat, '// ', $lowascii); | ||
| 953 | print $fh "\n"; | ||
| 954 | |||
| 955 | while (@csigs) { | ||
| 956 | my $sym = shift @csigs; | ||
| 957 | my $csig = shift @csigs; | ||
| 958 | my $brief = $$briefsref{$sym}; | ||
| 959 | if (defined $brief) { | ||
| 960 | $brief = "$brief"; | ||
| 961 | chomp($brief); | ||
| 962 | my $thiswikitype = defined $wikitypes{$sym} ? $wikitypes{$sym} : 'md'; # default to MarkDown for new stuff. | ||
| 963 | $brief = dewikify($thiswikitype, $brief); | ||
| 964 | my $spaces = ' ' x ($maxlen - length($csig)); | ||
| 965 | $brief = "$spaces// $brief"; | ||
| 966 | } else { | ||
| 967 | $brief = ''; | ||
| 968 | } | ||
| 969 | print $fh "$csig$brief\n"; | ||
| 970 | } | ||
| 971 | } | ||
| 972 | |||
| 973 | print $fh "```\n\n"; | ||
| 974 | |||
| 975 | close($fh); | ||
| 976 | |||
| 977 | # # Don't overwrite the file if nothing has changed besides the timestamp | ||
| 978 | # # and git revision. | ||
| 979 | # my $matches = 1; | ||
| 980 | # if ( not -f $path ) { | ||
| 981 | # $matches = 0; # always write if the file hasn't been created yet. | ||
| 982 | # } else { | ||
| 983 | # open(my $fh_a, '<', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
| 984 | # open(my $fh_b, '<', $path) or die("Can't open '$path': $!\n"); | ||
| 985 | # while (1) { | ||
| 986 | # my $a = <$fh_a>; | ||
| 987 | # my $b = <$fh_b>; | ||
| 988 | # $matches = 0, last if ((not defined $a) != (not defined $b)); | ||
| 989 | # last if ((not defined $a) || (not defined $b)); | ||
| 990 | # if ($a ne $b) { | ||
| 991 | # next if ($a =~ /\A\/\/ When this document was written:/); | ||
| 992 | # next if ($a =~ /\A\/\/ git revision /); | ||
| 993 | # $matches = 0; | ||
| 994 | # last; | ||
| 995 | # } | ||
| 996 | # } | ||
| 997 | # | ||
| 998 | # close($fh_a); | ||
| 999 | # close($fh_b); | ||
| 1000 | # } | ||
| 1001 | # | ||
| 1002 | # if ($matches) { | ||
| 1003 | # unlink($tmppath); # it's the same file except maybe the date/gitrev. Don't overwrite it. | ||
| 1004 | # } else { | ||
| 1005 | # rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
| 1006 | # } | ||
| 1007 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | |||
| 1011 | my $incpath = "$srcpath"; | ||
| 1012 | $incpath .= "/$incsubdir" if $incsubdir ne ''; | ||
| 1013 | |||
| 1014 | my $wikireadmepath = "$wikipath/$wikireadmesubdir"; | ||
| 1015 | my $readmepath = undef; | ||
| 1016 | if (defined $readmesubdir) { | ||
| 1017 | $readmepath = "$srcpath/$readmesubdir"; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | opendir(DH, $incpath) or die("Can't opendir '$incpath': $!\n"); | ||
| 1021 | while (my $d = readdir(DH)) { | ||
| 1022 | my $dent = $d; | ||
| 1023 | next if not $dent =~ /$selectheaderregex/; # just selected headers. | ||
| 1024 | open(FH, '<', "$incpath/$dent") or die("Can't open '$incpath/$dent': $!\n"); | ||
| 1025 | |||
| 1026 | # You can optionally set a wiki category with Perl code in .wikiheaders-options that gets eval()'d per-header, | ||
| 1027 | # and also if you put `/* WIKI CATEGORY: blah */` on a line by itself, it'll change the category for any symbols | ||
| 1028 | # below it in the same file. If no category is set, one won't be added for the symbol (beyond the standard CategoryFunction, etc) | ||
| 1029 | my $current_wiki_category = undef; | ||
| 1030 | if (defined $headercategoryeval) { | ||
| 1031 | $_ = $dent; | ||
| 1032 | $current_wiki_category = eval($headercategoryeval); | ||
| 1033 | if (($current_wiki_category eq '') || ($current_wiki_category eq '-')) { | ||
| 1034 | $current_wiki_category = undef; | ||
| 1035 | } | ||
| 1036 | #print("CATEGORY FOR '$dent' IS " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | my @contents = (); | ||
| 1040 | my @function_order = (); | ||
| 1041 | my $ignoring_lines = 0; | ||
| 1042 | my $header_comment = -1; | ||
| 1043 | my $saw_category_doxygen = -1; | ||
| 1044 | my $lineno = 0; | ||
| 1045 | |||
| 1046 | while (<FH>) { | ||
| 1047 | chomp; | ||
| 1048 | $lineno++; | ||
| 1049 | my $symtype = 0; # nothing, yet. | ||
| 1050 | my $decl; | ||
| 1051 | my @templines; | ||
| 1052 | my $str; | ||
| 1053 | my $has_doxygen = 1; | ||
| 1054 | |||
| 1055 | # 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. | ||
| 1056 | # Functions and other things are a different story, though! | ||
| 1057 | |||
| 1058 | if ($header_comment == -1) { | ||
| 1059 | $header_comment = /\A\/\*\s*\Z/ ? 1 : 0; | ||
| 1060 | } elsif (($header_comment == 1) && (/\A\*\/\s*\Z/)) { | ||
| 1061 | $header_comment = 0; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | if ($ignoring_lines && /\A\s*\#\s*endif\s*\Z/) { | ||
| 1065 | $ignoring_lines = 0; | ||
| 1066 | push @contents, $_; | ||
| 1067 | next; | ||
| 1068 | } elsif ($ignoring_lines) { | ||
| 1069 | push @contents, $_; | ||
| 1070 | next; | ||
| 1071 | } elsif (/\A\s*\#\s*ifndef\s+SDL_WIKI_DOCUMENTATION_SECTION\s*\Z/) { | ||
| 1072 | $ignoring_lines = 1; | ||
| 1073 | push @contents, $_; | ||
| 1074 | next; | ||
| 1075 | } elsif (/\A\s*\/\*\s*WIKI CATEGORY:\s*(.*?)\s*\*\/\s*\Z/) { | ||
| 1076 | $current_wiki_category = (($1 eq '') || ($1 eq '-')) ? undef : $1; | ||
| 1077 | #print("CATEGORY FOR '$dent' CHANGED TO " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); | ||
| 1078 | push @contents, $_; | ||
| 1079 | next; | ||
| 1080 | } elsif (/\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { # a function declaration without a doxygen comment? | ||
| 1081 | $symtype = 1; # function declaration | ||
| 1082 | @templines = (); | ||
| 1083 | $decl = $_; | ||
| 1084 | $str = ''; | ||
| 1085 | $has_doxygen = 0; | ||
| 1086 | } elsif (/\A\s*SDL_FORCE_INLINE/) { # a (forced-inline) function declaration without a doxygen comment? | ||
| 1087 | $symtype = 1; # function declaration | ||
| 1088 | @templines = (); | ||
| 1089 | $decl = $_; | ||
| 1090 | $str = ''; | ||
| 1091 | $has_doxygen = 0; | ||
| 1092 | } elsif (not /\A\/\*\*\s*\Z/) { # not doxygen comment start? | ||
| 1093 | push @contents, $_; | ||
| 1094 | add_coverage_gap($_, $dent, $lineno) if ($header_comment == 0); | ||
| 1095 | next; | ||
| 1096 | } else { # Start of a doxygen comment, parse it out. | ||
| 1097 | my $is_category_doxygen = 0; | ||
| 1098 | |||
| 1099 | @templines = ( $_ ); | ||
| 1100 | while (<FH>) { | ||
| 1101 | chomp; | ||
| 1102 | $lineno++; | ||
| 1103 | push @templines, $_; | ||
| 1104 | last if /\A\s*\*\/\Z/; | ||
| 1105 | 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... | ||
| 1106 | $str .= "$_\n"; | ||
| 1107 | while (<FH>) { | ||
| 1108 | chomp; | ||
| 1109 | $lineno++; | ||
| 1110 | push @templines, $_; | ||
| 1111 | s/\A\s*\*\s?//; | ||
| 1112 | if (s/\A\s*\`\`\`/```/) { | ||
| 1113 | $str .= "$_\n"; | ||
| 1114 | last; | ||
| 1115 | } else { | ||
| 1116 | $str .= "$_\n"; | ||
| 1117 | } | ||
| 1118 | } | ||
| 1119 | } else { | ||
| 1120 | s/\A\s*\*\s*//; # Strip off the " * " at the start of the comment line. | ||
| 1121 | |||
| 1122 | # To add documentation to Category Pages, the rule is it has to | ||
| 1123 | # be the first Doxygen comment in the header, and it must start with `# CategoryX` | ||
| 1124 | # (otherwise we'll treat it as documentation for whatever's below it). `X` is | ||
| 1125 | # the category name, which doesn't _necessarily_ have to match | ||
| 1126 | # $current_wiki_category, but it probably should. | ||
| 1127 | # | ||
| 1128 | # For compatibility with Doxygen, if there's a `\file` here instead of | ||
| 1129 | # `# CategoryName`, we'll accept it and use the $current_wiki_category if set. | ||
| 1130 | if ($saw_category_doxygen == -1) { | ||
| 1131 | $saw_category_doxygen = defined($current_wiki_category) && /\A\\file\s+/; | ||
| 1132 | if ($saw_category_doxygen) { | ||
| 1133 | $_ = "# Category$current_wiki_category"; | ||
| 1134 | } else { | ||
| 1135 | $saw_category_doxygen = /\A\# Category/; | ||
| 1136 | } | ||
| 1137 | $is_category_doxygen = $saw_category_doxygen; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | $str .= "$_\n"; | ||
| 1141 | } | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if ($is_category_doxygen) { | ||
| 1145 | $str =~ s/\s*\Z//; | ||
| 1146 | $decl = ''; | ||
| 1147 | $symtype = -1; # not a symbol at all. | ||
| 1148 | } else { | ||
| 1149 | $decl = <FH>; | ||
| 1150 | $lineno++ if defined $decl; | ||
| 1151 | $decl = '' if not defined $decl; | ||
| 1152 | chomp($decl); | ||
| 1153 | if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { | ||
| 1154 | $symtype = 1; # function declaration | ||
| 1155 | } elsif ($decl =~ /\A\s*SDL_FORCE_INLINE/) { | ||
| 1156 | $symtype = 1; # (forced-inline) function declaration | ||
| 1157 | } elsif ($decl =~ /\A\s*\#\s*define\s+/) { | ||
| 1158 | $symtype = 2; # macro | ||
| 1159 | } elsif ($decl =~ /\A\s*(typedef\s+|)(struct|union)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { | ||
| 1160 | $symtype = 3; # struct or union | ||
| 1161 | } elsif ($decl =~ /\A\s*(typedef\s+|)enum\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { | ||
| 1162 | $symtype = 4; # enum | ||
| 1163 | } elsif ($decl =~ /\A\s*typedef\s+.*\Z/) { | ||
| 1164 | $symtype = 5; # other typedef | ||
| 1165 | } else { | ||
| 1166 | #print "Found doxygen but no function sig:\n$str\n\n"; | ||
| 1167 | foreach (@templines) { | ||
| 1168 | push @contents, $_; | ||
| 1169 | add_coverage_gap($_, $dent, $lineno); | ||
| 1170 | } | ||
| 1171 | push @contents, $decl; | ||
| 1172 | add_coverage_gap($decl, $dent, $lineno); | ||
| 1173 | next; | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | my @paraminfo = (); | ||
| 1179 | my $rettype = undef; | ||
| 1180 | my @decllines = ( $decl ); | ||
| 1181 | my $sym = ''; | ||
| 1182 | |||
| 1183 | if ($symtype == -1) { # category documentation with no symbol attached. | ||
| 1184 | @decllines = (); | ||
| 1185 | if ($str =~ /^#\s*Category(.*?)\s*$/m) { | ||
| 1186 | $sym = "[category documentation] $1"; # make a fake, unique symbol that's not valid C. | ||
| 1187 | } else { | ||
| 1188 | die("Unexpected category documentation line '$str' in '$incpath/$dent' ...?"); | ||
| 1189 | } | ||
| 1190 | $headercategorydocs{$current_wiki_category} = $sym; | ||
| 1191 | } elsif ($symtype == 1) { # a function | ||
| 1192 | my $is_forced_inline = ($decl =~ /\A\s*SDL_FORCE_INLINE/); | ||
| 1193 | |||
| 1194 | if ($is_forced_inline) { | ||
| 1195 | if (not $decl =~ /\)\s*(\{.*|)\s*\Z/) { | ||
| 1196 | while (<FH>) { | ||
| 1197 | chomp; | ||
| 1198 | $lineno++; | ||
| 1199 | push @decllines, $_; | ||
| 1200 | s/\A\s+//; | ||
| 1201 | s/\s+\Z//; | ||
| 1202 | $decl .= " $_"; | ||
| 1203 | last if /\)\s*(\{.*|)\s*\Z/; | ||
| 1204 | } | ||
| 1205 | } | ||
| 1206 | $decl =~ s/\s*\)\s*(\{.*|)\s*\Z/);/; | ||
| 1207 | } else { | ||
| 1208 | if (not $decl =~ /;/) { | ||
| 1209 | while (<FH>) { | ||
| 1210 | chomp; | ||
| 1211 | $lineno++; | ||
| 1212 | push @decllines, $_; | ||
| 1213 | s/\A\s+//; | ||
| 1214 | s/\s+\Z//; | ||
| 1215 | $decl .= " $_"; | ||
| 1216 | last if /;/; | ||
| 1217 | } | ||
| 1218 | } | ||
| 1219 | $decl =~ s/\s+\);\Z/);/; | ||
| 1220 | $decl =~ s/\s+;\Z/;/; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | $decl =~ s/\s+\Z//; | ||
| 1224 | |||
| 1225 | $decl = strip_fn_declaration_metadata($decl); | ||
| 1226 | |||
| 1227 | my $paramsstr = undef; | ||
| 1228 | |||
| 1229 | 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*\((.*?)\);/) { | ||
| 1230 | $sym = $8; | ||
| 1231 | $rettype = "$3$4$5$6"; | ||
| 1232 | $paramsstr = $9; | ||
| 1233 | } elsif ($is_forced_inline && $decl =~ /\A\s*SDL_FORCE_INLINE\s+(SDL_DEPRECATED\s+|)(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(.*?)\s*\((.*?)\);/) { | ||
| 1234 | $sym = $6; | ||
| 1235 | $rettype = "$2$3$4$5"; | ||
| 1236 | $paramsstr = $7; | ||
| 1237 | } else { | ||
| 1238 | #print "Found doxygen but no function sig:\n$str\n\n"; | ||
| 1239 | foreach (@templines) { | ||
| 1240 | push @contents, $_; | ||
| 1241 | } | ||
| 1242 | foreach (@decllines) { | ||
| 1243 | push @contents, $_; | ||
| 1244 | } | ||
| 1245 | next; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | $rettype = sanitize_c_typename($rettype); | ||
| 1249 | |||
| 1250 | if ($paramsstr =~ /\(/) { | ||
| 1251 | die("\n\n$0 FAILURE!\n" . | ||
| 1252 | "There's a '(' in the parameters for function '$sym' '$incpath/$dent'.\n" . | ||
| 1253 | "This usually means there's a parameter that's a function pointer type.\n" . | ||
| 1254 | "This causes problems for wikiheaders.pl and is less readable, too.\n" . | ||
| 1255 | "Please put that function pointer into a typedef,\n" . | ||
| 1256 | "and use the new type in this function's signature instead!\n\n"); | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | my @params = split(/,/, $paramsstr); | ||
| 1260 | my $dotdotdot = 0; | ||
| 1261 | foreach (@params) { | ||
| 1262 | my $p = $_; | ||
| 1263 | $p =~ s/\A\s+//; | ||
| 1264 | $p =~ s/\s+\Z//; | ||
| 1265 | if (($p eq 'void') || ($p eq '')) { | ||
| 1266 | die("Void parameter in a function with multiple params?! ('$sym' in '$incpath/$dent')") if (scalar(@params) != 1); | ||
| 1267 | } elsif ($p eq '...') { | ||
| 1268 | die("Mutiple '...' params?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); | ||
| 1269 | $dotdotdot = 1; | ||
| 1270 | push @paraminfo, '...'; | ||
| 1271 | push @paraminfo, '...'; | ||
| 1272 | } elsif ($p =~ /\A(.*)\s+([a-zA-Z0-9_\*\[\]]+)\Z/) { | ||
| 1273 | die("Parameter after '...' param?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); | ||
| 1274 | my $t = $1; | ||
| 1275 | my $n = $2; | ||
| 1276 | if ($n =~ s/\A(\*+)//) { | ||
| 1277 | $t .= $1; # move any `*` that stuck to the name over. | ||
| 1278 | } | ||
| 1279 | if ($n =~ s/\[\]\Z//) { | ||
| 1280 | $t = "$t*"; # move any `[]` that stuck to the name over, as a pointer. | ||
| 1281 | } | ||
| 1282 | $t = sanitize_c_typename($t); | ||
| 1283 | #print("$t\n"); | ||
| 1284 | #print("$n\n"); | ||
| 1285 | push @paraminfo, $n; | ||
| 1286 | push @paraminfo, $t; | ||
| 1287 | } else { | ||
| 1288 | die("Unexpected parameter '$p' in function '$sym' in '$incpath/$dent'!"); | ||
| 1289 | } | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | if (!$is_forced_inline) { # don't do with forced-inline because we don't want the implementation inserted in the wiki. | ||
| 1293 | my $shrink_length = 0; | ||
| 1294 | |||
| 1295 | $decl = ''; # rebuild this with the line breaks, since it looks better for syntax highlighting. | ||
| 1296 | foreach (@decllines) { | ||
| 1297 | if ($decl eq '') { | ||
| 1298 | my $temp; | ||
| 1299 | |||
| 1300 | $decl = $_; | ||
| 1301 | $temp = $decl; | ||
| 1302 | $temp =~ s/\Aextern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(.*?)\s+(\*?)SDLCALL\s+/$3$4 /; | ||
| 1303 | $shrink_length = length($decl) - length($temp); | ||
| 1304 | $decl = $temp; | ||
| 1305 | } else { | ||
| 1306 | my $trimmed = $_; | ||
| 1307 | $trimmed =~ s/\A\s{$shrink_length}//; # shrink to match the removed "extern SDL_DECLSPEC SDLCALL " | ||
| 1308 | $decl .= $trimmed; | ||
| 1309 | } | ||
| 1310 | $decl .= "\n"; | ||
| 1311 | } | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | $decl = strip_fn_declaration_metadata($decl); | ||
| 1315 | |||
| 1316 | # !!! FIXME: code duplication with typedef processing, below. | ||
| 1317 | # We assume any `#define`s directly after the function are related to it: probably bitflags for an integer typedef. | ||
| 1318 | # We'll also allow some other basic preprocessor lines. | ||
| 1319 | # Blank lines are allowed, anything else, even comments, are not. | ||
| 1320 | my $blank_lines = 0; | ||
| 1321 | my $lastpos = tell(FH); | ||
| 1322 | my $lastlineno = $lineno; | ||
| 1323 | my $additional_decl = ''; | ||
| 1324 | my $saw_define = 0; | ||
| 1325 | while (<FH>) { | ||
| 1326 | chomp; | ||
| 1327 | |||
| 1328 | $lineno++; | ||
| 1329 | |||
| 1330 | if (/\A\s*\Z/) { | ||
| 1331 | $blank_lines++; | ||
| 1332 | } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { | ||
| 1333 | if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { | ||
| 1334 | $referenceonly{$1} = $sym; | ||
| 1335 | $saw_define = 1; | ||
| 1336 | } elsif (!$saw_define) { | ||
| 1337 | # if the first non-blank thing isn't a #define, assume we're done. | ||
| 1338 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
| 1339 | $lineno = $lastlineno; | ||
| 1340 | last; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. | ||
| 1344 | |||
| 1345 | # At Sam's request, don't list property defines with functions. (See #9440) | ||
| 1346 | my $is_property = /\A\s*\#\s*define\s+SDL_PROP_/; | ||
| 1347 | if (!$is_property) { | ||
| 1348 | if ($blank_lines > 0) { | ||
| 1349 | while ($blank_lines > 0) { | ||
| 1350 | $additional_decl .= "\n"; | ||
| 1351 | push @decllines, ''; | ||
| 1352 | $blank_lines--; | ||
| 1353 | } | ||
| 1354 | } | ||
| 1355 | $additional_decl .= "\n$_"; | ||
| 1356 | push @decllines, $_; | ||
| 1357 | $lastpos = tell(FH); | ||
| 1358 | } | ||
| 1359 | } else { | ||
| 1360 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
| 1361 | $lineno = $lastlineno; | ||
| 1362 | last; | ||
| 1363 | } | ||
| 1364 | } | ||
| 1365 | $decl .= $additional_decl; | ||
| 1366 | } elsif ($symtype == 2) { # a macro | ||
| 1367 | if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)\s+/) { | ||
| 1368 | $sym = $1; | ||
| 1369 | } else { | ||
| 1370 | #print "Found doxygen but no macro:\n$str\n\n"; | ||
| 1371 | foreach (@templines) { | ||
| 1372 | push @contents, $_; | ||
| 1373 | } | ||
| 1374 | foreach (@decllines) { | ||
| 1375 | push @contents, $_; | ||
| 1376 | } | ||
| 1377 | next; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | while ($decl =~ /\\\Z/) { | ||
| 1381 | my $l = <FH>; | ||
| 1382 | last if not $l; | ||
| 1383 | $lineno++; | ||
| 1384 | chomp($l); | ||
| 1385 | push @decllines, $l; | ||
| 1386 | #$l =~ s/\A\s+//; | ||
| 1387 | $l =~ s/\s+\Z//; | ||
| 1388 | $decl .= "\n$l"; | ||
| 1389 | } | ||
| 1390 | } elsif (($symtype == 3) || ($symtype == 4)) { # struct or union or enum | ||
| 1391 | my $has_definition = 0; | ||
| 1392 | if ($decl =~ /\A\s*(typedef\s+|)(struct|union|enum)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\;|\Z)/) { | ||
| 1393 | my $ctype = $2; | ||
| 1394 | my $origsym = $3; | ||
| 1395 | my $ending = $4; | ||
| 1396 | $sym = $origsym; | ||
| 1397 | if ($sym =~ s/\A(.*?)(\s+)(.*?)\Z/$1/) { | ||
| 1398 | die("Failed to parse '$origsym' correctly!") if ($sym ne $1); # Thought this was "typedef struct MySym MySym;" ... it was not. :( This is a hack! | ||
| 1399 | } | ||
| 1400 | if ($sym eq '') { | ||
| 1401 | die("\n\n$0 FAILURE!\n" . | ||
| 1402 | "There's a 'typedef $ctype' in $incpath/$dent without a name at the top.\n" . | ||
| 1403 | "Instead of `typedef $ctype {} x;`, this should be `typedef $ctype x {} x;`.\n" . | ||
| 1404 | "This causes problems for wikiheaders.pl and scripting language bindings.\n" . | ||
| 1405 | "Please fix it!\n\n"); | ||
| 1406 | } | ||
| 1407 | $has_definition = ($ending ne ';'); | ||
| 1408 | } else { | ||
| 1409 | #print "Found doxygen but no datatype:\n$str\n\n"; | ||
| 1410 | foreach (@templines) { | ||
| 1411 | push @contents, $_; | ||
| 1412 | } | ||
| 1413 | foreach (@decllines) { | ||
| 1414 | push @contents, $_; | ||
| 1415 | } | ||
| 1416 | next; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | # This block attempts to find the whole struct/union/enum definition by counting matching brackets. Kind of yucky. | ||
| 1420 | # It also "parses" enums enough to find out the elements of it. | ||
| 1421 | if ($has_definition) { | ||
| 1422 | my $started = 0; | ||
| 1423 | my $brackets = 0; | ||
| 1424 | my $pending = $decl; | ||
| 1425 | my $skipping_comment = 0; | ||
| 1426 | |||
| 1427 | $decl = ''; | ||
| 1428 | while (!$started || ($brackets != 0)) { | ||
| 1429 | foreach my $seg (split(/([{}])/, $pending)) { # (this will pick up brackets in comments! Be careful!) | ||
| 1430 | $decl .= $seg; | ||
| 1431 | if ($seg eq '{') { | ||
| 1432 | $started = 1; | ||
| 1433 | $brackets++; | ||
| 1434 | } elsif ($seg eq '}') { | ||
| 1435 | die("Something is wrong with header $incpath/$dent while parsing $sym; is a bracket missing?\n") if ($brackets <= 0); | ||
| 1436 | $brackets--; | ||
| 1437 | } | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if ($skipping_comment) { | ||
| 1441 | if ($pending =~ s/\A.*?\*\///) { | ||
| 1442 | $skipping_comment = 0; | ||
| 1443 | } | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | if (!$skipping_comment && $started && ($symtype == 4)) { # Pick out elements of an enum. | ||
| 1447 | my $stripped = "$pending"; | ||
| 1448 | $stripped =~ s/\/\*.*?\*\///g; # dump /* comments */ that exist fully on one line. | ||
| 1449 | if ($stripped =~ /\/\*/) { # uhoh, a /* comment */ that crosses newlines. | ||
| 1450 | $skipping_comment = 1; | ||
| 1451 | } elsif ($stripped =~ /\A\s*([a-zA-Z0-9_]+)(.*)\Z/) { #\s*(\=\s*.*?|)\s*,?(.*?)\Z/) { | ||
| 1452 | if ($1 ne 'typedef') { # make sure we didn't just eat the first line by accident. :/ | ||
| 1453 | #print("ENUM [$1] $incpath/$dent:$lineno\n"); | ||
| 1454 | $referenceonly{$1} = $sym; | ||
| 1455 | } | ||
| 1456 | } | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | if (!$started || ($brackets != 0)) { | ||
| 1460 | $pending = <FH>; | ||
| 1461 | die("EOF/error reading $incpath/$dent while parsing $sym\n") if not $pending; | ||
| 1462 | $lineno++; | ||
| 1463 | chomp($pending); | ||
| 1464 | push @decllines, $pending; | ||
| 1465 | $decl .= "\n"; | ||
| 1466 | } | ||
| 1467 | } | ||
| 1468 | # 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! | ||
| 1469 | } | ||
| 1470 | } elsif ($symtype == 5) { # other typedef | ||
| 1471 | if ($decl =~ /\A\s*typedef\s+(.*)\Z/) { | ||
| 1472 | my $tdstr = $1; | ||
| 1473 | |||
| 1474 | if (not $decl =~ /;/) { | ||
| 1475 | while (<FH>) { | ||
| 1476 | chomp; | ||
| 1477 | $lineno++; | ||
| 1478 | push @decllines, $_; | ||
| 1479 | s/\A\s+//; | ||
| 1480 | s/\s+\Z//; | ||
| 1481 | $decl .= " $_"; | ||
| 1482 | last if /;/; | ||
| 1483 | } | ||
| 1484 | } | ||
| 1485 | $decl =~ s/\s+(\))?;\Z/$1;/; | ||
| 1486 | |||
| 1487 | $tdstr =~ s/;\s*\Z//; | ||
| 1488 | |||
| 1489 | #my $datatype; | ||
| 1490 | if ($tdstr =~ /\A(.*?)\s*\((.*?)\s*\*\s*(.*?)\)\s*\((.*?)(\))?/) { # a function pointer type | ||
| 1491 | $sym = $3; | ||
| 1492 | #$datatype = "$1 ($2 *$sym)($4)"; | ||
| 1493 | } elsif ($tdstr =~ /\A(.*[\s\*]+)(.*?)\s*\Z/) { | ||
| 1494 | $sym = $2; | ||
| 1495 | #$datatype = $1; | ||
| 1496 | } else { | ||
| 1497 | die("Failed to parse typedef '$tdstr' in $incpath/$dent!\n"); # I'm hitting a C grammar nail with a regexp hammer here, y'all. | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | $sym =~ s/\A\s+//; | ||
| 1501 | $sym =~ s/\s+\Z//; | ||
| 1502 | #$datatype =~ s/\A\s+//; | ||
| 1503 | #$datatype =~ s/\s+\Z//; | ||
| 1504 | } else { | ||
| 1505 | #print "Found doxygen but no datatype:\n$str\n\n"; | ||
| 1506 | foreach (@templines) { | ||
| 1507 | push @contents, $_; | ||
| 1508 | } | ||
| 1509 | foreach (@decllines) { | ||
| 1510 | push @contents, $_; | ||
| 1511 | } | ||
| 1512 | next; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | # We assume any `#define`s directly after the typedef are related to it: probably bitflags for an integer typedef. | ||
| 1516 | # We'll also allow some other basic preprocessor lines. | ||
| 1517 | # Blank lines are allowed, anything else, even comments, are not. | ||
| 1518 | my $blank_lines = 0; | ||
| 1519 | my $lastpos = tell(FH); | ||
| 1520 | my $lastlineno = $lineno; | ||
| 1521 | my $additional_decl = ''; | ||
| 1522 | my $saw_define = 0; | ||
| 1523 | while (<FH>) { | ||
| 1524 | chomp; | ||
| 1525 | |||
| 1526 | $lineno++; | ||
| 1527 | |||
| 1528 | if (/\A\s*\Z/) { | ||
| 1529 | $blank_lines++; | ||
| 1530 | } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { | ||
| 1531 | if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { | ||
| 1532 | $referenceonly{$1} = $sym; | ||
| 1533 | $saw_define = 1; | ||
| 1534 | } elsif (!$saw_define) { | ||
| 1535 | # if the first non-blank thing isn't a #define, assume we're done. | ||
| 1536 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
| 1537 | $lineno = $lastlineno; | ||
| 1538 | last; | ||
| 1539 | } | ||
| 1540 | # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. | ||
| 1541 | if ($blank_lines > 0) { | ||
| 1542 | while ($blank_lines > 0) { | ||
| 1543 | $additional_decl .= "\n"; | ||
| 1544 | push @decllines, ''; | ||
| 1545 | $blank_lines--; | ||
| 1546 | } | ||
| 1547 | } | ||
| 1548 | $additional_decl .= "\n$_"; | ||
| 1549 | push @decllines, $_; | ||
| 1550 | $lastpos = tell(FH); | ||
| 1551 | } else { | ||
| 1552 | seek(FH, $lastpos, 0); # re-read eaten lines again next time. | ||
| 1553 | $lineno = $lastlineno; | ||
| 1554 | last; | ||
| 1555 | } | ||
| 1556 | } | ||
| 1557 | $decl .= $additional_decl; | ||
| 1558 | } else { | ||
| 1559 | die("Unexpected symtype $symtype"); | ||
| 1560 | } | ||
| 1561 | |||
| 1562 | #print("DECL: [$decl]\n"); | ||
| 1563 | |||
| 1564 | #print("$sym:\n$str\n\n"); | ||
| 1565 | |||
| 1566 | # There might be multiple declarations of a function due to #ifdefs, | ||
| 1567 | # and only one of them will have documentation. If we hit an | ||
| 1568 | # undocumented one before, delete the placeholder line we left for | ||
| 1569 | # it so it doesn't accumulate a new blank line on each run. | ||
| 1570 | my $skipsym = 0; | ||
| 1571 | if (defined $headersymshasdoxygen{$sym}) { | ||
| 1572 | if ($headersymshasdoxygen{$sym} == 0) { # An undocumented declaration already exists, nuke its placeholder line. | ||
| 1573 | delete $contents[$headersymschunk{$sym}]; # delete DOES NOT RENUMBER existing elements! | ||
| 1574 | } else { # documented function already existed? | ||
| 1575 | $skipsym = 1; # don't add this copy to the list of functions. | ||
| 1576 | if ($has_doxygen) { | ||
| 1577 | print STDERR "WARNING: Symbol '$sym' appears to be documented in multiple locations. Only keeping the first one we saw!\n"; | ||
| 1578 | } | ||
| 1579 | push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); # just put the existing declation in as-is. | ||
| 1580 | } | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | if (!$skipsym) { | ||
| 1584 | $headersymscategory{$sym} = $current_wiki_category if defined $current_wiki_category; | ||
| 1585 | $headersyms{$sym} = $str; | ||
| 1586 | $headerdecls{$sym} = $decl; | ||
| 1587 | $headersymslocation{$sym} = $dent; | ||
| 1588 | $headersymschunk{$sym} = scalar(@contents); | ||
| 1589 | $headersymshasdoxygen{$sym} = $has_doxygen; | ||
| 1590 | $headersymstype{$sym} = $symtype; | ||
| 1591 | $headersymsparaminfo{$sym} = \@paraminfo if (scalar(@paraminfo) > 0); | ||
| 1592 | $headersymsrettype{$sym} = $rettype if (defined($rettype)); | ||
| 1593 | push @function_order, $sym if ($symtype == 1) || ($symtype == 2); | ||
| 1594 | push @contents, join("\n", @templines); | ||
| 1595 | push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | } | ||
| 1599 | close(FH); | ||
| 1600 | |||
| 1601 | $headers{$dent} = \@contents; | ||
| 1602 | $quickreffuncorder{$current_wiki_category} = \@function_order if defined $current_wiki_category; | ||
| 1603 | } | ||
| 1604 | closedir(DH); | ||
| 1605 | |||
| 1606 | |||
| 1607 | opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n"); | ||
| 1608 | while (my $d = readdir(DH)) { | ||
| 1609 | my $dent = $d; | ||
| 1610 | my $type = ''; | ||
| 1611 | if ($dent =~ /\.(md|mediawiki)\Z/) { | ||
| 1612 | $type = $1; | ||
| 1613 | } else { | ||
| 1614 | next; # only dealing with wiki pages. | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | my $sym = $dent; | ||
| 1618 | $sym =~ s/\..*\Z//; | ||
| 1619 | |||
| 1620 | # (There are other pages to ignore, but these are known ones to not bother parsing.) | ||
| 1621 | # Ignore FrontPage. | ||
| 1622 | next if $sym eq 'FrontPage'; | ||
| 1623 | |||
| 1624 | open(FH, '<', "$wikipath/$dent") or die("Can't open '$wikipath/$dent': $!\n"); | ||
| 1625 | |||
| 1626 | if ($sym =~ /\ACategory(.*?)\Z/) { # Special case for Category pages. | ||
| 1627 | # Find the end of the category documentation in the existing file and append everything else to the new file. | ||
| 1628 | my $cat = $1; | ||
| 1629 | my $docstr = ''; | ||
| 1630 | my $notdocstr = ''; | ||
| 1631 | my $docs = 1; | ||
| 1632 | while (<FH>) { | ||
| 1633 | chomp; | ||
| 1634 | if ($docs) { | ||
| 1635 | $docs = 0 if /\A\-\-\-\-\Z/; # Hit a footer? We're done. | ||
| 1636 | $docs = 0 if /\A<!\-\-/; # Hit an HTML comment? We're done. | ||
| 1637 | } | ||
| 1638 | if ($docs) { | ||
| 1639 | $docstr .= "$_\n"; | ||
| 1640 | } else { | ||
| 1641 | $notdocstr .= "$_\n"; | ||
| 1642 | } | ||
| 1643 | } | ||
| 1644 | close(FH); | ||
| 1645 | |||
| 1646 | $docstr =~ s/\s*\Z//; | ||
| 1647 | |||
| 1648 | $sym = "[category documentation] $cat"; # make a fake, unique symbol that's not valid C. | ||
| 1649 | $wikitypes{$sym} = $type; | ||
| 1650 | my %sections = (); | ||
| 1651 | $sections{'Remarks'} = $docstr; | ||
| 1652 | $sections{'[footer]'} = $notdocstr; | ||
| 1653 | $wikisyms{$sym} = \%sections; | ||
| 1654 | my @section_order = ( 'Remarks', '[footer]' ); | ||
| 1655 | $wikisectionorder{$sym} = \@section_order; | ||
| 1656 | next; | ||
| 1657 | } | ||
| 1658 | |||
| 1659 | my $current_section = '[start]'; | ||
| 1660 | my @section_order = ( $current_section ); | ||
| 1661 | my %sections = (); | ||
| 1662 | $sections{$current_section} = ''; | ||
| 1663 | |||
| 1664 | my $firstline = 1; | ||
| 1665 | |||
| 1666 | while (<FH>) { | ||
| 1667 | chomp; | ||
| 1668 | my $orig = $_; | ||
| 1669 | s/\A\s*//; | ||
| 1670 | s/\s*\Z//; | ||
| 1671 | |||
| 1672 | if ($type eq 'mediawiki') { | ||
| 1673 | if (defined($wikipreamble) && $firstline && /\A\=\=\=\=\=\= (.*?) \=\=\=\=\=\=\Z/ && ($1 eq $wikipreamble)) { | ||
| 1674 | $firstline = 0; # skip this. | ||
| 1675 | next; | ||
| 1676 | } elsif (/\A\= (.*?) \=\Z/) { | ||
| 1677 | $firstline = 0; | ||
| 1678 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
| 1679 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
| 1680 | push @section_order, $current_section; | ||
| 1681 | $sections{$current_section} = ''; | ||
| 1682 | } elsif (/\A\=\= (.*?) \=\=\Z/) { | ||
| 1683 | $firstline = 0; | ||
| 1684 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
| 1685 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
| 1686 | push @section_order, $current_section; | ||
| 1687 | $sections{$current_section} = ''; | ||
| 1688 | next; | ||
| 1689 | } elsif (/\A\-\-\-\-\Z/) { | ||
| 1690 | $firstline = 0; | ||
| 1691 | $current_section = '[footer]'; | ||
| 1692 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
| 1693 | push @section_order, $current_section; | ||
| 1694 | $sections{$current_section} = ''; | ||
| 1695 | next; | ||
| 1696 | } | ||
| 1697 | } elsif ($type eq 'md') { | ||
| 1698 | if (defined($wikipreamble) && $firstline && /\A\#\#\#\#\#\# (.*?)\Z/ && ($1 eq $wikipreamble)) { | ||
| 1699 | $firstline = 0; # skip this. | ||
| 1700 | next; | ||
| 1701 | } elsif (/\A\#+ (.*?)\Z/) { | ||
| 1702 | $firstline = 0; | ||
| 1703 | $current_section = ($1 eq $sym) ? '[Brief]' : $1; | ||
| 1704 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
| 1705 | push @section_order, $current_section; | ||
| 1706 | $sections{$current_section} = ''; | ||
| 1707 | next; | ||
| 1708 | } elsif (/\A\-\-\-\-\Z/) { | ||
| 1709 | $firstline = 0; | ||
| 1710 | $current_section = '[footer]'; | ||
| 1711 | die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section}; | ||
| 1712 | push @section_order, $current_section; | ||
| 1713 | $sections{$current_section} = ''; | ||
| 1714 | next; | ||
| 1715 | } | ||
| 1716 | } else { | ||
| 1717 | die("Unexpected wiki file type. Fixme!"); | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | if ($firstline) { | ||
| 1721 | $firstline = ($_ ne ''); | ||
| 1722 | } | ||
| 1723 | if (!$firstline) { | ||
| 1724 | $sections{$current_section} .= "$orig\n"; | ||
| 1725 | } | ||
| 1726 | } | ||
| 1727 | close(FH); | ||
| 1728 | |||
| 1729 | foreach (keys %sections) { | ||
| 1730 | $sections{$_} =~ s/\A\n+//; | ||
| 1731 | $sections{$_} =~ s/\n+\Z//; | ||
| 1732 | $sections{$_} .= "\n"; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | # older section name we used, migrate over from it. | ||
| 1736 | if (defined $sections{'Related Functions'}) { | ||
| 1737 | if (not defined $sections{'See Also'}) { | ||
| 1738 | $sections{'See Also'} = $sections{'Related Functions'}; | ||
| 1739 | } | ||
| 1740 | delete $sections{'Related Functions'}; | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | if (0) { | ||
| 1744 | foreach (@section_order) { | ||
| 1745 | print("$sym SECTION '$_':\n"); | ||
| 1746 | print($sections{$_}); | ||
| 1747 | print("\n\n"); | ||
| 1748 | } | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | $wikitypes{$sym} = $type; | ||
| 1752 | $wikisyms{$sym} = \%sections; | ||
| 1753 | $wikisectionorder{$sym} = \@section_order; | ||
| 1754 | } | ||
| 1755 | closedir(DH); | ||
| 1756 | |||
| 1757 | delete $wikisyms{"Undocumented"}; | ||
| 1758 | |||
| 1759 | { | ||
| 1760 | my $path = "$wikipath/Undocumented.md"; | ||
| 1761 | open(my $fh, '>', $path) or die("Can't open '$path': $!\n"); | ||
| 1762 | |||
| 1763 | print $fh "# Undocumented\n\n"; | ||
| 1764 | print_undocumented_section($fh, 'Functions', 1); | ||
| 1765 | #print_undocumented_section($fh, 'Macros', 2); | ||
| 1766 | |||
| 1767 | close($fh); | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | if ($warn_about_missing) { | ||
| 1771 | foreach (keys %wikisyms) { | ||
| 1772 | my $sym = $_; | ||
| 1773 | if (not defined $headersyms{$sym}) { | ||
| 1774 | print STDERR "WARNING: $sym defined in the wiki but not the headers!\n"; | ||
| 1775 | } | ||
| 1776 | } | ||
| 1777 | |||
| 1778 | foreach (keys %headersyms) { | ||
| 1779 | my $sym = $_; | ||
| 1780 | if (not defined $wikisyms{$sym}) { | ||
| 1781 | print STDERR "WARNING: $sym defined in the headers but not the wiki!\n"; | ||
| 1782 | } | ||
| 1783 | } | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | if ($copy_direction == 1) { # --copy-to-headers | ||
| 1787 | my %changed_headers = (); | ||
| 1788 | |||
| 1789 | $dewikify_mode = 'md'; | ||
| 1790 | $wordwrap_mode = 'md'; # the headers use Markdown format. | ||
| 1791 | |||
| 1792 | foreach (keys %headersyms) { | ||
| 1793 | my $sym = $_; | ||
| 1794 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
| 1795 | my $symtype = $headersymstype{$sym}; | ||
| 1796 | my $wikitype = $wikitypes{$sym}; | ||
| 1797 | my $sectionsref = $wikisyms{$sym}; | ||
| 1798 | my $remarks = $sectionsref->{'Remarks'}; | ||
| 1799 | my $returns = $sectionsref->{'Return Value'}; | ||
| 1800 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
| 1801 | my $version = $sectionsref->{'Version'}; | ||
| 1802 | my $related = $sectionsref->{'See Also'}; | ||
| 1803 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
| 1804 | my $brief = $sectionsref->{'[Brief]'}; | ||
| 1805 | my $addblank = 0; | ||
| 1806 | my $str = ''; | ||
| 1807 | |||
| 1808 | my $params = undef; | ||
| 1809 | my $paramstr = undef; | ||
| 1810 | |||
| 1811 | if ($symtype == -1) { # category documentation block. | ||
| 1812 | # nothing to be done here. | ||
| 1813 | } elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef. | ||
| 1814 | $params = $sectionsref->{'Function Parameters'}; | ||
| 1815 | $paramstr = '\param'; | ||
| 1816 | } elsif ($symtype == 2) { | ||
| 1817 | $params = $sectionsref->{'Macro Parameters'}; | ||
| 1818 | $paramstr = '\param'; | ||
| 1819 | } elsif ($symtype == 3) { | ||
| 1820 | $params = $sectionsref->{'Fields'}; | ||
| 1821 | $paramstr = '\field'; | ||
| 1822 | } elsif ($symtype == 4) { | ||
| 1823 | $params = $sectionsref->{'Values'}; | ||
| 1824 | $paramstr = '\value'; | ||
| 1825 | } else { | ||
| 1826 | die("Unexpected symtype $symtype"); | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | $headersymshasdoxygen{$sym} = 1; # Added/changed doxygen for this header. | ||
| 1830 | |||
| 1831 | $brief = dewikify($wikitype, $brief); | ||
| 1832 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
| 1833 | my @briefsplit = split /\n/, $brief; | ||
| 1834 | $brief = shift @briefsplit; | ||
| 1835 | |||
| 1836 | if (defined $remarks) { | ||
| 1837 | $remarks = join("\n", @briefsplit) . dewikify($wikitype, $remarks); | ||
| 1838 | } | ||
| 1839 | |||
| 1840 | if (defined $brief) { | ||
| 1841 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1842 | $str .= wordwrap($brief) . "\n"; | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | if (defined $remarks) { | ||
| 1846 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1847 | $str .= wordwrap($remarks) . "\n"; | ||
| 1848 | } | ||
| 1849 | |||
| 1850 | if (defined $deprecated) { | ||
| 1851 | # !!! FIXME: lots of code duplication in all of these. | ||
| 1852 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1853 | my $v = dewikify($wikitype, $deprecated); | ||
| 1854 | my $whitespacelen = length("\\deprecated") + 1; | ||
| 1855 | my $whitespace = ' ' x $whitespacelen; | ||
| 1856 | $v = wordwrap($v, -$whitespacelen); | ||
| 1857 | my @desclines = split /\n/, $v; | ||
| 1858 | my $firstline = shift @desclines; | ||
| 1859 | $str .= "\\deprecated $firstline\n"; | ||
| 1860 | foreach (@desclines) { | ||
| 1861 | $str .= "${whitespace}$_\n"; | ||
| 1862 | } | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | if (defined $params) { | ||
| 1866 | $str .= "\n" if $addblank; $addblank = (defined $returns) ? 0 : 1; | ||
| 1867 | my @lines = split /\n/, dewikify($wikitype, $params); | ||
| 1868 | if ($wikitype eq 'mediawiki') { | ||
| 1869 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
| 1870 | while (scalar(@lines) >= 3) { | ||
| 1871 | my $c_datatype = shift @lines; | ||
| 1872 | my $name = shift @lines; | ||
| 1873 | my $desc = shift @lines; | ||
| 1874 | my $terminator; # the '|-' or '|}' line. | ||
| 1875 | |||
| 1876 | 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. | ||
| 1877 | $terminator = $desc; | ||
| 1878 | $desc = $name; | ||
| 1879 | $name = $c_datatype; | ||
| 1880 | $c_datatype = ''; | ||
| 1881 | } else { | ||
| 1882 | $terminator = shift @lines; | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
| 1886 | $name =~ s/\A\|\s*//; | ||
| 1887 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 1888 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 1889 | $desc =~ s/\A\|\s*//; | ||
| 1890 | #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; | ||
| 1891 | my $whitespacelen = length($name) + 8; | ||
| 1892 | my $whitespace = ' ' x $whitespacelen; | ||
| 1893 | $desc = wordwrap($desc, -$whitespacelen); | ||
| 1894 | my @desclines = split /\n/, $desc; | ||
| 1895 | my $firstline = shift @desclines; | ||
| 1896 | $str .= "$paramstr $name $firstline\n"; | ||
| 1897 | foreach (@desclines) { | ||
| 1898 | $str .= "${whitespace}$_\n"; | ||
| 1899 | } | ||
| 1900 | } | ||
| 1901 | } elsif ($wikitype eq 'md') { | ||
| 1902 | my $l; | ||
| 1903 | $l = shift @lines; | ||
| 1904 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
| 1905 | $l = shift @lines; | ||
| 1906 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
| 1907 | while (scalar(@lines) >= 1) { | ||
| 1908 | $l = shift @lines; | ||
| 1909 | my $name; | ||
| 1910 | my $desc; | ||
| 1911 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 1912 | # c datatype is $1, but we don't care about it here. | ||
| 1913 | $name = $2; | ||
| 1914 | $desc = $3; | ||
| 1915 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 1916 | $name = $1; | ||
| 1917 | $desc = $2; | ||
| 1918 | } else { | ||
| 1919 | last; # we seem to have run out of table. | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 1923 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 1924 | #print STDERR "SYM: $sym NAME: $name DESC: $desc\n"; | ||
| 1925 | my $whitespacelen = length($name) + 8; | ||
| 1926 | my $whitespace = ' ' x $whitespacelen; | ||
| 1927 | $desc = wordwrap($desc, -$whitespacelen); | ||
| 1928 | my @desclines = split /\n/, $desc; | ||
| 1929 | my $firstline = shift @desclines; | ||
| 1930 | $str .= "$paramstr $name $firstline\n"; | ||
| 1931 | foreach (@desclines) { | ||
| 1932 | $str .= "${whitespace}$_\n"; | ||
| 1933 | } | ||
| 1934 | } | ||
| 1935 | } else { | ||
| 1936 | die("write me"); | ||
| 1937 | } | ||
| 1938 | } | ||
| 1939 | |||
| 1940 | if (defined $returns) { | ||
| 1941 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1942 | my $r = dewikify($wikitype, $returns); | ||
| 1943 | $r =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. | ||
| 1944 | my $retstr = "\\returns"; | ||
| 1945 | if ($r =~ s/\AReturn(s?)\s+//) { | ||
| 1946 | $retstr = "\\return$1"; | ||
| 1947 | } | ||
| 1948 | |||
| 1949 | my $whitespacelen = length($retstr) + 1; | ||
| 1950 | my $whitespace = ' ' x $whitespacelen; | ||
| 1951 | $r = wordwrap($r, -$whitespacelen); | ||
| 1952 | my @desclines = split /\n/, $r; | ||
| 1953 | my $firstline = shift @desclines; | ||
| 1954 | $str .= "$retstr $firstline\n"; | ||
| 1955 | foreach (@desclines) { | ||
| 1956 | $str .= "${whitespace}$_\n"; | ||
| 1957 | } | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | if (defined $threadsafety) { | ||
| 1961 | # !!! FIXME: lots of code duplication in all of these. | ||
| 1962 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1963 | my $v = dewikify($wikitype, $threadsafety); | ||
| 1964 | my $whitespacelen = length("\\threadsafety") + 1; | ||
| 1965 | my $whitespace = ' ' x $whitespacelen; | ||
| 1966 | $v = wordwrap($v, -$whitespacelen); | ||
| 1967 | my @desclines = split /\n/, $v; | ||
| 1968 | my $firstline = shift @desclines; | ||
| 1969 | $str .= "\\threadsafety $firstline\n"; | ||
| 1970 | foreach (@desclines) { | ||
| 1971 | $str .= "${whitespace}$_\n"; | ||
| 1972 | } | ||
| 1973 | } | ||
| 1974 | |||
| 1975 | if (defined $version) { | ||
| 1976 | # !!! FIXME: lots of code duplication in all of these. | ||
| 1977 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1978 | my $v = dewikify($wikitype, $version); | ||
| 1979 | my $whitespacelen = length("\\since") + 1; | ||
| 1980 | my $whitespace = ' ' x $whitespacelen; | ||
| 1981 | $v = wordwrap($v, -$whitespacelen); | ||
| 1982 | my @desclines = split /\n/, $v; | ||
| 1983 | my $firstline = shift @desclines; | ||
| 1984 | $str .= "\\since $firstline\n"; | ||
| 1985 | foreach (@desclines) { | ||
| 1986 | $str .= "${whitespace}$_\n"; | ||
| 1987 | } | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | if (defined $related) { | ||
| 1991 | # !!! FIXME: lots of code duplication in all of these. | ||
| 1992 | $str .= "\n" if $addblank; $addblank = 1; | ||
| 1993 | my $v = dewikify($wikitype, $related); | ||
| 1994 | my @desclines = split /\n/, $v; | ||
| 1995 | foreach (@desclines) { | ||
| 1996 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
| 1997 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
| 1998 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
| 1999 | s/\A\/*//; | ||
| 2000 | s/\A\s*[\:\*\-]\s*//; | ||
| 2001 | s/\A\s+//; | ||
| 2002 | s/\s+\Z//; | ||
| 2003 | $str .= "\\sa $_\n"; | ||
| 2004 | } | ||
| 2005 | } | ||
| 2006 | |||
| 2007 | my $header = $headersymslocation{$sym}; | ||
| 2008 | my $contentsref = $headers{$header}; | ||
| 2009 | my $chunk = $headersymschunk{$sym}; | ||
| 2010 | |||
| 2011 | my @lines = split /\n/, $str; | ||
| 2012 | |||
| 2013 | my $addnewline = (($chunk > 0) && ($$contentsref[$chunk-1] ne '')) ? "\n" : ''; | ||
| 2014 | |||
| 2015 | my $output = "$addnewline/**\n"; | ||
| 2016 | foreach (@lines) { | ||
| 2017 | chomp; | ||
| 2018 | s/\s*\Z//; | ||
| 2019 | if ($_ eq '') { | ||
| 2020 | $output .= " *\n"; | ||
| 2021 | } else { | ||
| 2022 | $output .= " * $_\n"; | ||
| 2023 | } | ||
| 2024 | } | ||
| 2025 | $output .= " */"; | ||
| 2026 | |||
| 2027 | #print("$sym:\n[$output]\n\n"); | ||
| 2028 | |||
| 2029 | $$contentsref[$chunk] = $output; | ||
| 2030 | #$$contentsref[$chunk+1] = $headerdecls{$sym}; | ||
| 2031 | |||
| 2032 | $changed_headers{$header} = 1; | ||
| 2033 | } | ||
| 2034 | |||
| 2035 | foreach (keys %changed_headers) { | ||
| 2036 | my $header = $_; | ||
| 2037 | |||
| 2038 | # this is kinda inefficient, but oh well. | ||
| 2039 | my @removelines = (); | ||
| 2040 | foreach (keys %headersymslocation) { | ||
| 2041 | my $sym = $_; | ||
| 2042 | next if $headersymshasdoxygen{$sym}; | ||
| 2043 | next if $headersymslocation{$sym} ne $header; | ||
| 2044 | # 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. | ||
| 2045 | push @removelines, $headersymschunk{$sym}; | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | my $contentsref = $headers{$header}; | ||
| 2049 | foreach (@removelines) { | ||
| 2050 | delete $$contentsref[$_]; # delete DOES NOT RENUMBER existing elements! | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | my $path = "$incpath/$header.tmp"; | ||
| 2054 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
| 2055 | foreach (@$contentsref) { | ||
| 2056 | print FH "$_\n" if defined $_; | ||
| 2057 | } | ||
| 2058 | close(FH); | ||
| 2059 | rename($path, "$incpath/$header") or die("Can't rename '$path' to '$incpath/$header': $!\n"); | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | if (defined $readmepath) { | ||
| 2063 | if ( -d $wikireadmepath ) { | ||
| 2064 | mkdir($readmepath); # just in case | ||
| 2065 | opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n"); | ||
| 2066 | while (readdir(DH)) { | ||
| 2067 | my $dent = $_; | ||
| 2068 | if ($dent =~ /\A(.*?)\.md\Z/) { # we only bridge Markdown files here. | ||
| 2069 | next if $1 eq 'FrontPage'; | ||
| 2070 | filecopy("$wikireadmepath/$dent", "$readmepath/README-$dent", "\n"); | ||
| 2071 | } | ||
| 2072 | } | ||
| 2073 | closedir(DH); | ||
| 2074 | } | ||
| 2075 | } | ||
| 2076 | |||
| 2077 | } elsif ($copy_direction == -1) { # --copy-to-wiki | ||
| 2078 | |||
| 2079 | my %briefs = (); # $briefs{'SDL_OpenAudio'} -> the \brief string for the function. | ||
| 2080 | |||
| 2081 | if (defined $changeformat) { | ||
| 2082 | $dewikify_mode = $changeformat; | ||
| 2083 | $wordwrap_mode = $changeformat; | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | foreach (keys %headersyms) { | ||
| 2087 | my $sym = $_; | ||
| 2088 | next if not $headersymshasdoxygen{$sym}; | ||
| 2089 | next if $sym =~ /\A\[category documentation\]/; # not real symbols, we handle this elsewhere. | ||
| 2090 | my $symtype = $headersymstype{$sym}; | ||
| 2091 | my $origwikitype = defined $wikitypes{$sym} ? $wikitypes{$sym} : 'md'; # default to MarkDown for new stuff. | ||
| 2092 | my $wikitype = (defined $changeformat) ? $changeformat : $origwikitype; | ||
| 2093 | die("Unexpected wikitype '$wikitype'") if (($wikitype ne 'mediawiki') and ($wikitype ne 'md') and ($wikitype ne 'manpage')); | ||
| 2094 | |||
| 2095 | #print("$sym\n"); next; | ||
| 2096 | |||
| 2097 | $wordwrap_mode = $wikitype; | ||
| 2098 | |||
| 2099 | my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. | ||
| 2100 | next if not defined $raw; | ||
| 2101 | $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. | ||
| 2102 | |||
| 2103 | my @doxygenlines = split /\n/, $raw; | ||
| 2104 | my $brief = ''; | ||
| 2105 | while (@doxygenlines) { | ||
| 2106 | last if $doxygenlines[0] =~ /\A\\/; # some sort of doxygen command, assume we're past the general remarks. | ||
| 2107 | last if $doxygenlines[0] =~ /\A\s*\Z/; # blank line? End of paragraph, done. | ||
| 2108 | my $l = shift @doxygenlines; | ||
| 2109 | chomp($l); | ||
| 2110 | $l =~ s/\A\s*//; | ||
| 2111 | $l =~ s/\s*\Z//; | ||
| 2112 | $brief .= "$l "; | ||
| 2113 | } | ||
| 2114 | |||
| 2115 | $brief =~ s/\s+\Z//; | ||
| 2116 | $brief =~ s/\A(.*?\.) /$1\n\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
| 2117 | my @briefsplit = split /\n/, $brief; | ||
| 2118 | |||
| 2119 | next if not defined $briefsplit[0]; # No brief text? Probably a bogus Doxygen comment, skip it. | ||
| 2120 | |||
| 2121 | $brief = wikify($wikitype, shift @briefsplit) . "\n"; | ||
| 2122 | @doxygenlines = (@briefsplit, @doxygenlines); | ||
| 2123 | |||
| 2124 | my $remarks = ''; | ||
| 2125 | while (@doxygenlines) { | ||
| 2126 | last if $doxygenlines[0] =~ /\A\\/; # some sort of doxygen command, assume we're past the general remarks. | ||
| 2127 | my $l = shift @doxygenlines; | ||
| 2128 | $remarks .= "$l\n"; | ||
| 2129 | } | ||
| 2130 | |||
| 2131 | #print("REMARKS:\n\n $remarks\n\n"); | ||
| 2132 | |||
| 2133 | $remarks = wordwrap(wikify($wikitype, $remarks)); | ||
| 2134 | $remarks =~ s/\A\s*//; | ||
| 2135 | $remarks =~ s/\s*\Z//; | ||
| 2136 | |||
| 2137 | my $decl = $headerdecls{$sym}; | ||
| 2138 | |||
| 2139 | my $syntax = ''; | ||
| 2140 | if ($wikitype eq 'mediawiki') { | ||
| 2141 | $syntax = "<syntaxhighlight lang='c'>\n$decl</syntaxhighlight>\n"; | ||
| 2142 | } elsif ($wikitype eq 'md') { | ||
| 2143 | $decl =~ s/\n+\Z//; | ||
| 2144 | $syntax = "```c\n$decl\n```\n"; | ||
| 2145 | } else { die("Expected wikitype '$wikitype'"); } | ||
| 2146 | |||
| 2147 | my %sections = (); | ||
| 2148 | $sections{'[Brief]'} = $brief; # include this section even if blank so we get a title line. | ||
| 2149 | $sections{'Remarks'} = "$remarks\n" if $remarks ne ''; | ||
| 2150 | $sections{'Syntax'} = $syntax; | ||
| 2151 | |||
| 2152 | $briefs{$sym} = $brief; | ||
| 2153 | |||
| 2154 | my %params = (); # have to parse these and build up the wiki tables after, since Markdown needs to know the length of the largest string. :/ | ||
| 2155 | my @paramsorder = (); | ||
| 2156 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
| 2157 | my $has_returns = 0; | ||
| 2158 | my $has_threadsafety = 0; | ||
| 2159 | |||
| 2160 | while (@doxygenlines) { | ||
| 2161 | my $l = shift @doxygenlines; | ||
| 2162 | # We allow param/field/value interchangeably, even if it doesn't make sense. The next --copy-to-headers will correct it anyhow. | ||
| 2163 | if ($l =~ /\A\\(param|field|value)\s+(.*?)\s+(.*)\Z/) { | ||
| 2164 | my $arg = $2; | ||
| 2165 | my $desc = $3; | ||
| 2166 | while (@doxygenlines) { | ||
| 2167 | my $subline = $doxygenlines[0]; | ||
| 2168 | $subline =~ s/\A\s*//; | ||
| 2169 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
| 2170 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
| 2171 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
| 2172 | $desc .= "\n"; | ||
| 2173 | } else { | ||
| 2174 | $desc .= " $subline"; | ||
| 2175 | } | ||
| 2176 | } | ||
| 2177 | |||
| 2178 | $desc =~ s/[\s\n]+\Z//ms; | ||
| 2179 | |||
| 2180 | if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. | ||
| 2181 | if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { | ||
| 2182 | print STDERR "WARNING: $sym\'s '\\param $arg' text starts with a capital letter: '$desc'. Fixing.\n"; | ||
| 2183 | $desc = lcfirst($desc); | ||
| 2184 | } | ||
| 2185 | } | ||
| 2186 | |||
| 2187 | if (not $desc =~ /[\.\!]\Z/) { | ||
| 2188 | print STDERR "WARNING: $sym\'s '\\param $arg' text doesn't end with punctuation: '$desc'. Fixing.\n"; | ||
| 2189 | $desc .= '.'; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | # Validate this param. | ||
| 2193 | if (defined($params{$arg})) { | ||
| 2194 | print STDERR "WARNING: Symbol '$sym' has multiple '\\param $arg' declarations! Only keeping the first one!\n"; | ||
| 2195 | } elsif (defined $fnsigparams) { | ||
| 2196 | my $found = 0; | ||
| 2197 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
| 2198 | $found = 1, last if (@$fnsigparams[$i] eq $arg); | ||
| 2199 | } | ||
| 2200 | if (!$found) { | ||
| 2201 | print STDERR "WARNING: Symbol '$sym' has a '\\param $arg' for a param that doesn't exist. It will be removed!\n"; | ||
| 2202 | } | ||
| 2203 | } | ||
| 2204 | |||
| 2205 | # We need to know the length of the longest string to make Markdown tables, so we just store these off until everything is parsed. | ||
| 2206 | $params{$arg} = $desc; | ||
| 2207 | push @paramsorder, $arg; | ||
| 2208 | } elsif ($l =~ /\A\\r(eturns?)\s+(.*)\Z/) { | ||
| 2209 | $has_returns = 1; | ||
| 2210 | # !!! FIXME: complain if this isn't a function or macro. | ||
| 2211 | my $retstr = "R$1"; # "Return" or "Returns" | ||
| 2212 | my $desc = $2; | ||
| 2213 | |||
| 2214 | while (@doxygenlines) { | ||
| 2215 | my $subline = $doxygenlines[0]; | ||
| 2216 | $subline =~ s/\A\s*//; | ||
| 2217 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
| 2218 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
| 2219 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
| 2220 | $desc .= "\n"; | ||
| 2221 | } else { | ||
| 2222 | $desc .= " $subline"; | ||
| 2223 | } | ||
| 2224 | } | ||
| 2225 | $desc =~ s/[\s\n]+\Z//ms; | ||
| 2226 | |||
| 2227 | if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. | ||
| 2228 | if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { | ||
| 2229 | print STDERR "WARNING: $sym\'s '\\returns' text starts with a capital letter: '$desc'. Fixing.\n"; | ||
| 2230 | $desc = lcfirst($desc); | ||
| 2231 | } | ||
| 2232 | } | ||
| 2233 | |||
| 2234 | if (not $desc =~ /[\.\!]\Z/) { | ||
| 2235 | print STDERR "WARNING: $sym\'s '\\returns' text doesn't end with punctuation: '$desc'. Fixing.\n"; | ||
| 2236 | $desc .= '.'; | ||
| 2237 | } | ||
| 2238 | |||
| 2239 | # Make sure the \returns info is valid. | ||
| 2240 | my $rettype = $headersymsrettype{$sym}; | ||
| 2241 | die("Don't have a rettype for '$sym' for some reason!") if (($symtype == 1) && (not defined($rettype))); | ||
| 2242 | if (defined($sections{'Return Value'})) { | ||
| 2243 | print STDERR "WARNING: Symbol '$sym' has multiple '\\return' declarations! Only keeping the first one!\n"; | ||
| 2244 | } elsif (($symtype != 1) && ($symtype != 2) && ($symtype != 5)) { # !!! FIXME: if 5, make sure it's a function pointer typedef! | ||
| 2245 | print STDERR "WARNING: Symbol '$sym' has a '\\return' declaration but isn't a function or macro! Removing it!\n"; | ||
| 2246 | } elsif (($symtype == 1) && ($headersymsrettype{$sym} eq 'void')) { | ||
| 2247 | print STDERR "WARNING: Function '$sym' has a '\\returns' declaration but function returns void! Removing it!\n"; | ||
| 2248 | } else { | ||
| 2249 | my $rettypestr = defined($rettype) ? ('(' . wikify($wikitype, $rettype) . ') ') : ''; | ||
| 2250 | $sections{'Return Value'} = wordwrap("$rettypestr$retstr ". wikify($wikitype, $desc)) . "\n"; | ||
| 2251 | } | ||
| 2252 | } elsif ($l =~ /\A\\deprecated\s+(.*)\Z/) { | ||
| 2253 | my $desc = $1; | ||
| 2254 | while (@doxygenlines) { | ||
| 2255 | my $subline = $doxygenlines[0]; | ||
| 2256 | $subline =~ s/\A\s*//; | ||
| 2257 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
| 2258 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
| 2259 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
| 2260 | $desc .= "\n"; | ||
| 2261 | } else { | ||
| 2262 | $desc .= " $subline"; | ||
| 2263 | } | ||
| 2264 | } | ||
| 2265 | $desc =~ s/[\s\n]+\Z//ms; | ||
| 2266 | $sections{'Deprecated'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
| 2267 | } elsif ($l =~ /\A\\since\s+(.*)\Z/) { | ||
| 2268 | my $desc = $1; | ||
| 2269 | while (@doxygenlines) { | ||
| 2270 | my $subline = $doxygenlines[0]; | ||
| 2271 | $subline =~ s/\A\s*//; | ||
| 2272 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
| 2273 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
| 2274 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
| 2275 | $desc .= "\n"; | ||
| 2276 | } else { | ||
| 2277 | $desc .= " $subline"; | ||
| 2278 | } | ||
| 2279 | } | ||
| 2280 | $desc =~ s/[\s\n]+\Z//ms; | ||
| 2281 | $sections{'Version'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
| 2282 | } elsif ($l =~ /\A\\threadsafety\s+(.*)\Z/) { | ||
| 2283 | my $desc = $1; | ||
| 2284 | while (@doxygenlines) { | ||
| 2285 | my $subline = $doxygenlines[0]; | ||
| 2286 | $subline =~ s/\A\s*//; | ||
| 2287 | last if $subline =~ /\A\\/; # some sort of doxygen command, assume we're past this thing. | ||
| 2288 | shift @doxygenlines; # dump this line from the array; we're using it. | ||
| 2289 | if ($subline eq '') { # empty line, make sure it keeps the newline char. | ||
| 2290 | $desc .= "\n"; | ||
| 2291 | } else { | ||
| 2292 | $desc .= " $subline"; | ||
| 2293 | } | ||
| 2294 | } | ||
| 2295 | $desc =~ s/[\s\n]+\Z//ms; | ||
| 2296 | $sections{'Thread Safety'} = wordwrap(wikify($wikitype, $desc)) . "\n"; | ||
| 2297 | $has_threadsafety = 1; | ||
| 2298 | } elsif ($l =~ /\A\\sa\s+(.*)\Z/) { | ||
| 2299 | my $sa = $1; | ||
| 2300 | $sa =~ s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
| 2301 | $sections{'See Also'} = '' if not defined $sections{'See Also'}; | ||
| 2302 | if ($wikitype eq 'mediawiki') { | ||
| 2303 | $sections{'See Also'} .= ":[[$sa]]\n"; | ||
| 2304 | } elsif ($wikitype eq 'md') { | ||
| 2305 | $sections{'See Also'} .= "- [$sa]($sa)\n"; | ||
| 2306 | } else { die("Expected wikitype '$wikitype'"); } | ||
| 2307 | } | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | if (($symtype == 1) && ($headersymsrettype{$sym} ne 'void') && !$has_returns) { | ||
| 2311 | print STDERR "WARNING: Function '$sym' has a non-void return type but no '\\returns' declaration\n"; | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | # !!! FIXME: uncomment this when we're trying to clean this up in the headers. | ||
| 2315 | #if (($symtype == 1) && !$has_threadsafety) { | ||
| 2316 | # print STDERR "WARNING: Function '$sym' doesn't have a '\\threadsafety' declaration\n"; | ||
| 2317 | #} | ||
| 2318 | |||
| 2319 | # Make sure %params is in the same order as the actual function signature and add C datatypes... | ||
| 2320 | my $params_has_c_datatype = 0; | ||
| 2321 | my @final_params = (); | ||
| 2322 | if (($symtype == 1) && (defined($headersymsparaminfo{$sym}))) { # is a function and we have param info for it... | ||
| 2323 | my $fnsigparams = $headersymsparaminfo{$sym}; | ||
| 2324 | for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { | ||
| 2325 | my $paramname = @$fnsigparams[$i]; | ||
| 2326 | my $paramdesc = $params{$paramname}; | ||
| 2327 | if (defined($paramdesc)) { | ||
| 2328 | push @final_params, $paramname; # name | ||
| 2329 | push @final_params, @$fnsigparams[$i+1]; # C datatype | ||
| 2330 | push @final_params, $paramdesc; # description | ||
| 2331 | $params_has_c_datatype = 1 if (defined(@$fnsigparams[$i+1])); | ||
| 2332 | } else { | ||
| 2333 | print STDERR "WARNING: Symbol '$sym' is missing a '\\param $paramname' declaration!\n"; | ||
| 2334 | } | ||
| 2335 | } | ||
| 2336 | } else { | ||
| 2337 | foreach (@paramsorder) { | ||
| 2338 | my $paramname = $_; | ||
| 2339 | my $paramdesc = $params{$paramname}; | ||
| 2340 | if (defined($paramdesc)) { | ||
| 2341 | push @final_params, $_; | ||
| 2342 | push @final_params, undef; | ||
| 2343 | push @final_params, $paramdesc; | ||
| 2344 | } | ||
| 2345 | } | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | my $hfiletext = $wikiheaderfiletext; | ||
| 2349 | $hfiletext =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
| 2350 | $sections{'Header File'} = "$hfiletext\n"; | ||
| 2351 | |||
| 2352 | # Make sure this ends with a double-newline. | ||
| 2353 | $sections{'See Also'} .= "\n" if defined $sections{'See Also'}; | ||
| 2354 | |||
| 2355 | if (0) { # !!! FIXME: this was a useful hack, but this needs to be generalized if we're going to do this always. | ||
| 2356 | # Plug in a \since section if one wasn't listed. | ||
| 2357 | if (not defined $sections{'Version'}) { | ||
| 2358 | my $symtypename; | ||
| 2359 | if ($symtype == 1) { | ||
| 2360 | $symtypename = 'function'; | ||
| 2361 | } elsif ($symtype == 2) { | ||
| 2362 | $symtypename = 'macro'; | ||
| 2363 | } elsif ($symtype == 3) { | ||
| 2364 | $symtypename = 'struct'; | ||
| 2365 | } elsif ($symtype == 4) { | ||
| 2366 | $symtypename = 'enum'; | ||
| 2367 | } elsif ($symtype == 5) { | ||
| 2368 | $symtypename = 'datatype'; | ||
| 2369 | } else { | ||
| 2370 | die("Unexpected symbol type $symtype!"); | ||
| 2371 | } | ||
| 2372 | my $str = "This $symtypename is available since SDL 3.0.0."; | ||
| 2373 | $sections{'Version'} = wordwrap(wikify($wikitype, $str)) . "\n"; | ||
| 2374 | } | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | # We can build the wiki table now that we have all the data. | ||
| 2378 | if (scalar(@final_params) > 0) { | ||
| 2379 | my $str = ''; | ||
| 2380 | if ($wikitype eq 'mediawiki') { | ||
| 2381 | while (scalar(@final_params) > 0) { | ||
| 2382 | my $arg = shift @final_params; | ||
| 2383 | my $c_datatype = shift @final_params; | ||
| 2384 | my $desc = wikify($wikitype, shift @final_params); | ||
| 2385 | $c_datatype = '' if not defined $c_datatype; | ||
| 2386 | $str .= ($str eq '') ? "{|\n" : "|-\n"; | ||
| 2387 | $str .= "|$c_datatype\n" if $params_has_c_datatype; | ||
| 2388 | $str .= "|'''$arg'''\n"; | ||
| 2389 | $str .= "|$desc\n"; | ||
| 2390 | } | ||
| 2391 | $str .= "|}\n"; | ||
| 2392 | } elsif ($wikitype eq 'md') { | ||
| 2393 | my $longest_arg = 0; | ||
| 2394 | my $longest_c_datatype = 0; | ||
| 2395 | my $longest_desc = 0; | ||
| 2396 | my $which = 0; | ||
| 2397 | foreach (@final_params) { | ||
| 2398 | if ($which == 0) { | ||
| 2399 | my $len = length($_); | ||
| 2400 | $longest_arg = $len if ($len > $longest_arg); | ||
| 2401 | $which = 1; | ||
| 2402 | } elsif ($which == 1) { | ||
| 2403 | if (defined($_)) { | ||
| 2404 | my $len = length(wikify($wikitype, $_)); | ||
| 2405 | $longest_c_datatype = $len if ($len > $longest_c_datatype); | ||
| 2406 | } | ||
| 2407 | $which = 2; | ||
| 2408 | } else { | ||
| 2409 | my $len = length(wikify($wikitype, $_)); | ||
| 2410 | $longest_desc = $len if ($len > $longest_desc); | ||
| 2411 | $which = 0; | ||
| 2412 | } | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | # Markdown tables are sort of obnoxious. | ||
| 2416 | my $c_datatype_cell; | ||
| 2417 | $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . (' ' x ($longest_c_datatype)) . ' ') : ''; | ||
| 2418 | $str .= $c_datatype_cell . '| ' . (' ' x ($longest_arg+4)) . ' | ' . (' ' x $longest_desc) . " |\n"; | ||
| 2419 | $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . ('-' x ($longest_c_datatype)) . ' ') : ''; | ||
| 2420 | $str .= $c_datatype_cell . '| ' . ('-' x ($longest_arg+4)) . ' | ' . ('-' x $longest_desc) . " |\n"; | ||
| 2421 | |||
| 2422 | while (@final_params) { | ||
| 2423 | my $arg = shift @final_params; | ||
| 2424 | my $c_datatype = shift @final_params; | ||
| 2425 | $c_datatype_cell = ''; | ||
| 2426 | if ($params_has_c_datatype) { | ||
| 2427 | $c_datatype = defined($c_datatype) ? wikify($wikitype, $c_datatype) : ''; | ||
| 2428 | $c_datatype_cell = ($longest_c_datatype > 0) ? ("| $c_datatype " . (' ' x ($longest_c_datatype - length($c_datatype)))) : ''; | ||
| 2429 | } | ||
| 2430 | my $desc = wikify($wikitype, shift @final_params); | ||
| 2431 | $str .= $c_datatype_cell . "| **$arg** " . (' ' x ($longest_arg - length($arg))) . "| $desc" . (' ' x ($longest_desc - length($desc))) . " |\n"; | ||
| 2432 | } | ||
| 2433 | } else { | ||
| 2434 | die("Unexpected wikitype!"); # should have checked this elsewhere. | ||
| 2435 | } | ||
| 2436 | $sections{'Function Parameters'} = $str; | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | my $path = "$wikipath/$sym.${wikitype}.tmp"; | ||
| 2440 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
| 2441 | |||
| 2442 | my $sectionsref = $wikisyms{$sym}; | ||
| 2443 | |||
| 2444 | foreach (@standard_wiki_sections) { | ||
| 2445 | # drop sections we either replaced or removed from the original wiki's contents. | ||
| 2446 | if (not defined $only_wiki_sections{$_}) { | ||
| 2447 | delete($$sectionsref{$_}); | ||
| 2448 | } | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | my $wikisectionorderref = $wikisectionorder{$sym}; | ||
| 2452 | |||
| 2453 | # Make sure there's a footer in the wiki that puts this function in CategoryAPI... | ||
| 2454 | if (not $$sectionsref{'[footer]'}) { | ||
| 2455 | $$sectionsref{'[footer]'} = ''; | ||
| 2456 | push @$wikisectionorderref, '[footer]'; | ||
| 2457 | } | ||
| 2458 | |||
| 2459 | # If changing format, convert things that otherwise are passed through unmolested. | ||
| 2460 | if (defined $changeformat) { | ||
| 2461 | if (($dewikify_mode eq 'md') and ($origwikitype eq 'mediawiki')) { | ||
| 2462 | $$sectionsref{'[footer]'} =~ s/\[\[(Category[a-zA-Z0-9_]+)\]\]/[$1]($1)/g; | ||
| 2463 | } elsif (($dewikify_mode eq 'mediawiki') and ($origwikitype eq 'md')) { | ||
| 2464 | $$sectionsref{'[footer]'} =~ s/\[(Category[a-zA-Z0-9_]+)\]\(.*?\)/[[$1]]/g; | ||
| 2465 | } | ||
| 2466 | |||
| 2467 | foreach (keys %only_wiki_sections) { | ||
| 2468 | my $sect = $_; | ||
| 2469 | if (defined $$sectionsref{$sect}) { | ||
| 2470 | $$sectionsref{$sect} = wikify($wikitype, dewikify($origwikitype, $$sectionsref{$sect})); | ||
| 2471 | } | ||
| 2472 | } | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | if ($symtype != -1) { # Don't do these in category documentation block | ||
| 2476 | my $footer = $$sectionsref{'[footer]'}; | ||
| 2477 | |||
| 2478 | my $symtypename; | ||
| 2479 | if ($symtype == 1) { | ||
| 2480 | $symtypename = 'Function'; | ||
| 2481 | } elsif ($symtype == 2) { | ||
| 2482 | $symtypename = 'Macro'; | ||
| 2483 | } elsif ($symtype == 3) { | ||
| 2484 | $symtypename = 'Struct'; | ||
| 2485 | } elsif ($symtype == 4) { | ||
| 2486 | $symtypename = 'Enum'; | ||
| 2487 | } elsif ($symtype == 5) { | ||
| 2488 | $symtypename = 'Datatype'; | ||
| 2489 | } else { | ||
| 2490 | die("Unexpected symbol type $symtype!"); | ||
| 2491 | } | ||
| 2492 | |||
| 2493 | my $symcategory = $headersymscategory{$sym}; | ||
| 2494 | if ($wikitype eq 'mediawiki') { | ||
| 2495 | $footer =~ s/\[\[CategoryAPI\]\],?\s*//g; | ||
| 2496 | $footer =~ s/\[\[CategoryAPI${symtypename}\]\],?\s*//g; | ||
| 2497 | $footer =~ s/\[\[Category${symcategory}\]\],?\s*//g if defined $symcategory; | ||
| 2498 | $footer = "[[CategoryAPI]], [[CategoryAPI$symtypename]]" . (defined $symcategory ? ", [[Category$symcategory]]" : '') . (($footer eq '') ? "\n" : ", $footer"); | ||
| 2499 | } elsif ($wikitype eq 'md') { | ||
| 2500 | $footer =~ s/\[CategoryAPI\]\(CategoryAPI\),?\s*//g; | ||
| 2501 | $footer =~ s/\[CategoryAPI${symtypename}\]\(CategoryAPI${symtypename}\),?\s*//g; | ||
| 2502 | $footer =~ s/\[Category${symcategory}\]\(Category${symcategory}\),?\s*//g if defined $symcategory; | ||
| 2503 | $footer = "[CategoryAPI](CategoryAPI), [CategoryAPI$symtypename](CategoryAPI$symtypename)" . (defined $symcategory ? ", [Category$symcategory](Category$symcategory)" : '') . (($footer eq '') ? '' : ', ') . $footer; | ||
| 2504 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
| 2505 | $$sectionsref{'[footer]'} = $footer; | ||
| 2506 | |||
| 2507 | if (defined $wikipreamble) { | ||
| 2508 | my $wikified_preamble = wikify($wikitype, $wikipreamble); | ||
| 2509 | if ($wikitype eq 'mediawiki') { | ||
| 2510 | print FH "====== $wikified_preamble ======\n"; | ||
| 2511 | } elsif ($wikitype eq 'md') { | ||
| 2512 | print FH "###### $wikified_preamble\n"; | ||
| 2513 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
| 2514 | } | ||
| 2515 | } | ||
| 2516 | |||
| 2517 | my $prevsectstr = ''; | ||
| 2518 | my @ordered_sections = (@standard_wiki_sections, defined $wikisectionorderref ? @$wikisectionorderref : ()); # this copies the arrays into one. | ||
| 2519 | foreach (@ordered_sections) { | ||
| 2520 | my $sect = $_; | ||
| 2521 | next if $sect eq '[start]'; | ||
| 2522 | next if (not defined $sections{$sect} and not defined $$sectionsref{$sect}); | ||
| 2523 | my $section = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; | ||
| 2524 | |||
| 2525 | if ($sect eq '[footer]') { | ||
| 2526 | # Make sure previous section ends with two newlines. | ||
| 2527 | if (substr($prevsectstr, -1) ne "\n") { | ||
| 2528 | print FH "\n\n"; | ||
| 2529 | } elsif (substr($prevsectstr, -2) ne "\n\n") { | ||
| 2530 | print FH "\n"; | ||
| 2531 | } | ||
| 2532 | print FH "----\n"; # It's the same in Markdown and MediaWiki. | ||
| 2533 | } elsif ($sect eq '[Brief]') { | ||
| 2534 | if ($wikitype eq 'mediawiki') { | ||
| 2535 | print FH "= $sym =\n\n"; | ||
| 2536 | } elsif ($wikitype eq 'md') { | ||
| 2537 | print FH "# $sym\n\n"; | ||
| 2538 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
| 2539 | } else { | ||
| 2540 | my $sectname = $sect; | ||
| 2541 | if ($sectname eq 'Function Parameters') { # We use this same table for different things depending on what we're documenting, so rename it now. | ||
| 2542 | if (($symtype == 1) || ($symtype == 5)) { # function (or typedef, in case it's a function pointer type). | ||
| 2543 | } elsif ($symtype == 2) { # macro | ||
| 2544 | $sectname = 'Macro Parameters'; | ||
| 2545 | } elsif ($symtype == 3) { # struct/union | ||
| 2546 | $sectname = 'Fields'; | ||
| 2547 | } elsif ($symtype == 4) { # enum | ||
| 2548 | $sectname = 'Values'; | ||
| 2549 | } else { | ||
| 2550 | die("Unexpected symtype $symtype"); | ||
| 2551 | } | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | if ($symtype != -1) { # Not for category documentation block | ||
| 2555 | if ($wikitype eq 'mediawiki') { | ||
| 2556 | print FH "\n== $sectname ==\n\n"; | ||
| 2557 | } elsif ($wikitype eq 'md') { | ||
| 2558 | print FH "\n## $sectname\n\n"; | ||
| 2559 | } else { die("Unexpected wikitype '$wikitype'"); } | ||
| 2560 | } | ||
| 2561 | } | ||
| 2562 | |||
| 2563 | my $sectstr = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; | ||
| 2564 | print FH $sectstr; | ||
| 2565 | |||
| 2566 | $prevsectstr = $sectstr; | ||
| 2567 | |||
| 2568 | # make sure these don't show up twice. | ||
| 2569 | delete($sections{$sect}); | ||
| 2570 | delete($$sectionsref{$sect}); | ||
| 2571 | } | ||
| 2572 | |||
| 2573 | print FH "\n\n"; | ||
| 2574 | close(FH); | ||
| 2575 | |||
| 2576 | if (defined $changeformat and ($origwikitype ne $wikitype)) { | ||
| 2577 | system("cd '$wikipath' ; git mv '$_.${origwikitype}' '$_.${wikitype}'"); | ||
| 2578 | unlink("$wikipath/$_.${origwikitype}"); | ||
| 2579 | } | ||
| 2580 | |||
| 2581 | rename($path, "$wikipath/$_.${wikitype}") or die("Can't rename '$path' to '$wikipath/$_.${wikitype}': $!\n"); | ||
| 2582 | } | ||
| 2583 | |||
| 2584 | # Write out simple redirector pages if they don't already exist. | ||
| 2585 | foreach (keys %referenceonly) { | ||
| 2586 | my $sym = $_; | ||
| 2587 | my $refersto = $referenceonly{$sym}; | ||
| 2588 | my $path = "$wikipath/$sym.md"; # we only do Markdown for these. | ||
| 2589 | next if (-f $path); # don't overwrite if it already exists. Delete the file if you need a rebuild! | ||
| 2590 | open(FH, '>', $path) or die("Can't open '$path': $!\n"); | ||
| 2591 | |||
| 2592 | if (defined $wikipreamble) { | ||
| 2593 | my $wikified_preamble = wikify('md', $wikipreamble); | ||
| 2594 | print FH "###### $wikified_preamble\n"; | ||
| 2595 | } | ||
| 2596 | |||
| 2597 | my $category = 'CategoryAPIMacro'; | ||
| 2598 | if ($headersymstype{$refersto} == 4) { | ||
| 2599 | $category = 'CategoryAPIEnumerators'; # NOT CategoryAPIEnum! | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | print FH "# $sym\n\nPlease refer to [$refersto]($refersto) for details.\n\n"; | ||
| 2603 | print FH "----\n"; | ||
| 2604 | print FH "[CategoryAPI](CategoryAPI), [$category]($category)\n\n"; | ||
| 2605 | |||
| 2606 | close(FH); | ||
| 2607 | } | ||
| 2608 | |||
| 2609 | # Write out Category pages... | ||
| 2610 | foreach (keys %headercategorydocs) { | ||
| 2611 | my $cat = $_; | ||
| 2612 | my $sym = $headercategorydocs{$cat}; # fake symbol | ||
| 2613 | my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. | ||
| 2614 | my $wikitype = defined($wikitypes{$sym}) ? $wikitypes{$sym} : 'md'; | ||
| 2615 | my $path = "$wikipath/Category$cat.$wikitype"; | ||
| 2616 | |||
| 2617 | $raw = wordwrap(wikify($wikitype, $raw)); | ||
| 2618 | |||
| 2619 | my $tmppath = "$path.tmp"; | ||
| 2620 | open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
| 2621 | print FH "$raw\n\n"; | ||
| 2622 | |||
| 2623 | if (! -f $path) { # Doesn't exist at all? Write out a template file. | ||
| 2624 | # If writing from scratch, it's always a Markdown file. | ||
| 2625 | die("Unexpected wikitype '$wikitype'!") if $wikitype ne 'md'; | ||
| 2626 | print FH <<__EOF__ | ||
| 2627 | |||
| 2628 | <!-- END CATEGORY DOCUMENTATION --> | ||
| 2629 | |||
| 2630 | ## Functions | ||
| 2631 | |||
| 2632 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
| 2633 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIFunction --> | ||
| 2634 | <!-- END CATEGORY LIST --> | ||
| 2635 | |||
| 2636 | ## Datatypes | ||
| 2637 | |||
| 2638 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
| 2639 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIDatatype --> | ||
| 2640 | <!-- END CATEGORY LIST --> | ||
| 2641 | |||
| 2642 | ## Structs | ||
| 2643 | |||
| 2644 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
| 2645 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIStruct --> | ||
| 2646 | <!-- END CATEGORY LIST --> | ||
| 2647 | |||
| 2648 | ## Enums | ||
| 2649 | |||
| 2650 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
| 2651 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIEnum --> | ||
| 2652 | <!-- END CATEGORY LIST --> | ||
| 2653 | |||
| 2654 | ## Macros | ||
| 2655 | |||
| 2656 | <!-- DO NOT HAND-EDIT CATEGORY LISTS, THEY ARE AUTOGENERATED AND WILL BE OVERWRITTEN, BASED ON TAGS IN INDIVIDUAL PAGE FOOTERS. EDIT THOSE INSTEAD. --> | ||
| 2657 | <!-- BEGIN CATEGORY LIST: Category$cat, CategoryAPIMacro --> | ||
| 2658 | <!-- END CATEGORY LIST --> | ||
| 2659 | |||
| 2660 | ---- | ||
| 2661 | [CategoryAPICategory](CategoryAPICategory) | ||
| 2662 | |||
| 2663 | __EOF__ | ||
| 2664 | ; | ||
| 2665 | } else { | ||
| 2666 | my $endstr = $wikisyms{$sym}->{'[footer]'}; | ||
| 2667 | if (defined($endstr)) { | ||
| 2668 | print FH $endstr; | ||
| 2669 | } | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | close(FH); | ||
| 2673 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | # Write out READMEs... | ||
| 2677 | if (defined $readmepath) { | ||
| 2678 | if ( -d $readmepath ) { | ||
| 2679 | mkdir($wikireadmepath); # just in case | ||
| 2680 | opendir(DH, $readmepath) or die("Can't opendir '$readmepath': $!\n"); | ||
| 2681 | while (my $d = readdir(DH)) { | ||
| 2682 | my $dent = $d; | ||
| 2683 | if ($dent =~ /\AREADME\-(.*?\.md)\Z/) { # we only bridge Markdown files here. | ||
| 2684 | my $wikifname = $1; | ||
| 2685 | next if $wikifname eq 'FrontPage.md'; | ||
| 2686 | filecopy("$readmepath/$dent", "$wikireadmepath/$wikifname", "\n"); | ||
| 2687 | } | ||
| 2688 | } | ||
| 2689 | closedir(DH); | ||
| 2690 | |||
| 2691 | my @pages = (); | ||
| 2692 | opendir(DH, $wikireadmepath) or die("Can't opendir '$wikireadmepath': $!\n"); | ||
| 2693 | while (my $d = readdir(DH)) { | ||
| 2694 | my $dent = $d; | ||
| 2695 | if ($dent =~ /\A(.*?)\.(mediawiki|md)\Z/) { | ||
| 2696 | my $wikiname = $1; | ||
| 2697 | next if $wikiname eq 'FrontPage'; | ||
| 2698 | push @pages, $wikiname; | ||
| 2699 | } | ||
| 2700 | } | ||
| 2701 | closedir(DH); | ||
| 2702 | |||
| 2703 | open(FH, '>', "$wikireadmepath/FrontPage.md") or die("Can't open '$wikireadmepath/FrontPage.md': $!\n"); | ||
| 2704 | print FH "# All READMEs available here\n\n"; | ||
| 2705 | foreach (sort @pages) { | ||
| 2706 | my $wikiname = $_; | ||
| 2707 | print FH "- [$wikiname]($wikiname)\n"; | ||
| 2708 | } | ||
| 2709 | close(FH); | ||
| 2710 | } | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | # Write out quick reference pages... | ||
| 2714 | if ($quickrefenabled) { | ||
| 2715 | generate_quickref(\%briefs, "$wikipath/QuickReference.md", 0); | ||
| 2716 | generate_quickref(\%briefs, "$wikipath/QuickReferenceNoUnicode.md", 1); | ||
| 2717 | } | ||
| 2718 | } elsif ($copy_direction == -2) { # --copy-to-manpages | ||
| 2719 | # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. | ||
| 2720 | |||
| 2721 | File::Path::make_path("$manpath/man3"); | ||
| 2722 | |||
| 2723 | $dewikify_mode = 'manpage'; | ||
| 2724 | $wordwrap_mode = 'manpage'; | ||
| 2725 | |||
| 2726 | my $introtxt = ''; | ||
| 2727 | if (0) { | ||
| 2728 | open(FH, '<', "$srcpath/LICENSE.txt") or die("Can't open '$srcpath/LICENSE.txt': $!\n"); | ||
| 2729 | while (<FH>) { | ||
| 2730 | chomp; | ||
| 2731 | $introtxt .= ".\\\" $_\n"; | ||
| 2732 | } | ||
| 2733 | close(FH); | ||
| 2734 | } | ||
| 2735 | |||
| 2736 | if (!$gitrev) { | ||
| 2737 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
| 2738 | chomp($gitrev); | ||
| 2739 | } | ||
| 2740 | |||
| 2741 | # !!! FIXME | ||
| 2742 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
| 2743 | my $majorver = 0; | ||
| 2744 | my $minorver = 0; | ||
| 2745 | my $microver = 0; | ||
| 2746 | while (<FH>) { | ||
| 2747 | chomp; | ||
| 2748 | if (/$versionmajorregex/) { | ||
| 2749 | $majorver = int($1); | ||
| 2750 | } elsif (/$versionminorregex/) { | ||
| 2751 | $minorver = int($1); | ||
| 2752 | } elsif (/$versionmicroregex/) { | ||
| 2753 | $microver = int($1); | ||
| 2754 | } | ||
| 2755 | } | ||
| 2756 | close(FH); | ||
| 2757 | my $fullversion = "$majorver.$minorver.$microver"; | ||
| 2758 | |||
| 2759 | foreach (keys %headersyms) { | ||
| 2760 | my $sym = $_; | ||
| 2761 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
| 2762 | next if $sym =~ /\A\[category documentation\]/; # not real symbols | ||
| 2763 | next if (defined $manpagesymbolfilterregex) && ($sym =~ /$manpagesymbolfilterregex/); | ||
| 2764 | my $symtype = $headersymstype{$sym}; | ||
| 2765 | my $wikitype = $wikitypes{$sym}; | ||
| 2766 | my $sectionsref = $wikisyms{$sym}; | ||
| 2767 | my $remarks = $sectionsref->{'Remarks'}; | ||
| 2768 | my $params = $sectionsref->{'Function Parameters'}; | ||
| 2769 | my $returns = $sectionsref->{'Return Value'}; | ||
| 2770 | my $version = $sectionsref->{'Version'}; | ||
| 2771 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
| 2772 | my $related = $sectionsref->{'See Also'}; | ||
| 2773 | my $examples = $sectionsref->{'Code Examples'}; | ||
| 2774 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
| 2775 | my $headerfile = $manpageheaderfiletext; | ||
| 2776 | $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
| 2777 | $headerfile .= "\n"; | ||
| 2778 | |||
| 2779 | my $mansection; | ||
| 2780 | my $mansectionname; | ||
| 2781 | if (($symtype == 1) || ($symtype == 2)) { # functions or macros | ||
| 2782 | $mansection = '3'; | ||
| 2783 | $mansectionname = 'FUNCTIONS'; | ||
| 2784 | } elsif (($symtype >= 3) && ($symtype <= 5)) { # struct/union/enum/typedef | ||
| 2785 | $mansection = '3type'; | ||
| 2786 | $mansectionname = 'DATATYPES'; | ||
| 2787 | } else { | ||
| 2788 | die("Unexpected symtype $symtype"); | ||
| 2789 | } | ||
| 2790 | |||
| 2791 | my $brief = $sectionsref->{'[Brief]'}; | ||
| 2792 | my $decl = $headerdecls{$sym}; | ||
| 2793 | my $str = ''; | ||
| 2794 | |||
| 2795 | # the "$brief" makes sure this is a copy of the string, which is doing some weird reference thing otherwise. | ||
| 2796 | $brief = defined $brief ? "$brief" : ''; | ||
| 2797 | $brief =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
| 2798 | $brief =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
| 2799 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
| 2800 | my @briefsplit = split /\n/, $brief; | ||
| 2801 | $brief = shift @briefsplit; | ||
| 2802 | $brief = dewikify($wikitype, $brief); | ||
| 2803 | |||
| 2804 | if (defined $remarks) { | ||
| 2805 | $remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks); | ||
| 2806 | } | ||
| 2807 | |||
| 2808 | $str .= $introtxt; | ||
| 2809 | |||
| 2810 | $str .= ".\\\" This manpage content is licensed under Creative Commons\n"; | ||
| 2811 | $str .= ".\\\" Attribution 4.0 International (CC BY 4.0)\n"; | ||
| 2812 | $str .= ".\\\" https://creativecommons.org/licenses/by/4.0/\n"; | ||
| 2813 | $str .= ".\\\" This manpage was generated from ${projectshortname}'s wiki page for $sym:\n"; | ||
| 2814 | $str .= ".\\\" $wikiurl/$sym\n"; | ||
| 2815 | $str .= ".\\\" Generated with SDL/build-scripts/wikiheaders.pl\n"; | ||
| 2816 | $str .= ".\\\" revision $gitrev\n" if $gitrev ne ''; | ||
| 2817 | $str .= ".\\\" Please report issues in this manpage's content at:\n"; | ||
| 2818 | $str .= ".\\\" $bugreporturl\n"; | ||
| 2819 | $str .= ".\\\" Please report issues in the generation of this manpage from the wiki at:\n"; | ||
| 2820 | $str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$sym\n"; | ||
| 2821 | $str .= ".\\\" $projectshortname can be found at $projecturl\n"; | ||
| 2822 | |||
| 2823 | # 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. | ||
| 2824 | # This wizadry is from https://web.archive.org/web/20060102165607/http://people.debian.org/~branden/talks/wtfm/wtfm.pdf | ||
| 2825 | $str .= ".de URL\n"; | ||
| 2826 | $str .= '\\$2 \(laURL: \\$1 \(ra\\$3' . "\n"; | ||
| 2827 | $str .= "..\n"; | ||
| 2828 | $str .= '.if \n[.g] .mso www.tmac' . "\n"; | ||
| 2829 | |||
| 2830 | $str .= ".TH $sym $mansection \"$projectshortname $fullversion\" \"$projectfullname\" \"$projectshortname$majorver $mansectionname\"\n"; | ||
| 2831 | $str .= ".SH NAME\n"; | ||
| 2832 | |||
| 2833 | $str .= "$sym"; | ||
| 2834 | $str .= " \\- $brief" if (defined $brief); | ||
| 2835 | $str .= "\n"; | ||
| 2836 | |||
| 2837 | if (defined $deprecated) { | ||
| 2838 | $str .= ".SH DEPRECATED\n"; | ||
| 2839 | $str .= dewikify($wikitype, $deprecated) . "\n"; | ||
| 2840 | } | ||
| 2841 | |||
| 2842 | if (defined $headerfile) { | ||
| 2843 | $str .= ".SH HEADER FILE\n"; | ||
| 2844 | $str .= dewikify($wikitype, $headerfile) . "\n"; | ||
| 2845 | } | ||
| 2846 | |||
| 2847 | $str .= ".SH SYNOPSIS\n"; | ||
| 2848 | $str .= ".nf\n"; | ||
| 2849 | $str .= ".B #include \\(dq$mainincludefname\\(dq\n"; | ||
| 2850 | $str .= ".PP\n"; | ||
| 2851 | |||
| 2852 | my @decllines = split /\n/, $decl; | ||
| 2853 | foreach (@decllines) { | ||
| 2854 | $str .= ".BI \"$_\n"; | ||
| 2855 | } | ||
| 2856 | $str .= ".fi\n"; | ||
| 2857 | |||
| 2858 | if (defined $remarks) { | ||
| 2859 | $str .= ".SH DESCRIPTION\n"; | ||
| 2860 | $str .= $remarks . "\n"; | ||
| 2861 | } | ||
| 2862 | |||
| 2863 | if (defined $params) { | ||
| 2864 | if (($symtype == 1) || ($symtype == 5)) { | ||
| 2865 | $str .= ".SH FUNCTION PARAMETERS\n"; | ||
| 2866 | } elsif ($symtype == 2) { # macro | ||
| 2867 | $str .= ".SH MACRO PARAMETERS\n"; | ||
| 2868 | } elsif ($symtype == 3) { # struct/union | ||
| 2869 | $str .= ".SH FIELDS\n"; | ||
| 2870 | } elsif ($symtype == 4) { # enum | ||
| 2871 | $str .= ".SH VALUES\n"; | ||
| 2872 | } else { | ||
| 2873 | die("Unexpected symtype $symtype"); | ||
| 2874 | } | ||
| 2875 | |||
| 2876 | my @lines = split /\n/, $params; | ||
| 2877 | if ($wikitype eq 'mediawiki') { | ||
| 2878 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
| 2879 | while (scalar(@lines) >= 3) { | ||
| 2880 | my $c_datatype = shift @lines; | ||
| 2881 | my $name = shift @lines; | ||
| 2882 | my $desc = shift @lines; | ||
| 2883 | my $terminator; # the '|-' or '|}' line. | ||
| 2884 | |||
| 2885 | 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. | ||
| 2886 | $terminator = $desc; | ||
| 2887 | $desc = $name; | ||
| 2888 | $name = $c_datatype; | ||
| 2889 | $c_datatype = ''; | ||
| 2890 | } else { | ||
| 2891 | $terminator = shift @lines; | ||
| 2892 | } | ||
| 2893 | |||
| 2894 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
| 2895 | $name =~ s/\A\|\s*//; | ||
| 2896 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 2897 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 2898 | $desc =~ s/\A\|\s*//; | ||
| 2899 | $desc = dewikify($wikitype, $desc); | ||
| 2900 | #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; | ||
| 2901 | |||
| 2902 | $str .= ".TP\n"; | ||
| 2903 | $str .= ".I $name\n"; | ||
| 2904 | $str .= "$desc\n"; | ||
| 2905 | } | ||
| 2906 | } elsif ($wikitype eq 'md') { | ||
| 2907 | my $l; | ||
| 2908 | $l = shift @lines; | ||
| 2909 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
| 2910 | $l = shift @lines; | ||
| 2911 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
| 2912 | while (scalar(@lines) >= 1) { | ||
| 2913 | $l = shift @lines; | ||
| 2914 | my $name; | ||
| 2915 | my $desc; | ||
| 2916 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 2917 | # c datatype is $1, but we don't care about it here. | ||
| 2918 | $name = $2; | ||
| 2919 | $desc = $3; | ||
| 2920 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 2921 | $name = $1; | ||
| 2922 | $desc = $2; | ||
| 2923 | } else { | ||
| 2924 | last; # we seem to have run out of table. | ||
| 2925 | } | ||
| 2926 | |||
| 2927 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 2928 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 2929 | $desc = dewikify($wikitype, $desc); | ||
| 2930 | |||
| 2931 | $str .= ".TP\n"; | ||
| 2932 | $str .= ".I $name\n"; | ||
| 2933 | $str .= "$desc\n"; | ||
| 2934 | } | ||
| 2935 | } else { | ||
| 2936 | die("write me"); | ||
| 2937 | } | ||
| 2938 | } | ||
| 2939 | |||
| 2940 | if (defined $returns) { | ||
| 2941 | $returns = dewikify($wikitype, $returns); | ||
| 2942 | $returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. | ||
| 2943 | $str .= ".SH RETURN VALUE\n"; | ||
| 2944 | $str .= "$returns\n"; | ||
| 2945 | } | ||
| 2946 | |||
| 2947 | if (defined $examples) { | ||
| 2948 | $str .= ".SH CODE EXAMPLES\n"; | ||
| 2949 | $dewikify_manpage_code_indent = 0; | ||
| 2950 | $str .= dewikify($wikitype, $examples) . "\n"; | ||
| 2951 | $dewikify_manpage_code_indent = 1; | ||
| 2952 | } | ||
| 2953 | |||
| 2954 | if (defined $threadsafety) { | ||
| 2955 | $str .= ".SH THREAD SAFETY\n"; | ||
| 2956 | $str .= dewikify($wikitype, $threadsafety) . "\n"; | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | if (defined $version) { | ||
| 2960 | $str .= ".SH AVAILABILITY\n"; | ||
| 2961 | $str .= dewikify($wikitype, $version) . "\n"; | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | if (defined $related) { | ||
| 2965 | $str .= ".SH SEE ALSO\n"; | ||
| 2966 | # !!! FIXME: lots of code duplication in all of these. | ||
| 2967 | my $v = dewikify($wikitype, $related); | ||
| 2968 | my @desclines = split /\n/, $v; | ||
| 2969 | my $nextstr = ''; | ||
| 2970 | foreach (@desclines) { | ||
| 2971 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
| 2972 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
| 2973 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
| 2974 | s/\A\*\s*\Z//; | ||
| 2975 | s/\A\/*//; | ||
| 2976 | s/\A\.BR\s+//; # dewikify added this, but we want to handle it. | ||
| 2977 | s/\A\.I\s+//; # dewikify added this, but we want to handle it. | ||
| 2978 | s/\A\s*[\:\*\-]\s*//; | ||
| 2979 | s/\A\s+//; | ||
| 2980 | s/\s+\Z//; | ||
| 2981 | next if $_ eq ''; | ||
| 2982 | my $seealso_symtype = $headersymstype{$_}; | ||
| 2983 | my $seealso_mansection = '3'; | ||
| 2984 | if (defined($seealso_symtype) && ($seealso_symtype >= 3) && ($seealso_symtype <= 5)) { # struct/union/enum/typedef | ||
| 2985 | $seealso_mansection = '3type'; | ||
| 2986 | } | ||
| 2987 | $str .= "$nextstr.BR $_ ($seealso_mansection)"; | ||
| 2988 | $nextstr = ",\n"; | ||
| 2989 | } | ||
| 2990 | $str .= "\n"; | ||
| 2991 | } | ||
| 2992 | |||
| 2993 | if (0) { | ||
| 2994 | $str .= ".SH COPYRIGHT\n"; | ||
| 2995 | $str .= "This manpage is licensed under\n"; | ||
| 2996 | $str .= ".UR https://creativecommons.org/licenses/by/4.0/\n"; | ||
| 2997 | $str .= "Creative Commons Attribution 4.0 International (CC BY 4.0)\n"; | ||
| 2998 | $str .= ".UE\n"; | ||
| 2999 | $str .= ".PP\n"; | ||
| 3000 | $str .= "This manpage was generated from\n"; | ||
| 3001 | $str .= ".UR $wikiurl/$sym\n"; | ||
| 3002 | $str .= "${projectshortname}'s wiki\n"; | ||
| 3003 | $str .= ".UE\n"; | ||
| 3004 | $str .= "using SDL/build-scripts/wikiheaders.pl"; | ||
| 3005 | $str .= " revision $gitrev" if $gitrev ne ''; | ||
| 3006 | $str .= ".\n"; | ||
| 3007 | $str .= "Please report issues in this manpage at\n"; | ||
| 3008 | $str .= ".UR $bugreporturl\n"; | ||
| 3009 | $str .= "our bugtracker!\n"; | ||
| 3010 | $str .= ".UE\n"; | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | my $path = "$manpath/man3/$_.$mansection"; | ||
| 3014 | my $tmppath = "$path.tmp"; | ||
| 3015 | open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); | ||
| 3016 | print FH $str; | ||
| 3017 | close(FH); | ||
| 3018 | rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); | ||
| 3019 | } | ||
| 3020 | |||
| 3021 | } elsif ($copy_direction == -4) { # --copy-to-latex | ||
| 3022 | # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. | ||
| 3023 | |||
| 3024 | 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"; | ||
| 3025 | |||
| 3026 | $dewikify_mode = 'LaTeX'; | ||
| 3027 | $wordwrap_mode = 'LaTeX'; | ||
| 3028 | |||
| 3029 | # !!! FIXME: code duplication with --copy-to-manpages section. | ||
| 3030 | |||
| 3031 | my $introtxt = ''; | ||
| 3032 | if (0) { | ||
| 3033 | open(FH, '<', "$srcpath/LICENSE.txt") or die("Can't open '$srcpath/LICENSE.txt': $!\n"); | ||
| 3034 | while (<FH>) { | ||
| 3035 | chomp; | ||
| 3036 | $introtxt .= ".\\\" $_\n"; | ||
| 3037 | } | ||
| 3038 | close(FH); | ||
| 3039 | } | ||
| 3040 | |||
| 3041 | if (!$gitrev) { | ||
| 3042 | $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; | ||
| 3043 | chomp($gitrev); | ||
| 3044 | } | ||
| 3045 | |||
| 3046 | # !!! FIXME | ||
| 3047 | open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); | ||
| 3048 | my $majorver = 0; | ||
| 3049 | my $minorver = 0; | ||
| 3050 | my $microver = 0; | ||
| 3051 | while (<FH>) { | ||
| 3052 | chomp; | ||
| 3053 | if (/$versionmajorregex/) { | ||
| 3054 | $majorver = int($1); | ||
| 3055 | } elsif (/$versionminorregex/) { | ||
| 3056 | $minorver = int($1); | ||
| 3057 | } elsif (/$versionmicroregex/) { | ||
| 3058 | $microver = int($1); | ||
| 3059 | } | ||
| 3060 | } | ||
| 3061 | close(FH); | ||
| 3062 | my $fullversion = "$majorver.$minorver.$microver"; | ||
| 3063 | |||
| 3064 | my $latex_fname = "$srcpath/$projectshortname.tex"; | ||
| 3065 | my $latex_tmpfname = "$latex_fname.tmp"; | ||
| 3066 | open(TEXFH, '>', "$latex_tmpfname") or die("Can't open '$latex_tmpfname' for writing: $!\n"); | ||
| 3067 | |||
| 3068 | print TEXFH <<__EOF__ | ||
| 3069 | \\documentclass{book} | ||
| 3070 | |||
| 3071 | \\usepackage{listings} | ||
| 3072 | \\usepackage{color} | ||
| 3073 | \\usepackage{hyperref} | ||
| 3074 | |||
| 3075 | \\definecolor{dkgreen}{rgb}{0,0.6,0} | ||
| 3076 | \\definecolor{gray}{rgb}{0.5,0.5,0.5} | ||
| 3077 | \\definecolor{mauve}{rgb}{0.58,0,0.82} | ||
| 3078 | |||
| 3079 | \\setcounter{secnumdepth}{0} | ||
| 3080 | |||
| 3081 | \\lstset{frame=tb, | ||
| 3082 | language=C, | ||
| 3083 | aboveskip=3mm, | ||
| 3084 | belowskip=3mm, | ||
| 3085 | showstringspaces=false, | ||
| 3086 | columns=flexible, | ||
| 3087 | basicstyle={\\small\\ttfamily}, | ||
| 3088 | numbers=none, | ||
| 3089 | numberstyle=\\tiny\\color{gray}, | ||
| 3090 | keywordstyle=\\color{blue}, | ||
| 3091 | commentstyle=\\color{dkgreen}, | ||
| 3092 | stringstyle=\\color{mauve}, | ||
| 3093 | breaklines=true, | ||
| 3094 | breakatwhitespace=true, | ||
| 3095 | tabsize=3 | ||
| 3096 | } | ||
| 3097 | |||
| 3098 | \\begin{document} | ||
| 3099 | \\frontmatter | ||
| 3100 | |||
| 3101 | \\title{$projectfullname $majorver.$minorver.$microver Reference Manual} | ||
| 3102 | \\author{The $projectshortname Developers} | ||
| 3103 | \\maketitle | ||
| 3104 | |||
| 3105 | \\mainmatter | ||
| 3106 | |||
| 3107 | __EOF__ | ||
| 3108 | ; | ||
| 3109 | |||
| 3110 | # !!! FIXME: Maybe put this in the book intro? print TEXFH $introtxt; | ||
| 3111 | |||
| 3112 | # Sort symbols by symbol type, then alphabetically. | ||
| 3113 | my @headersymskeys = sort { | ||
| 3114 | my $symtypea = $headersymstype{$a}; | ||
| 3115 | my $symtypeb = $headersymstype{$b}; | ||
| 3116 | $symtypea = 3 if ($symtypea > 3); | ||
| 3117 | $symtypeb = 3 if ($symtypeb > 3); | ||
| 3118 | my $rc = $symtypea <=> $symtypeb; | ||
| 3119 | if ($rc == 0) { | ||
| 3120 | $rc = lc($a) cmp lc($b); | ||
| 3121 | } | ||
| 3122 | return $rc; | ||
| 3123 | } keys %headersyms; | ||
| 3124 | |||
| 3125 | my $current_symtype = 0; | ||
| 3126 | my $current_chapter = ''; | ||
| 3127 | |||
| 3128 | foreach (@headersymskeys) { | ||
| 3129 | my $sym = $_; | ||
| 3130 | next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. | ||
| 3131 | next if $sym =~ /\A\[category documentation\]/; # not real symbols. | ||
| 3132 | my $symtype = $headersymstype{$sym}; | ||
| 3133 | my $wikitype = $wikitypes{$sym}; | ||
| 3134 | my $sectionsref = $wikisyms{$sym}; | ||
| 3135 | my $remarks = $sectionsref->{'Remarks'}; | ||
| 3136 | my $params = $sectionsref->{'Function Parameters'}; | ||
| 3137 | my $returns = $sectionsref->{'Return Value'}; | ||
| 3138 | my $version = $sectionsref->{'Version'}; | ||
| 3139 | my $threadsafety = $sectionsref->{'Thread Safety'}; | ||
| 3140 | my $related = $sectionsref->{'See Also'}; | ||
| 3141 | my $examples = $sectionsref->{'Code Examples'}; | ||
| 3142 | my $deprecated = $sectionsref->{'Deprecated'}; | ||
| 3143 | my $headerfile = $manpageheaderfiletext; | ||
| 3144 | $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; | ||
| 3145 | $headerfile .= "\n"; | ||
| 3146 | |||
| 3147 | my $brief = $sectionsref->{'[Brief]'}; | ||
| 3148 | my $decl = $headerdecls{$sym}; | ||
| 3149 | my $str = ''; | ||
| 3150 | |||
| 3151 | if ($current_symtype != $symtype) { | ||
| 3152 | my $newchapter = ''; | ||
| 3153 | if ($symtype == 1) { | ||
| 3154 | $newchapter = 'Functions'; | ||
| 3155 | } elsif ($symtype == 2) { | ||
| 3156 | $newchapter = 'Macros'; | ||
| 3157 | } else { | ||
| 3158 | $newchapter = 'Datatypes'; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | if ($current_chapter ne $newchapter) { | ||
| 3162 | $str .= "\n\n\\chapter{$projectshortname $newchapter}\n\n\\clearpage\n\n"; | ||
| 3163 | $current_chapter = $newchapter; | ||
| 3164 | } | ||
| 3165 | $current_symtype = $symtype; | ||
| 3166 | } | ||
| 3167 | |||
| 3168 | $brief = "$brief"; | ||
| 3169 | $brief =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; | ||
| 3170 | $brief =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; | ||
| 3171 | $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. | ||
| 3172 | my @briefsplit = split /\n/, $brief; | ||
| 3173 | $brief = shift @briefsplit; | ||
| 3174 | $brief = dewikify($wikitype, $brief); | ||
| 3175 | |||
| 3176 | if (defined $remarks) { | ||
| 3177 | $remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks); | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | my $escapedsym = escLaTeX($sym); | ||
| 3181 | $str .= "\\hypertarget{$sym}{%\n\\section{$escapedsym}\\label{$sym}}\n\n"; | ||
| 3182 | $str .= $brief if (defined $brief); | ||
| 3183 | $str .= "\n\n"; | ||
| 3184 | |||
| 3185 | if (defined $deprecated) { | ||
| 3186 | $str .= "\\subsection{Deprecated}\n\n"; | ||
| 3187 | $str .= dewikify($wikitype, $deprecated) . "\n"; | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | if (defined $headerfile) { | ||
| 3191 | $str .= "\\subsection{Header File}\n\n"; | ||
| 3192 | $str .= dewikify($wikitype, $headerfile) . "\n"; | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | $str .= "\\subsection{Syntax}\n\n"; | ||
| 3196 | $str .= "\\begin{lstlisting}\n$decl\n\\end{lstlisting}\n"; | ||
| 3197 | |||
| 3198 | if (defined $params) { | ||
| 3199 | if (($symtype == 1) || ($symtype == 5)) { | ||
| 3200 | $str .= "\\subsection{Function Parameters}\n\n"; | ||
| 3201 | } elsif ($symtype == 2) { # macro | ||
| 3202 | $str .= "\\subsection{Macro Parameters}\n\n"; | ||
| 3203 | } elsif ($symtype == 3) { # struct/union | ||
| 3204 | $str .= "\\subsection{Fields}\n\n"; | ||
| 3205 | } elsif ($symtype == 4) { # enum | ||
| 3206 | $str .= "\\subsection{Values}\n\n"; | ||
| 3207 | } else { | ||
| 3208 | die("Unexpected symtype $symtype"); | ||
| 3209 | } | ||
| 3210 | |||
| 3211 | $str .= "\\begin{center}\n"; | ||
| 3212 | $str .= " \\begin{tabular}{ | l | p{0.75\\textwidth} |}\n"; | ||
| 3213 | $str .= " \\hline\n"; | ||
| 3214 | |||
| 3215 | # !!! FIXME: this table parsing has gotten complicated and is pasted three times in this file; move it to a subroutine! | ||
| 3216 | my @lines = split /\n/, $params; | ||
| 3217 | if ($wikitype eq 'mediawiki') { | ||
| 3218 | die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start | ||
| 3219 | while (scalar(@lines) >= 3) { | ||
| 3220 | my $name = shift @lines; | ||
| 3221 | my $desc = shift @lines; | ||
| 3222 | my $terminator = shift @lines; # the '|-' or '|}' line. | ||
| 3223 | last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. | ||
| 3224 | $name =~ s/\A\|\s*//; | ||
| 3225 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 3226 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 3227 | $name = escLaTeX($name); | ||
| 3228 | $desc =~ s/\A\|\s*//; | ||
| 3229 | $desc = dewikify($wikitype, $desc); | ||
| 3230 | #print STDERR "FN: $sym NAME: $name DESC: $desc TERM: $terminator\n"; | ||
| 3231 | $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; | ||
| 3232 | } | ||
| 3233 | } elsif ($wikitype eq 'md') { | ||
| 3234 | my $l; | ||
| 3235 | $l = shift @lines; | ||
| 3236 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); | ||
| 3237 | $l = shift @lines; | ||
| 3238 | die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); | ||
| 3239 | while (scalar(@lines) >= 1) { | ||
| 3240 | $l = shift @lines; | ||
| 3241 | my $name; | ||
| 3242 | my $desc; | ||
| 3243 | if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 3244 | # c datatype is $1, but we don't care about it here. | ||
| 3245 | $name = $2; | ||
| 3246 | $desc = $3; | ||
| 3247 | } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { | ||
| 3248 | $name = $1; | ||
| 3249 | $desc = $2; | ||
| 3250 | } else { | ||
| 3251 | last; # we seem to have run out of table. | ||
| 3252 | } | ||
| 3253 | |||
| 3254 | $name =~ s/\A\*\*(.*?)\*\*/$1/; | ||
| 3255 | $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; | ||
| 3256 | $name = escLaTeX($name); | ||
| 3257 | $desc = dewikify($wikitype, $desc); | ||
| 3258 | $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; | ||
| 3259 | } | ||
| 3260 | } else { | ||
| 3261 | die("write me"); | ||
| 3262 | } | ||
| 3263 | |||
| 3264 | $str .= " \\end{tabular}\n"; | ||
| 3265 | $str .= "\\end{center}\n"; | ||
| 3266 | } | ||
| 3267 | |||
| 3268 | if (defined $returns) { | ||
| 3269 | $returns = dewikify($wikitype, $returns); | ||
| 3270 | $returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. | ||
| 3271 | $str .= "\\subsection{Return Value}\n\n"; | ||
| 3272 | $str .= "$returns\n"; | ||
| 3273 | } | ||
| 3274 | |||
| 3275 | if (defined $remarks) { | ||
| 3276 | $str .= "\\subsection{Remarks}\n\n"; | ||
| 3277 | $str .= $remarks . "\n"; | ||
| 3278 | } | ||
| 3279 | |||
| 3280 | if (defined $examples) { | ||
| 3281 | $str .= "\\subsection{Code Examples}\n\n"; | ||
| 3282 | $dewikify_manpage_code_indent = 0; | ||
| 3283 | $str .= dewikify($wikitype, $examples) . "\n"; | ||
| 3284 | $dewikify_manpage_code_indent = 1; | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | if (defined $threadsafety) { | ||
| 3288 | $str .= "\\subsection{Thread Safety}\n\n"; | ||
| 3289 | $str .= dewikify($wikitype, $threadsafety) . "\n"; | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | if (defined $version) { | ||
| 3293 | $str .= "\\subsection{Version}\n\n"; | ||
| 3294 | $str .= dewikify($wikitype, $version) . "\n"; | ||
| 3295 | } | ||
| 3296 | |||
| 3297 | if (defined $related) { | ||
| 3298 | $str .= "\\subsection{See Also}\n\n"; | ||
| 3299 | $str .= "\\begin{itemize}\n"; | ||
| 3300 | # !!! FIXME: lots of code duplication in all of these. | ||
| 3301 | my $v = dewikify($wikitype, $related); | ||
| 3302 | my @desclines = split /\n/, $v; | ||
| 3303 | my $nextstr = ''; | ||
| 3304 | foreach (@desclines) { | ||
| 3305 | s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" | ||
| 3306 | s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. | ||
| 3307 | s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. | ||
| 3308 | s/\A\*\s*\Z//; | ||
| 3309 | s/\A\s*\\item\s*//; | ||
| 3310 | s/\A\/*//; | ||
| 3311 | s/\A\s*[\:\*\-]\s*//; | ||
| 3312 | s/\A\s+//; | ||
| 3313 | s/\s+\Z//; | ||
| 3314 | next if $_ eq ''; | ||
| 3315 | next if $_ eq '\begin{itemize}'; | ||
| 3316 | next if $_ eq '\end{itemize}'; | ||
| 3317 | $str .= " \\item $_\n"; | ||
| 3318 | } | ||
| 3319 | $str .= "\\end{itemize}\n"; | ||
| 3320 | $str .= "\n"; | ||
| 3321 | } | ||
| 3322 | |||
| 3323 | # !!! FIXME: Maybe put copyright in the book intro? | ||
| 3324 | if (0) { | ||
| 3325 | $str .= ".SH COPYRIGHT\n"; | ||
| 3326 | $str .= "This manpage is licensed under\n"; | ||
| 3327 | $str .= ".UR https://creativecommons.org/licenses/by/4.0/\n"; | ||
| 3328 | $str .= "Creative Commons Attribution 4.0 International (CC BY 4.0)\n"; | ||
| 3329 | $str .= ".UE\n"; | ||
| 3330 | $str .= ".PP\n"; | ||
| 3331 | $str .= "This manpage was generated from\n"; | ||
| 3332 | $str .= ".UR $wikiurl/$sym\n"; | ||
| 3333 | $str .= "${projectshortname}'s wiki\n"; | ||
| 3334 | $str .= ".UE\n"; | ||
| 3335 | $str .= "using SDL/build-scripts/wikiheaders.pl"; | ||
| 3336 | $str .= " revision $gitrev" if $gitrev ne ''; | ||
| 3337 | $str .= ".\n"; | ||
| 3338 | $str .= "Please report issues in this manpage at\n"; | ||
| 3339 | $str .= ".UR $bugreporturl\n"; | ||
| 3340 | $str .= "our bugtracker!\n"; | ||
| 3341 | $str .= ".UE\n"; | ||
| 3342 | } | ||
| 3343 | |||
| 3344 | $str .= "\\clearpage\n\n"; | ||
| 3345 | |||
| 3346 | print TEXFH $str; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | print TEXFH "\\end{document}\n\n"; | ||
| 3350 | close(TEXFH); | ||
| 3351 | rename($latex_tmpfname, $latex_fname) or die("Can't rename '$latex_tmpfname' to '$latex_fname': $!\n"); | ||
| 3352 | |||
| 3353 | } elsif ($copy_direction == -3) { # --report-coverage-gaps | ||
| 3354 | foreach (@coverage_gap) { | ||
| 3355 | print("$_\n"); | ||
| 3356 | } | ||
| 3357 | } | ||
| 3358 | |||
| 3359 | # end of wikiheaders.pl ... | ||
| 3360 | |||
