Update: Translations from eints
[openttd-github.git] / src / script / api / doxygen_filter.awk
blobdaf8057425ebdde4867b2d8be912fbd004e6917d
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...
14 BEGIN {
15 cls = ""
16 api_selected = ""
17 cls_in_api = ""
18 cls_level = 0
19 skip_function_body = "false"
20 skip_function_par = 0
21 RS = "\r|\n"
22 apis = tolower(api)
23 if (apis == "gs") apis = "game"
27 # replace Script with AI/GS, except for ScriptErrorType
28 gsub(/Script/, api)
29 gsub(/AIErrorType/, "ScriptErrorType")
30 gsub(/GSErrorType/, "ScriptErrorType")
34 if (skip_function_body == "true") {
35 input = $0
36 gsub(/[^{]/, "", input)
37 skip_function_par += length(input)
38 if (skip_function_par > 0) {
39 input = $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
48 /@file/ {
49 gsub(/script/, apis)
52 /^([ ]*)\* @api/ {
53 if (api == "Script") {
54 api_selected = "true"
55 next
58 # By default, classes are not selected
59 if (cls_level == 0) api_selected = "false"
61 gsub("^([ ]*)", "", $0)
62 gsub("* @api ", "", $0)
64 if ($0 == "none") {
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)) {
71 api_selected = "true"
74 next
77 # Ignore forward declarations of classes
78 /^( *)class(.*);/ { next; }
79 # We only want to have public functions exported for now
80 /^( *)class/ {
81 if (cls_level == 0) {
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"
86 public = "false"
87 cls_param[0] = ""
88 cls_param[1] = 1
89 cls_param[2] = "x"
90 cls_in_api = api_selected
91 api_selected = ""
92 cls = $2
94 if (cls_in_api == "true") {
95 print comment_buffer
96 print
97 print "public:"
98 comment_buffer = ""
100 } else if (cls_level == 1) {
101 if (api_selected == "") api_selected = cls_in_api
103 if (api_selected == "true") {
104 print comment_buffer
105 print
106 print "public:"
107 comment_buffer = ""
109 api_selected = ""
110 } else {
111 print "Classes nested too deep" > "/dev/stderr"
112 exit 1
114 cls_level++
115 next
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; }
125 /^#else/ {
126 if (doxygen_skip == "next") {
127 doxygen_skip = "true";
128 } else {
129 doxygen_skip = "false";
131 next;
133 { if (doxygen_skip == "true") next }
135 /^#/ {
136 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 ")
149 # Store comments
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
168 /^( *)struct/ {
169 comments_so_far = comment_buffer
170 comment_buffer = ""
171 cls_level++
173 # Check if we want to publish this struct
174 if (api_selected == "") api_selected = cls_in_api
175 if (api_selected == "false") {
176 api_selected = ""
177 next
179 api_selected = ""
181 if (public == "false") next
183 print comments_so_far
184 print $0
186 next
189 # We need to make specialized conversions for enums
190 /^( *)enum/ {
191 comments_so_far = comment_buffer
192 comment_buffer = ""
193 cls_level++
195 # Check if we want to publish this enum
196 if (api_selected == "") api_selected = cls_in_api
197 if (api_selected == "false") {
198 api_selected = ""
199 next
201 api_selected = ""
203 if (public == "false") next
205 in_enum = "true"
207 print comments_so_far
208 print $0
210 next
213 # Maybe the end of the class, if so we can start with the Squirrel export pretty soon
214 /^[ ]*};/ {
215 comment_buffer = ""
216 cls_level--
217 if (cls_level != 0) {
218 if (in_enum == "true") print
219 in_enum = "false"
220 next
222 if (cls == "") {
223 next
225 if (cls_in_api == "true") print
226 next;
229 # Empty/white lines
230 /^([ ]*)$/ {
231 print $0
233 next
236 # Skip non-public functions
237 { if (public == "false") next }
239 # Add enums
241 if (in_enum == "true") {
242 print comment_buffer
243 comment_buffer = ""
244 gsub("=([^/]*),", ",", $0)
245 print $0
247 # Check if this a special error enum
248 if (match(enums[enum_size], ".*::ErrorMessages") != 0) {
249 # syntax:
250 # enum ErrorMessages {
251 # ERR_SOME_ERROR, // [STR_ITEM1, STR_ITEM2, ...]
254 ##TODO: don't print the STR_*
256 next
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") {
264 api_selected = ""
265 comment_buffer = ""
266 next
268 print comment_buffer
269 print $0
270 comment_buffer = ""
271 next
274 # Add a method to the list
275 /^.*\(.*\).*$/ {
276 if (cls_level != 1) next
277 if (!match($0, ";")) {
278 gsub(/ :$/, ";")
279 skip_function_body = "true"
281 if (match($0, "~")) {
282 if (api_selected != "") {
283 print "Destructor for '"cls"' has @api. Tag ignored." > "/dev/stderr"
284 api_selected = ""
286 next
289 # Check if we want to publish this function
290 if (api_selected == "") api_selected = cls_in_api
291 if (api_selected == "false") {
292 api_selected = ""
293 comment_buffer = ""
294 next
296 api_selected = ""
298 print comment_buffer
299 print $0
300 comment_buffer = ""
302 next