Files
@ r24096:cb8e221271af
Branch filter:
Location: cpp/openttd-patchpack/source/src/script/api/squirrel_export.vbs
r24096:cb8e221271af
29.0 KiB
text/plain
Change: Heading for 1.11 now
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 | Option Explicit
' 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 == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, " & Chr(34) & realname & Chr(34) & ", res, nullptr, 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 nullptr;"
file.WriteLine " }"
Else
file.WriteLine " template <> inline int Return<" & name & " *>(HSQUIRRELVM vm, " & name & " *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, " & Chr(34) & realname & Chr(34) & ", res, nullptr, DefSQDestructorCallback<" & name & ">, true); return 1; }"
End If
End Function
Function DumpFileheader(api, file)
Dim re
Set re = New RegExp
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
|