gendynapi.pl 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/usr/bin/perl -w
  2. # Simple DirectMedia Layer
  3. # Copyright (C) 1997-2024 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. # WHAT IS THIS?
  21. # When you add a public API to SDL, please run this script, make sure the
  22. # output looks sane (git diff, it adds to existing files), and commit it.
  23. # It keeps the dynamic API jump table operating correctly.
  24. # If you wanted this to be readable, you shouldn't have used perl.
  25. use warnings;
  26. use strict;
  27. use File::Basename;
  28. chdir(dirname(__FILE__) . '/../..');
  29. my $sdl_dynapi_procs_h = "src/dynapi/SDL_dynapi_procs.h";
  30. my $sdl_dynapi_overrides_h = "src/dynapi/SDL_dynapi_overrides.h";
  31. my $sdl2_exports = "src/dynapi/SDL2.exports";
  32. my %existing = ();
  33. if (-f $sdl_dynapi_procs_h) {
  34. open(SDL_DYNAPI_PROCS_H, '<', $sdl_dynapi_procs_h) or die("Can't open $sdl_dynapi_procs_h: $!\n");
  35. while (<SDL_DYNAPI_PROCS_H>) {
  36. if (/\ASDL_DYNAPI_PROC\(.*?,(.*?),/) {
  37. $existing{$1} = 1;
  38. }
  39. }
  40. close(SDL_DYNAPI_PROCS_H)
  41. }
  42. open(SDL_DYNAPI_PROCS_H, '>>', $sdl_dynapi_procs_h) or die("Can't open $sdl_dynapi_procs_h: $!\n");
  43. open(SDL_DYNAPI_OVERRIDES_H, '>>', $sdl_dynapi_overrides_h) or die("Can't open $sdl_dynapi_overrides_h: $!\n");
  44. open(SDL2_EXPORTS, '>>', $sdl2_exports) or die("Can't open $sdl2_exports: $!\n");
  45. # Ordered for reproducible builds
  46. opendir(HEADERS, 'include') or die("Can't open include dir: $!\n");
  47. my @entries = readdir(HEADERS);
  48. closedir(HEADERS);
  49. # Sort the entries
  50. @entries = sort @entries;
  51. foreach my $d (@entries) {
  52. next if not $d =~ /\.h\Z/;
  53. my $header = "include/$d";
  54. open(HEADER, '<', $header) or die("Can't open $header: $!\n");
  55. while (<HEADER>) {
  56. chomp;
  57. next if not /\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC/;
  58. my $decl = "$_ ";
  59. if (not $decl =~ /\)\s*;/) {
  60. while (<HEADER>) {
  61. chomp;
  62. s/\A\s+//;
  63. s/\s+\Z//;
  64. $decl .= "$_ ";
  65. last if /\)\s*;/;
  66. }
  67. }
  68. $decl =~ s/\s+\Z//;
  69. #print("DECL: [$decl]\n");
  70. if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC\s+(const\s+|)(unsigned\s+|)(.*?)\s*(\*?)\s*SDLCALL\s+(.*?)\s*\((.*?)\);/) {
  71. my $rc = "$2$3$4$5";
  72. my $fn = $6;
  73. next if $existing{$fn}; # already slotted into the jump table.
  74. my @params = split(',', $7);
  75. #print("rc == '$rc', fn == '$fn', params == '$params'\n");
  76. my $retstr = ($rc eq 'void') ? '' : 'return';
  77. my $paramstr = '(';
  78. my $argstr = '(';
  79. my $i = 0;
  80. foreach (@params) {
  81. my $str = $_;
  82. $str =~ s/\A\s+//;
  83. $str =~ s/\s+\Z//;
  84. #print("1PARAM: $str\n");
  85. if ($str eq 'void') {
  86. $paramstr .= 'void';
  87. } elsif ($str eq '...') {
  88. if ($i > 0) {
  89. $paramstr .= ', ';
  90. }
  91. $paramstr .= $str;
  92. } elsif ($str =~ /\A\s*((const\s+|)(unsigned\s+|)([a-zA-Z0-9_]*)\s*([\*\s]*))\s*(.*?)\Z/) {
  93. #print("PARSED: [$1], [$2], [$3], [$4], [$5]\n");
  94. my $type = $1;
  95. my $var = $6;
  96. $type =~ s/\A\s+//;
  97. $type =~ s/\s+\Z//;
  98. $var =~ s/\A\s+//;
  99. $var =~ s/\s+\Z//;
  100. $type =~ s/\s*\*\Z/*/g;
  101. $type =~ s/\s*(\*+)\Z/ $1/;
  102. #print("SPLIT: ($type, $var)\n");
  103. my $var_array_suffix = "";
  104. # parse array suffix
  105. if ($var =~ /\A.*(\[.*\])\Z/) {
  106. #print("PARSED ARRAY SUFFIX: [$1] of '$var'\n");
  107. $var_array_suffix = $1;
  108. }
  109. my $name = chr(ord('a') + $i);
  110. if ($i > 0) {
  111. $paramstr .= ', ';
  112. $argstr .= ',';
  113. }
  114. my $spc = ($type =~ /\*\Z/) ? '' : ' ';
  115. $paramstr .= "$type$spc$name$var_array_suffix";
  116. $argstr .= "$name";
  117. }
  118. $i++;
  119. }
  120. $paramstr = '(void' if ($i == 0); # Just to make this consistent.
  121. $paramstr .= ')';
  122. $argstr .= ')';
  123. print("NEW: $decl\n");
  124. print SDL_DYNAPI_PROCS_H "SDL_DYNAPI_PROC($rc,$fn,$paramstr,$argstr,$retstr)\n";
  125. print SDL_DYNAPI_OVERRIDES_H "#define $fn ${fn}_REAL\n";
  126. print SDL2_EXPORTS "++'_${fn}'.'SDL2.dll'.'${fn}'\n";
  127. } else {
  128. print("Failed to parse decl [$decl]!\n");
  129. }
  130. }
  131. close(HEADER);
  132. }
  133. close(SDL_DYNAPI_PROCS_H);
  134. close(SDL_DYNAPI_OVERRIDES_H);
  135. close(SDL2_EXPORTS);
  136. # vi: set ts=4 sw=4 expandtab: