summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorglx <glx@openttd.org>2019-01-09 14:52:13 +0100
committerCharles Pigott <charlespigott@googlemail.com>2019-01-14 00:34:52 +0000
commit3f28e0cf53dc0c3de53a47874465be140f949949 (patch)
tree0f513d3e6f0437f7ab37927eeb198bbd117a3fd6
parent8e5a8d3ec3ec19e25f040b0b85b8f5764a735db1 (diff)
downloadopenttd-3f28e0cf53dc0c3de53a47874465be140f949949.tar.xz
Add: squirrel_export.vbs for users unable to run bash/gawk scripts
-rw-r--r--src/script/api/squirrel_export.vbs946
1 files changed, 946 insertions, 0 deletions
diff --git a/src/script/api/squirrel_export.vbs b/src/script/api/squirrel_export.vbs
new file mode 100644
index 000000000..a13869509
--- /dev/null
+++ b/src/script/api/squirrel_export.vbs
@@ -0,0 +1,946 @@
+Option Explicit
+
+' $Id$
+'
+' This file is part of OpenTTD.
+' 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.
+' 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.
+' 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/>.
+
+Dim FSO
+Dim enum_size, enums, enum_value_size, enum_value
+Dim enum_string_to_error_size, enum_string_to_error_mapping_string, enum_string_to_error_mapping_error
+Dim enum_error_to_string_size, enum_error_to_string_mapping, const_size, const_value
+Dim struct_size, structs, method_size, methods, static_method_size, static_methods
+Dim super_cls, cls, api_selected, cls_in_api, start_squirrel_define_on_next_line, has_fileheader, cls_level
+Dim apis, filename, doxygen_skip, squirrel_stuff, is_public, cls_param(2), comment, in_enum
+
+Set FSO = CreateObject("Scripting.FileSystemObject")
+
+Function CompareFiles(filename1, filename2)
+ Dim file, lines1, lines2
+
+ If Not FSO.FileExists(filename1) Then
+ CompareFiles = False
+ Exit Function
+ End If
+ Set file = FSO.OpenTextFile(filename1, 1)
+ If Not file.AtEndOfStream Then
+ lines1 = file.ReadAll
+ End IF
+ file.Close
+
+ If Not FSO.FileExists(filename2) Then
+ CompareFiles = False
+ Exit Function
+ End If
+ Set file = FSO.OpenTextFile(filename2, 1)
+ If Not file.AtEndOfStream Then
+ lines2 = file.ReadAll
+ End IF
+ file.Close
+
+ CompareFiles = (lines1 = lines2)
+End Function
+
+Function IsEmptyFile(filename)
+ Dim file
+ Set file = FSO.OpenTextFile(filename, 1)
+ IsEmptyFile = file.AtEndOfStream
+ file.Close
+End Function
+
+Function DumpClassTemplates(name, file)
+ Dim re, realname
+ Set re = New RegExp
+
+ re.Pattern = "^Script"
+ realname = re.Replace(name, "")
+
+ file.WriteLine " template <> inline " & name & " *GetParam(ForceType<" & name & " *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (" & name & " *)instance; }"
+ file.WriteLine " template <> inline " & name & " &GetParam(ForceType<" & name & " &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(" & name & " *)instance; }"
+ file.WriteLine " template <> inline const " & name & " *GetParam(ForceType<const " & name & " *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (" & name & " *)instance; }"
+ file.WriteLine " template <> inline const " & name & " &GetParam(ForceType<const " & name & " &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(" & name & " *)instance; }"
+ If name = "ScriptEvent" Then
+ file.WriteLine " template <> inline int Return<" & name & " *>(HSQUIRRELVM vm, " & name & " *res) { if (res == NULL) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, " & Chr(34) & realname & Chr(34) & ", res, NULL, DefSQDestructorCallback<" & name & ">, true); return 1; }"
+ ElseIf name = "ScriptText" Then
+ file.WriteLine ""
+ file.WriteLine " template <> inline Text *GetParam(ForceType<Text *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) {"
+ file.WriteLine " if (sq_gettype(vm, index) == OT_INSTANCE) {"
+ file.WriteLine " return GetParam(ForceType<ScriptText *>(), vm, index, ptr);"
+ file.WriteLine " }"
+ file.WriteLine " if (sq_gettype(vm, index) == OT_STRING) {"
+ file.WriteLine " return new RawText(GetParam(ForceType<const char *>(), vm, index, ptr));"
+ file.WriteLine " }"
+ file.WriteLine " return NULL;"
+ file.WriteLine " }"
+ Else
+ file.WriteLine " template <> inline int Return<" & name & " *>(HSQUIRRELVM vm, " & name & " *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, " & Chr(34) & realname & Chr(34) & ", res, NULL, DefSQDestructorCallback<" & name & ">, true); return 1; }"
+ End If
+End Function
+
+Function DumpFileheader(api, file)
+ Dim re
+ Set re = New RegExp
+ ' Break the Id tag, so SVN doesn't replace it
+ file.WriteLine "/* $I" & "d$ */"
+ file.WriteLine ""
+ file.WriteLine "/*"
+ file.WriteLine " * This file is part of OpenTTD."
+ file.WriteLine " * 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."
+ file.WriteLine " * 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."
+ file.WriteLine " * 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/>."
+ file.WriteLine " */"
+ file.WriteLine ""
+ file.WriteLine "/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */"
+ file.WriteLine ""
+ file.WriteLine "#include " & Chr(34) & "../" & filename & Chr(34)
+ If api <> "Template" Then
+ re.Pattern = "script_"
+ filename = re.Replace(filename, "template_")
+ file.WriteLine "#include " & Chr(34) & "../template/" & filename & ".sq" & Chr(34)
+ End If
+End Function
+
+Function ResetReader()
+ enum_size = 0
+ enums.RemoveAll
+ enum_value_size = 0
+ enum_value.RemoveAll
+ enum_string_to_error_size = 0
+ enum_string_to_error_mapping_string.RemoveAll
+ enum_string_to_error_mapping_error.RemoveAll
+ enum_error_to_string_size = 0
+ enum_error_to_string_mapping.RemoveAll
+ const_size = 0
+ const_value.RemoveAll
+ struct_size = 0
+ structs.RemoveAll
+ method_size = 0
+ methods.RemoveAll
+ static_method_size = 0
+ static_methods.RemoveAll
+ cls = ""
+ start_squirrel_define_on_next_line = False
+ cls_level = 0
+ cls_in_api = ""
+End Function
+
+Sub SquirrelExportParse(api, line, file)
+ Dim re
+ Set re = New RegExp
+
+ re.Pattern = "@file"
+ If re.Test(line) Then
+ filename = Split(line)(2)
+ re.Pattern = "^" & apis & "_"
+ filename = re.Replace(filename, "script_")
+ End If
+
+ ' Ignore special doxygen blocks
+ re.Pattern = "^#ifndef DOXYGEN_API"
+ If re.Test(line) Then
+ doxygen_skip = "next"
+ Exit Sub
+ End If
+ re.Pattern = "^#ifdef DOXYGEN_API"
+ If re.Test(line) Then
+ doxygen_skip = "true"
+ Exit Sub
+ End If
+ re.Pattern = "^#endif /\* DOXYGEN_API \*/"
+ If re.Test(line) Then
+ doxygen_skip = "false"
+ Exit Sub
+ End If
+ re.Pattern = "^#else"
+ If re.Test(line) Then
+ If doxygen_skip = "next" Then
+ doxygen_skip = "true"
+ Else
+ doxygen_skip = "false"
+ End If
+ Exit Sub
+ End If
+ If doxygen_skip = "true" Then Exit Sub
+
+ re.Pattern = "^([ ]*)\* @api"
+ If re.Test(line) Then
+ ' By default, classes are not selected
+ If cls_level = 0 Then api_selected = "false"
+
+ re.Pattern = "^([ ]*)"
+ line = re.Replace(line, "")
+ re.Pattern = "\* @api "
+ line = re.Replace(line, "")
+
+ If api = "Template" Then
+ api_selected = "true"
+ If line = "none" Or line = "-all" Then api_selected = "false"
+ Exit Sub
+ End If
+
+ If line = "none" Then
+ api_selected = "false"
+ ElseIf line = "-all" Then
+ api_selected = "false"
+ Else
+ re.Pattern = "-" & apis
+ If re.Test(line) Then
+ api_selected = "false"
+ Else
+ re.Pattern = apis
+ If re.Test(line) Then
+ api_selected = "true"
+ End If
+ End If
+ End If
+ Exit Sub
+ End If
+
+ ' Remove the old squirrel stuff
+ re.Pattern = "#ifdef DEFINE_SQUIRREL_CLASS"
+ If re.Test(line) Then
+ squirrel_stuff = True
+ Exit Sub
+ End If
+ re.Pattern = "^#endif /\* DEFINE_SQUIRREL_CLASS \*/"
+ If re.Test(line) Then
+ If squirrel_stuff Then squirrel_stuff = False
+ Exit Sub
+ End If
+ If squirrel_stuff Then Exit Sub
+
+ ' Ignore forward declarations of classes
+ re.Pattern = "^( *)class(.*);"
+ If re.Test(line) Then Exit Sub
+ ' We only want to have public functions exported for now
+ re.Pattern = "^( *)class"
+ If re.Test(line) Then
+ line = Split(line)
+ If cls_level = 0 Then
+ If api_selected = "" Then
+ WScript.Echo "Class '" & line(1) & "' has no @api. It won't be published to any API."
+ api_selected = "false"
+ End If
+ is_public = False
+ cls_param(0) = ""
+ cls_param(1) = 1
+ cls_param(2) = "x"
+ cls_in_api = api_selected
+ api_selected = ""
+ cls = line(1)
+ re.Pattern = "public|protected|private"
+ If UBound(line) > 2 Then
+ If re.Test(line(3)) Then
+ super_cls = line(4)
+ Else
+ super_cls = line(3)
+ End If
+ End If
+ ElseIf cls_level = 1 Then
+ If api_selected = "" Then api_selected = cls_in_api
+
+ If api_selected = "true" Then
+ struct_size = struct_size + 1
+ structs.Item(struct_size) = cls & "::" & line(1)
+ End If
+ api_selected = ""
+ End If
+ cls_level = cls_level + 1
+ Exit Sub
+ End If
+ re.Pattern = "^( *)public"
+ If re.Test(line) Then
+ If cls_level = 1 Then is_public = True
+ Exit Sub
+ End If
+ re.Pattern = "^( *)protected"
+ If re.Test(line) Then
+ If cls_level = 1 Then is_public = False
+ Exit Sub
+ End If
+ re.Pattern = "^( *)private"
+ If re.Test(line) Then
+ If cls_level = 1 Then is_public = False
+ Exit Sub
+ End If
+
+ ' Ignore the comments
+ re.Pattern = "^#"
+ If re.Test(line) Then Exit Sub
+ re.Pattern = "/\*.*\*/"
+ If re.Test(line) Then
+ comment = False
+ Exit Sub
+ End If
+ re.Pattern = "/\*"
+ If re.Test(line) Then
+ comment = True
+ Exit Sub
+ End If
+ re.Pattern = "\*/"
+ If re.Test(line) Then
+ comment = False
+ Exit Sub
+ End If
+ If comment Then Exit Sub
+
+ ' We need to make specialized conversions for structs
+ re.Pattern = "^( *)struct"
+ If re.Test(line) Then
+ cls_level = cls_level + 1
+
+ ' Check if we want to publish this struct
+ If api_selected = "" Then api_selected = cls_in_api
+ If api_selected = "false" Then
+ api_selected = ""
+ Exit Sub
+ End If
+ api_selected = ""
+
+ If Not is_public Then Exit Sub
+ If cls_level <> 1 Then Exit Sub
+
+ struct_size = struct_size + 1
+ structs.Item(struct_size) = cls & "::" & Split(line)(1)
+ Exit Sub
+ End If
+
+ ' We need to make specialized conversions for enums
+ re.Pattern = "^( *)enum"
+ If re.Test(line) Then
+ cls_level = cls_level + 1
+
+ ' Check if we want to publish this enum
+ If api_selected = "" Then api_selected = cls_in_api
+ If api_selected = "false" Then
+ api_selected = ""
+ Exit Sub
+ End If
+ api_selected = ""
+
+ If Not is_public Then Exit Sub
+
+ in_enum = True
+ enum_size = enum_size + 1
+ enums.Item(enum_size) = cls & "::" & Split(line)(1)
+ Exit Sub
+ End If
+
+ ' Maybe the end of the class, if so we can start with the Squirrel export pretty soon
+ re.Pattern = "};"
+ If re.Test(line) Then
+ cls_level = cls_level - 1
+ If cls_level <> 0 Then
+ in_enum = False
+ Exit Sub
+ End If
+
+ If cls = "" Then Exit Sub
+ start_squirrel_define_on_next_line = True
+ Exit Sub
+ End If
+
+ ' Empty/white lines. When we may do the Squirrel export, do that export.
+ re.Pattern = "^([ ]*)$"
+ If re.Test(line) Then
+ Dim namespace_opened, api_cls, api_super_cls, i, mlen, spaces
+
+ If Not start_squirrel_define_on_next_line Then Exit Sub
+
+ If cls_in_api <> "true" Then
+ ResetReader
+ Exit Sub
+ End If
+ If Not has_fileheader Then
+ DumpFileHeader api, file
+ has_fileheader = True
+ End If
+
+ is_public = False
+ namespace_opened = False
+
+ re.Pattern = "^Script"
+ api_cls = re.Replace(cls, api)
+ api_super_cls = re.Replace(super_cls, api)
+
+ file.WriteLine ""
+
+ If api = "Template" Then
+ ' First check whether we have enums to print
+ If enum_size <> 0 Then
+ If Not namespace_opened Then
+ file.WriteLine "namespace SQConvert {"
+ namespace_opened = True
+ End If
+ file.WriteLine " /* Allow enums to be used as Squirrel parameters */"
+ For i = 1 To enum_size
+ file.WriteLine " template <> inline " & enums.Item(i) & " GetParam(ForceType<" & enums.Item(i) & ">, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (" & enums.Item(i) & ")tmp; }"
+ file.WriteLine " template <> inline int Return<" & enums.Item(i) & ">(HSQUIRRELVM vm, " & enums.Item(i) & " res) { sq_pushinteger(vm, (int32)res); return 1; }"
+ Next
+ End If
+
+ ' Then check whether we have structs/classes to print
+ If struct_size <> 0 Then
+ If Not namespace_opened Then
+ file.WriteLine "namespace SQConvert {"
+ namespace_opened = True
+ End If
+ file.WriteLine " /* Allow inner classes/structs to be used as Squirrel parameters */"
+ For i = 1 To struct_size
+ DumpClassTemplates structs.Item(i), file
+ Next
+ End If
+
+ If Not namespace_opened Then
+ file.WriteLine "namespace SQConvert {"
+ namespace_opened = True
+ Else
+ file.WriteLine ""
+ End If
+ file.WriteLine " /* Allow " & cls & " to be used as Squirrel parameter */"
+ DumpClassTemplates cls, file
+
+ file.WriteLine "} // namespace SQConvert"
+
+ ResetReader
+ Exit Sub
+ End If
+
+ file.WriteLine ""
+ file.WriteLine "template <> const char *GetClassName<" & cls & ", ST_" & UCase(api) & ">() { return " & Chr(34) & api_cls & Chr(34) & "; }"
+ file.WriteLine ""
+
+ ' Then do the registration functions of the class.
+ file.WriteLine "void SQ" & api_cls & "_Register(Squirrel *engine)"
+ file.WriteLine "{"
+ file.WriteLine " DefSQClass<" & cls & ", ST_" & UCase(api) & "> SQ" & api_cls & "(" & Chr(34) & api_cls & Chr(34) & ");"
+ If super_cls = "Text" Or super_cls = "ScriptObject" Or super_cls = "AIAbstractiveList::Valuator" Then
+ file.WriteLine " SQ" & api_cls & ".PreRegister(engine);"
+ Else
+ file.WriteLine " SQ" & api_cls & ".PreRegister(engine, " & Chr(34) & api_super_cls & Chr(34) & ");"
+ End If
+ If super_cls <> "ScriptEvent" Then
+ If cls_param(2) = "v" Then
+ file.WriteLine " SQ" & api_cls & ".AddSQAdvancedConstructor(engine);"
+ Else
+ file.WriteLine " SQ" & api_cls & ".AddConstructor<void (" & cls & "::*)(" & cls_param(0) & "), " & cls_param(1) & ">(engine, " & Chr(34) & cls_param(2) & Chr(34) & ");"
+ End If
+ End If
+ file.WriteLine ""
+
+ ' Enum values
+ mlen = 0
+ For i = 1 To enum_value_size
+ If mlen <= Len(enum_value.Item(i)) Then mlen = Len(enum_value.Item(i))
+ Next
+ For i = 1 To enum_value_size
+ file.WriteLine " SQ" & api_cls & ".DefSQConst(engine, " & cls & "::" & enum_value.Item(i) & ", " & Space(mlen - Len(enum_value.Item(i))) & Chr(34) & enum_value.Item(i) & Chr(34) & ");"
+ Next
+ If enum_value_size <> 0 Then file.WriteLine ""
+
+ ' Const values
+ mlen = 0
+ For i = 1 To const_size
+ If mlen <= Len(const_value.Item(i)) Then mlen = Len(const_value.Item(i))
+ Next
+ For i = 1 To const_size
+ file.WriteLine " SQ" & api_cls & ".DefSQConst(engine, " & cls & "::" & const_value.Item(i) & ", " & Space(mlen - Len(const_value.Item(i))) & Chr(34) & const_value.Item(i) & Chr(34) & ");"
+ Next
+ If const_size <> 0 Then file.WriteLine ""
+
+ ' Mapping of OTTD strings to errors
+ mlen = 0
+ For i = 1 To enum_string_to_error_size
+ If mlen <= Len(enum_string_to_error_mapping_string.Item(i)) Then mlen = Len(enum_string_to_error_mapping_string.Item(i))
+ Next
+ For i = 1 To enum_string_to_error_size
+ file.WriteLine " ScriptError::RegisterErrorMap(" & enum_string_to_error_mapping_string.Item(i) & ", " & Space(mlen - Len(enum_string_to_error_mapping_string.Item(i))) & cls & "::" & enum_string_to_error_mapping_error.Item(i) & ");"
+ Next
+ If enum_string_to_error_size <> 0 Then file.WriteLine ""
+
+ ' Mapping of errors to human 'readable' strings.
+ mlen = 0
+ For i = 1 To enum_error_to_string_size
+ If mlen <= Len(enum_error_to_string_mapping.Item(i)) Then mlen = Len(enum_error_to_string_mapping.Item(i))
+ Next
+ For i = 1 To enum_error_to_string_size
+ file.WriteLine " ScriptError::RegisterErrorMapString(" & cls & "::" & enum_error_to_string_mapping.Item(i) & ", " & Space(mlen - Len(enum_error_to_string_mapping.Item(i))) & Chr(34) & enum_error_to_string_mapping.Item(i) & Chr(34) & ");"
+ Next
+ If enum_error_to_string_size <> 0 Then file.WriteLine ""
+
+ ' Static methods
+ mlen = 0
+ For i = 1 To static_method_size
+ If mlen <= Len(static_methods.Item(i)(0)) Then mlen = Len(static_methods.Item(i)(0))
+ Next
+ For i = 1 To static_method_size
+ If static_methods.Item(i)(2) = "v" Then
+ spaces = mlen - Len(static_methods.Item(i)(0)) - 8
+ If spaces < 0 Then spaces = 0
+ file.WriteLine " SQ" & api_cls & ".DefSQAdvancedStaticMethod(engine, &" & cls & "::" & static_methods.Item(i)(0) & ", " & Space(spaces) & Chr(34) & static_methods.Item(i)(0) & Chr(34) & ");"
+ Else
+ file.WriteLine " SQ" & api_cls & ".DefSQStaticMethod(engine, &" & cls & "::" & static_methods.Item(i)(0) & ", " & Space(mlen - Len(static_methods.Item(i)(0))) & Chr(34) & static_methods.Item(i)(0) & Chr(34) & ", " & Space(mlen - Len(static_methods.Item(i)(0))) & static_methods.Item(i)(1) & ", " & Chr(34) & static_methods.Item(i)(2) & Chr(34) & ");"
+ End If
+ Next
+ If static_method_size <> 0 Then file.WriteLine ""
+
+ ' Non-static methods
+ mlen = 0
+ For i = 1 To method_size
+ If mlen <= Len(methods.Item(i)(0)) Then mlen = Len(methods.Item(i)(0))
+ Next
+ For i = 1 To method_size
+ If methods.Item(i)(2) = "v" Then
+ spaces = mlen - Len(methods.Item(i)(0)) - 8
+ If spaces < 0 Then spaces = 0
+ file.WriteLine " SQ" & api_cls & ".DefSQAdvancedMethod(engine, &" & cls & "::" & methods.Item(i)(0) & ", " & Space(spaces) & Chr(34) & methods.Item(i)(0) & Chr(34) & ");"
+ Else
+ file.WriteLine " SQ" & api_cls & ".DefSQMethod(engine, &" & cls & "::" & methods.Item(i)(0) & ", " & Space(mlen - Len(methods.Item(i)(0))) & Chr(34) & methods.Item(i)(0) & Chr(34) & ", " & Space(mlen - Len(methods.Item(i)(0))) & methods.Item(i)(1) & ", " & Chr(34) & methods.Item(i)(2) & Chr(34) & ");"
+ End If
+ Next
+ If method_size <> 0 Then file.WriteLine ""
+
+ file.WriteLine " SQ" & api_cls & ".PostRegister(engine);"
+ file.WriteLine "}"
+
+ ResetReader
+
+ Exit Sub
+ End If
+
+ ' Skip non-public functions
+ If Not is_public Then Exit Sub
+
+ ' Add enums
+ If in_enum Then
+ enum_value_size = enum_value_size + 1
+ re.Pattern = "[, ]"
+ re.Global = True
+ enum_value.Item(enum_value_size) = re.Replace(split(line)(0), "")
+
+ ' Check if this a special error enum
+ re.Pattern = ".*::ErrorMessages"
+ If re.Test(enums.Item(enum_size)) Then
+ ' syntax:
+ ' enum ErrorMessages {
+ ' ERR_SOME_ERROR, // [STR_ITEM1, STR_ITEM2, ...]
+ ' }
+
+ ' Set the mappings
+ re.Pattern = "\[.*\]"
+ If re.Test(line) Then
+ Dim mappings
+ mappings = re.Execute(line)(0).Value
+ re.Pattern = "[\[ \]]"
+ mappings = re.Replace(mappings, "")
+
+ mappings = Split(mappings, ",")
+ For i = LBound(mappings) To UBound(mappings)
+ enum_string_to_error_size = enum_string_to_error_size + 1
+ enum_string_to_error_mapping_string.Item(enum_string_to_error_size) = mappings(i)
+ enum_string_to_error_mapping_error.Item(enum_string_to_error_size) = enum_value.Item(enum_value_size)
+ Next
+
+ enum_error_to_string_size = enum_error_to_string_size + 1
+ enum_error_to_string_mapping.Item(enum_error_to_string_size) = enum_value.Item(enum_value_size)
+ End If
+ End If
+ re.Global = False
+ Exit Sub
+ End If
+
+ ' Add a const (non-enum) value
+ re.Pattern = "^[ ]*static const \w+ \w+ = -?\(?\w*\)?\w+;"
+ If re.Test(line) Then
+ const_size = const_size + 1
+ const_value.Item(const_size) = Split(line)(3)
+ Exit Sub
+ End If
+
+ ' Add a method to the list
+ re.Pattern = "^.*\(.*\).*$"
+ If re.Test(line) Then
+ Dim is_static, param_s, func, funcname, params, types
+ If cls_level <> 1 Then Exit Sub
+ re.Pattern = "~"
+ If re.Test(line) Then
+ If api_selected <> "" Then
+ WScript.Echo "Destructor for '" & cls & "' has @api. Tag ignored."
+ api_selected = ""
+ End If
+ Exit Sub
+ End If
+
+ re.Pattern = "static"
+ is_static = re.Test(line)
+ re.Pattern = "\bvirtual\b"
+ line = re.Replace(line, "")
+ re.Pattern = "\bstatic\b"
+ line = re.Replace(line, "")
+ re.Pattern = "\bconst\b"
+ line = re.Replace(line, "")
+ re.Pattern = "{.*"
+ line = re.Replace(line, "")
+ param_s = line
+ re.Pattern = "\*"
+ line = re.Replace(line, "")
+ re.Pattern = "\(.*"
+ line = re.Replace(line, "")
+ re.Pattern = "^[ ]*"
+ line = re.Replace(line, "")
+
+ re.Pattern = ".*\("
+ param_s = re.Replace(param_s, "")
+ re.Pattern = "\).*"
+ param_s = re.Replace(param_s, "")
+
+ func = Split(line)
+ If UBound(func) > 0 Then
+ funcname = func(1)
+ Else
+ funcname = ""
+ End If
+ If func(0) = cls And funcname = "" Then
+ If api_selected <> "" Then
+ WScript.Echo "Constructor for '" & cls & "' has @api. Tag ignored."
+ api_selected = ""
+ End If
+ cls_param(0) = param_s
+ If param_s = "" Then Exit Sub
+ ElseIf funcname = "" Then
+ Exit Sub
+ End If
+
+ params = Split(param_s, ",")
+ If is_static Then
+ types = "."
+ Else
+ types = "x"
+ End If
+ For i = LBound(params) To UBound(params)
+ Do ' null loop for logic short-circuit
+ re.Pattern = "^[ ]*"
+ params(i) = re.Replace(params(i), "")
+ re.Pattern = "\*|&"
+ If re.Test(params(i)) Then
+ re.Pattern = "^char"
+ If re.test(params(i)) Then
+ ' Many types can be converted to string, so use '.', not 's'. (handled by our glue code)
+ types = types & "."
+ Exit Do
+ End If
+ re.Pattern = "^void"
+ If re.test(params(i)) Then
+ types = types & "p"
+ Exit Do
+ End If
+ re.Pattern = "^Array"
+ If re.test(params(i)) Then
+ types = types & "a"
+ Exit Do
+ End If
+ re.Pattern = "^struct Array"
+ If re.test(params(i)) Then
+ types = types & "a"
+ Exit Do
+ End If
+ re.Pattern = "^Text"
+ If re.test(params(i)) Then
+ types = types & "."
+ Exit Do
+ End If
+ types = types & "x"
+ Exit Do
+ End If
+ re.Pattern = "^bool"
+ If re.Test(params(i)) Then
+ types = types & "b"
+ Exit Do
+ End If
+ re.Pattern = "^HSQUIRRELVM"
+ If re.Test(params(i)) Then
+ types = "v"
+ Exit Do
+ End If
+ types = types & "i"
+ Loop While False ' end of null loop
+ Next
+ i = i + 1
+
+ ' Check if we want to publish this function
+ If api_selected = "" Then api_selected = cls_in_api
+ If api_selected = "false" Then
+ api_selected = ""
+ Exit Sub
+ End If
+ api_selected = ""
+
+ If func(0) = cls And funcname = "" Then
+ cls_param(1) = i
+ cls_param(2) = types
+ Exit Sub
+ End If
+ If Left(funcname, 1) = "_" And types <> "v" Then Exit Sub
+ If is_static Then
+ static_method_size = static_method_size + 1
+ static_methods.Item(static_method_size) = Array(funcname, i, types)
+ Exit Sub
+ End If
+ method_size = method_size + 1
+ methods.Item(method_size) = Array(funcname, i, types)
+ Exit Sub
+ End If
+End Sub
+
+Sub SquirrelExport(api, srcfilename, dstfilename)
+ Dim src, dst, line
+ Set src = FSO.OpenTextFile(srcfilename, 1)
+ Set dst = FSO.OpenTextFile(dstfilename, 2, True)
+
+ enum_size = 0
+ Set enums = CreateObject("Scripting.Dictionary")
+ enum_value_size = 0
+ Set enum_value = CreateObject("Scripting.Dictionary")
+ enum_string_to_error_size = 0
+ Set enum_string_to_error_mapping_string = CreateObject("Scripting.Dictionary")
+ Set enum_string_to_error_mapping_error = CreateObject("Scripting.Dictionary")
+ enum_error_to_string_size = 0
+ Set enum_error_to_string_mapping = CreateObject("Scripting.Dictionary")
+ const_size = 0
+ Set const_value = CreateObject("Scripting.Dictionary")
+ struct_size = 0
+ Set structs = CreateObject("Scripting.Dictionary")
+ method_size = 0
+ Set methods = CreateObject("Scripting.Dictionary")
+ static_method_size = 0
+ Set static_methods = CreateObject("Scripting.Dictionary")
+ super_cls = ""
+ cls = ""
+ api_selected = ""
+ cls_in_api = ""
+ start_squirrel_define_on_next_line = False
+ has_fileheader = False
+ cls_level = 0
+ apis = LCase(api)
+ If apis = "gs" Then apis = "game"
+
+ While Not src.AtEndOfStream
+ line = src.ReadLine
+ SquirrelExportParse api, line, dst
+ Wend
+
+ src.Close
+ dst.Close
+End Sub
+
+Function SortDict(dict)
+ Set SortDict = CreateObject("Scripting.Dictionary")
+ While dict.Count <> 0
+ Dim first, i
+ first = ""
+ For Each i in dict
+ If first = "" Or StrComp(first, i) = 1 Then first = i
+ Next
+ SortDict.Add first, first
+ dict.Remove(first)
+ Wend
+End Function
+
+Sub ExportInstanceParse(apiuc, apilc, line, file)
+ Dim re, fname, f, files, r, regs
+ Set re = New RegExp
+
+ re.Pattern = "\.hpp\.sq"
+ If re.Test(line) Then
+ re.Pattern = "template"
+ If re.Test(line) Then
+ file.WriteLine line
+ End If
+ Exit Sub
+ End If
+
+ re.Pattern = "SQ" & apiuc & "Controller_Register"
+ If re.Test(line) Then
+ file.WriteLine line
+ Exit Sub
+ End If
+
+ re.Pattern = "SQ" & apiuc & ".*_Register"
+ If re.Test(line) Then Exit Sub
+
+ re.Pattern = "Note: this line is a marker in squirrel_export.sh. Do not change!"
+ If re.Test(line) Then
+ file.WriteLine line
+ Set files = CreateObject("Scripting.Dictionary")
+ For Each fname In FSO.GetFolder(".").Files
+ Do ' null loop for logic short-circuit
+ re.Pattern = ".*_(.*)\.hpp\.sq"
+ If Not re.Test(fname) Then Exit Do
+ Set f = FSO.OpenTextFile(fname, 1)
+ fname = fname.Name
+ re.Pattern = "^void SQ" & apiuc & ".*Register\(Squirrel \*engine\)$"
+ While Not f.AtEndOfStream
+ If re.Test(f.ReadLine) And Not files.Exists(fname) Then
+ files.Add fname, fname
+ End If
+ Wend
+ f.Close
+ Loop While False ' end of null loop
+ Next
+ Set files = SortDict(files)
+ For Each f in files
+ file.WriteLine "#include " & Chr(34) & "../script/api/" & apilc & "/" & f & Chr(34)
+ Next
+ Exit Sub
+ End If
+
+ re.Pattern = "/\* Register all classes \*/"
+ If re.Test(line) Then
+ file.WriteLine line
+ Set regs = CreateObject("Scripting.Dictionary")
+ ' List needs to be registered with squirrel before all List subclasses
+ file.WriteLine " SQ" & apiuc & "List_Register(this->engine);"
+ For Each fname In FSO.GetFolder(".").Files
+ Do ' null loop for logic short-circuit
+ re.Pattern = ".*_(.*)\.hpp\.sq"
+ If Not re.Test(fname) Then Exit Do
+ Set f = FSO.OpenTextFile(fname, 1)
+ While Not f.AtEndOfStream
+ Do ' null loop for logic short-circuit
+ r = f.ReadLine
+ re.Pattern = "^void SQ" & apiuc & ".*Register\(Squirrel \*engine\)$"
+ If Not re.Test(r) Then Exit Do
+ re.Pattern = "SQ" & apiuc & "List_Register"
+ If re.Test(r) Then Exit Do
+ re.Pattern = "^.*void "
+ r = re.Replace(r, "")
+ re.Pattern = "Squirrel \*"
+ r = re.Replace(r, "this->")
+ re.Pattern = "$"
+ r = re.Replace(r, ";")
+ re.Pattern = "_Register"
+ r = re.Replace(r, "0000Register")
+ If Not regs.Exists(r) Then regs.Add r, r
+ Loop While False ' end of null loop
+ Wend
+ f.Close
+ Loop While False ' end of null loop
+ Next
+ Set regs = SortDict(regs)
+ re.Pattern = "0000Register"
+ For Each r in regs.Items
+ r = re.Replace(r, "_Register")
+ If r <> "SQ" & apiuc & "Controller_Register(this->engine);" Then file.WriteLine " " & r
+ Next
+ Exit Sub
+ End If
+
+ file.WriteLine line
+End Sub
+
+Sub ExportInstance(apiuc, apilc, srcfilename, dstfilename)
+ Dim src, dst, line
+ Set src = FSO.OpenTextFile(srcfilename, 1)
+ Set dst = FSO.OpenTextFile(dstfilename, 2, True)
+
+ While Not src.AtEndOfStream
+ line = src.ReadLine
+ ExportInstanceParse apiuc, apilc, line, dst
+ Wend
+
+ src.Close
+ dst.Close
+End Sub
+
+' Recursive entry point
+Sub Main
+ Dim WSH, scriptdir, apilc, re, api, apiuc, f, bf
+ Set WSH = CreateObject("WScript.Shell")
+ Set re = New RegExp
+
+ ' This must be called from within a src/???/api directory.
+ scriptdir = FSO.GetParentFolderName(WScript.ScriptFullName)
+ apilc = WSH.CurrentDirectory
+ re.Pattern = "\\api"
+ apilc = re.Replace(apilc, "")
+ re.Pattern = ".*\\"
+ apilc = re.Replace(apilc, "")
+
+ ' Check if we are in the root directory of the API, as then we generate all APIs
+ If apilc = "script" Then
+ For Each api In FSO.GetFolder(".").SubFolders
+ WScript.Echo "Generating for API '" & api.Name & "' ..."
+ WSH.CurrentDirectory = api
+ Main
+ Next
+ WScript.Quit 0
+ End If
+
+ Select Case apilc
+ Case "template" apiuc = "Template"
+ Case "ai" apiuc = "AI"
+ Case "game" apiuc = "GS"
+ Case Else
+ WScript.Echo "Unknown API type."
+ Exit Sub
+ End Select
+
+ For Each f in FSO.GetFolder("..").Files
+ Do ' null loop for logic short-circuit
+ re.Pattern = ".*\.hpp"
+ If Not re.Test(f) Then Exit Do
+ ' ScriptController has custom code, and should not be generated
+ If f.Name = "script_controller.hpp" Then Exit Do
+ re.Pattern = "script_"
+ bf = re.Replace(f.name, apilc & "_")
+ SquirrelExport apiuc, f, bf & ".tmp"
+ If IsEmptyFile(bf & ".tmp") Then
+ If FSO.FileExists(bf & ".sq") Then
+ WScript.Echo "Deleted: " & bf & ".sq"
+ FSO.DeleteFile bf & ".sq"
+ End If
+ FSO.DeleteFile bf & ".tmp"
+ ElseIf Not FSO.FileExists(bf & ".sq") Or Not CompareFiles(bf & ".sq", bf & ".tmp") Then
+ If FSO.FileExists(bf & ".sq") Then FSO.DeleteFile bf & ".sq"
+ FSO.MoveFile bf & ".tmp", bf & ".sq"
+ WScript.Echo "Updated: " & bf & ".sq"
+ Else
+ FSO.DeleteFile bf & ".tmp"
+ End If
+ Loop While False ' end of null loop
+ Next
+
+ ' Remove .hpp.sq if .hpp doesn't exist anymore
+ For Each f in FSO.GetFolder(".").Files
+ Do ' null loop for logic short-circuit
+ re.Pattern = ".*\.hpp\.sq"
+ If Not re.Test(f) Then Exit Do
+ f = f.Name
+ re.Pattern = "\.hpp\.sq$"
+ f = re.Replace(f, ".hpp")
+ re.Pattern = apilc & "_"
+ f = re.Replace(f, "script_")
+ If Not FSO.FileExists("..\" & f) Then
+ WScript.Echo "Deleted: " & f & ".sq"
+ 'FSO.DeleteFile f & ".sq"
+ End If
+ Loop While False ' end of null loop
+ Next
+
+ If apilc = "template" Then Exit Sub
+
+ ' Add stuff to ${apilc}_instance.cpp
+ f = "..\..\..\" & apilc & "\" & apilc & "_instance.cpp"
+ ExportInstance apiuc, apilc, f, f & ".tmp"
+ If Not FSO.FileExists(f) Or Not CompareFiles(f, f & ".tmp") Then
+ If FSO.FileExists(f) Then FSO.DeleteFile f
+ FSO.MoveFile f & ".tmp", f
+ WScript.Echo "Updated: " & f
+ Else
+ FSO.DeleteFile f & ".tmp"
+ End If
+End Sub
+
+Main