1 # This file is part of OpenTTD.
2 # OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
3 # OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4 # See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
7 # Awk script to automatically generate the code needed
8 # to export the script APIs to Squirrel.
10 # Note that arrays are 1 based...
19 skip_function_body =
"false"
23 if (apis ==
"gs") apis =
"game"
27 # replace Script with AI/GS, except for ScriptErrorType
29 gsub(/AIErrorType
/, "ScriptErrorType")
30 gsub(/GSErrorType
/, "ScriptErrorType")
34 if (skip_function_body ==
"true") {
36 gsub(/[^
{]/, "", input
)
37 skip_function_par
+=
length(input
)
38 if (skip_function_par
> 0) {
40 gsub(/[^
}]/, "", input
)
41 skip_function_par
-=
length(input
)
42 if (skip_function_par ==
0) skip_function_body =
"false"
45 if (skip_function_body ==
"true") next
53 if (api ==
"Script") {
58 # By default, classes are not selected
59 if (cls_level ==
0) api_selected =
"false"
61 gsub("^([ ]*)", "", $
0)
62 gsub("* @api ", "", $
0)
65 api_selected =
"false"
66 } else if ($
0 ==
"-all") {
67 api_selected =
"false"
68 } else if (match($
0, "-" apis
)) {
69 api_selected =
"false"
70 } else if (match($
0, apis
)) {
77 # Ignore forward declarations of classes
78 /^
( *)class
(.
*);/ { next; }
79 # We only want to have public functions exported for now
82 if (api_selected ==
"") {
83 print "Class '"$
2"' has no @api. It won't be published to any API." > "/dev/stderr"
84 api_selected =
"false"
90 cls_in_api = api_selected
94 if (cls_in_api ==
"true") {
100 } else if (cls_level ==
1) {
101 if (api_selected ==
"") api_selected = cls_in_api
103 if (api_selected ==
"true") {
111 print "Classes nested too deep" > "/dev/stderr"
117 /^
( *)public
/ { if (cls_level ==
1) comment_buffer =
""; public =
"true"; next; }
118 /^
( *)protected
/ { if (cls_level ==
1) comment_buffer =
""; public =
"false"; next; }
119 /^
( *)private
/ { if (cls_level ==
1) comment_buffer =
""; public =
"false"; next; }
121 # Ignore special doxygen blocks
122 /^
#ifndef DOXYGEN_API/ { doxygen_skip = "true"; next; }
123 /^
#ifdef DOXYGEN_API/ { doxygen_skip = "next"; next; }
124 /^
#endif \/\* DOXYGEN_API \*\// { doxygen_skip = "false"; next; }
126 if (doxygen_skip ==
"next") {
127 doxygen_skip =
"true";
129 doxygen_skip =
"false";
133 { if (doxygen_skip ==
"true") next }
139 # Convert/unify type names
141 gsub(/\
<SQInteger\
>/, "int")
142 gsub(/\
<SquirrelTable\
>/, "table")
143 gsub(/\
<u?int
[0-9]*(_t
)?\
>/, "int")
144 gsub(/\
<HSQOBJECT\
>/, "object")
145 gsub(/std
::optional
<std
::string
>/, "string")
146 gsub(/(const
)?std
::string
*[*&]?
/, "string ")
150 /\
/\
*\
*.
*\
*\
// { comment_buffer = $
0; comment =
"false"; next; }
151 /\
/\
*.
*\
*\
// { comment_buffer =
""; comment =
"false"; next; }
152 /\
/\
*\
*/ { comment_buffer = $
0 "\n"; comment =
"true"; next; }
153 /\
/\
*/ { comment_buffer =
""; comment =
"false"; next; }
154 /\
*\
// { comment_buffer = comment_buffer $
0; comment =
"false"; next; }
156 if (comment ==
"true" && !
match($
0, /@api
/))
158 if (match($
0, /@game
/) && api
!= "GS") next;
159 if (match($
0, /@ai
/) && api
!= "AI") next;
160 gsub("@game ", "", $
0);
161 gsub("@ai ", "", $
0);
162 comment_buffer = comment_buffer $
0 "\n"; next;
167 # We need to make specialized conversions for structs
169 comments_so_far = comment_buffer
173 # Check if we want to publish this struct
174 if (api_selected ==
"") api_selected = cls_in_api
175 if (api_selected ==
"false") {
181 if (public ==
"false") next
183 print comments_so_far
189 # We need to make specialized conversions for enums
191 comments_so_far = comment_buffer
195 # Check if we want to publish this enum
196 if (api_selected ==
"") api_selected = cls_in_api
197 if (api_selected ==
"false") {
203 if (public ==
"false") next
207 print comments_so_far
213 # Maybe the end of the class, if so we can start with the Squirrel export pretty soon
217 if (cls_level
!= 0) {
218 if (in_enum ==
"true") print
225 if (cls_in_api ==
"true") print
236 # Skip non-public functions
237 { if (public ==
"false") next }
241 if (in_enum ==
"true") {
244 gsub("=([^/]*),", ",", $
0)
247 # Check if this a special error enum
248 if (match(enums
[enum_size
], ".*::ErrorMessages") != 0) {
250 # enum ErrorMessages {
251 # ERR_SOME_ERROR, // [STR_ITEM1, STR_ITEM2, ...]
254 ##TODO: don't print the STR_*
260 # Add a const (non-enum) value
261 /^
[ ]*static const \w
+ \w
+ =
[^
;]+;/ {
262 if (api_selected ==
"") api_selected = cls_in_api
263 if (api_selected ==
"false") {
274 # Add a method to the list
276 if (cls_level
!= 1) next
277 if (!
match($
0, ";")) {
279 skip_function_body =
"true"
281 if (match($
0, "~")) {
282 if (api_selected
!= "") {
283 print "Destructor for '"cls
"' has @api. Tag ignored." > "/dev/stderr"
289 # Check if we want to publish this function
290 if (api_selected ==
"") api_selected = cls_in_api
291 if (api_selected ==
"false") {