Browse Source

initial commit, project adapted from the original commercial GRLD files, cleaned-up for simpler open source distribution, license switched to MIT

pull/1/merge
Youen Toupin 8 years ago
parent
commit
953450fbcd
  1. 7
      .gitignore
  2. 66
      bin/win_x86/lua5.1/lfs-README.txt
  3. BIN
      bin/win_x86/lua5.1/lfs.dll
  4. BIN
      bin/win_x86/lua5.1/lua5.1.dll
  5. BIN
      bin/win_x86/lua5.1/lua51.dll
  6. BIN
      bin/win_x86/lua5.1/lua51.exe
  7. BIN
      bin/win_x86/lua5.1/socket.dll
  8. BIN
      bin/win_x86/lua5.1/wx.dll
  9. 674
      bin/win_x86/lua5.1/wxlua-gpl.txt
  10. 165
      bin/win_x86/lua5.1/wxlua-lgpl.txt
  11. 53
      bin/win_x86/lua5.1/wxlua-licence.txt
  12. BIN
      bin/win_x86/lua5.1/wxmsw28_gl_vc_custom.dll
  13. BIN
      bin/win_x86/lua5.1/wxmsw28_stc_vc_custom.dll
  14. BIN
      bin/win_x86/lua5.1/wxmsw28_vc_custom.dll
  15. BIN
      bin/win_x86/lua5.2/lua52.dll
  16. BIN
      bin/win_x86/lua5.2/lua52.exe
  17. BIN
      bin/win_x86/lua5.2/luac52.exe
  18. BIN
      bin/win_x86/lua5.2/socket.dll
  19. 24
      client/3rdparty/lua5.2/include/lapi.h
  20. 212
      client/3rdparty/lua5.2/include/lauxlib.h
  21. 309
      client/3rdparty/lua5.2/include/llimits.h
  22. 57
      client/3rdparty/lua5.2/include/lmem.h
  23. 607
      client/3rdparty/lua5.2/include/lobject.h
  24. 228
      client/3rdparty/lua5.2/include/lstate.h
  25. 57
      client/3rdparty/lua5.2/include/ltm.h
  26. 444
      client/3rdparty/lua5.2/include/lua.h
  27. 9
      client/3rdparty/lua5.2/include/lua.hpp
  28. 553
      client/3rdparty/lua5.2/include/luaconf.h
  29. 55
      client/3rdparty/lua5.2/include/lualib.h
  30. 65
      client/3rdparty/lua5.2/include/lzio.h
  31. BIN
      client/3rdparty/lua5.2/liblua52.a
  32. 53
      client/build/embed.lua.bat
  33. 554
      client/src/grldc.c
  34. 51
      client/src/grldc.h
  35. 808
      client/src/grldc_ldb.lua
  36. 1404
      client/src/grldc_ldb.lua.c
  37. 376
      client/src/grldc_net.lua.c
  38. 190
      client/src/grldc_socket.lua.c
  39. 121
      client/src/grldc_utilities.lua.c
  40. 15
      client/src/luajit_ex.c
  41. 12
      client/src/luajit_ex.h
  42. 28
      client/visual/grldc.sln
  43. 243
      client/visual/grldc.vcxproj
  44. 83
      client/visual/grldc.vcxproj.filters
  45. 109
      doc/generate-toc.lua
  46. 206
      doc/index.html
  47. BIN
      doc/screenshots/client-connected-thumb.png
  48. BIN
      doc/screenshots/client-connected.png
  49. BIN
      doc/screenshots/source-popup-thumb.png
  50. BIN
      doc/screenshots/source-popup.png
  51. BIN
      doc/screenshots/startup-thumb.png
  52. BIN
      doc/screenshots/startup.png
  53. BIN
      doc/screenshots/watch-thumb.png
  54. BIN
      doc/screenshots/watch.png
  55. BIN
      doc/screenshots/wine-thumb.png
  56. BIN
      doc/screenshots/wine.png
  57. 3
      samples/demo01/demo01.bat
  58. 64
      samples/demo01/demo01.lua
  59. 2
      server/GRLD-server.bat
  60. 302
      server/grld/engine.lua
  61. 64
      server/wxLdb/coxpcall-LICENSE.html
  62. 81
      server/wxLdb/coxpcall.lua
  63. 46
      server/wxLdb/mainthread.lua
  64. 11
      server/wxLdb/ui/about.lua
  65. 76
      server/wxLdb/ui/callstack.lua
  66. 236
      server/wxLdb/ui/editor.lua
  67. 12
      server/wxLdb/ui/id.lua
  68. 211
      server/wxLdb/ui/luaExplorer.lua
  69. 364
      server/wxLdb/ui/mainWindow.lua
  70. 84
      server/wxLdb/ui/notification.lua
  71. 154
      server/wxLdb/ui/promptMountPath.lua
  72. 136
      server/wxLdb/ui/sourcePage.lua
  73. 135
      server/wxLdb/ui/threads.lua
  74. 59
      server/wxLdb/wxLdb.lua
  75. 810
      server/wxLdb/wxLdbController.lua
  76. 219
      shared/grldc/net.lua
  77. 85
      shared/grldc/socket.lua
  78. 70
      shared/grldc/utilities.lua

7
.gitignore vendored

@ -0,0 +1,7 @@
/client/.vs/grldc/v14/*.suo
/client/visual/.vs/grldc/v14/*.suo
/client/visual/Debug
/client/visual/*.sdf
/client/visual/*.user
/client/visual/x64/Debug
/server/clients

66
bin/win_x86/lua5.1/lfs-README.txt

@ -0,0 +1,66 @@
LuaFileSystem - File System Library for Lua
Copyright 2003 Kepler Project
http://www.keplerproject.org/luafilesystem
Description
-----------
LuaFileSystem is a Lua library developed to complement the set of functions
related to file systems offered by the standard Lua distribution.
LuaFileSystem offers a portable way to access the underlying directory structure and file attributes.
LuaFileSystem is free software and uses the same license as Lua 5.1
LuaRocks Installation
---------------------
luarocks install luafilesystem
Documentation
-------------
Please check the documentation at doc/us/ for more information.
History
-------
Version 1.5.0 [20/Oct/2009]
* added explicit next and close methods to second return value of lfs.dir (the directory object), for explicit iteration or explicit closing.
* added directory locking via lfs.lock_dir function (see the manual).
Version 1.4.2 [03/Feb/2009]
* fixed bug [#13198] lfs.attributes(filename, 'size') overflow on files > 2 Gb again (bug report and patch by KUBO Takehiro).
* fixed bug [#39794] Compile error on Solaris 10 (bug report and patch by Aaron B).
* fixed compilation problems with Borland C.
Version 1.4.1 [07/May/2008]
* documentation review
* fixed Windows compilation issues
* fixed bug in the Windows tests (patch by Shmuel Zeigerman)
* fixed bug [#2185] lfs.attributes(filename, 'size') overflow on files > 2 Gb
Version 1.4.0 [13/Feb/2008]
* added function lfs.setmode (works only in Windows systems).
* lfs.attributes raises an error if attribute does not exist
Version 1.3.0 [26/Oct/2007]
* added function lfs.symlinkattributes (works only in non Windows systems).
Version 1.2.1 [08/May/2007]
* compatible only with Lua 5.1 (Lua 5.0 support was dropped)
Version 1.2 [15/Mar/2006]
* added optional argument to lfs.attributes
* added function lfs.rmdir
* bug correction on lfs.dir
Version 1.1 [30/May/2005]
* added function lfs.touch.
Version 1.0 [21/Jan/2005]
Version 1.0 Beta [10/Nov/2004]

BIN
bin/win_x86/lua5.1/lfs.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/lua5.1.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/lua51.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/lua51.exe

Binary file not shown.

BIN
bin/win_x86/lua5.1/socket.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/wx.dll

Binary file not shown.

674
bin/win_x86/lua5.1/wxlua-gpl.txt

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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, either version 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

165
bin/win_x86/lua5.1/wxlua-lgpl.txt

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

53
bin/win_x86/lua5.1/wxlua-licence.txt

@ -0,0 +1,53 @@
wxWindows Library Licence, Version 3
====================================
Copyright (c) 1998 Julian Smart, Robert Roebling et al
Everyone is permitted to copy and distribute verbatim copies
of this licence document, but changing it is not allowed.
WXWINDOWS LIBRARY LICENCE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public Licence as published by
the Free Software Foundation; either version 2 of the Licence, or (at
your option) any later version.
This library 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 Library
General Public Licence for more details.
You should have received a copy of the GNU Library General Public Licence
along with this software, usually in a file named COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA.
EXCEPTION NOTICE
1. As a special exception, the copyright holders of this library give
permission for additional uses of the text contained in this release of
the library as licenced under the wxWindows Library Licence, applying
either version 3 of the Licence, or (at your option) any later version of
the Licence as published by the copyright holders of version 3 of the
Licence document.
2. The exception is that you may use, copy, link, modify and distribute
under the user's own terms, binary object code versions of works based
on the Library.
3. If you copy code from files distributed under the terms of the GNU
General Public Licence or the GNU Library General Public Licence into a
copy of this library, as this licence permits, the exception does not
apply to the code that you add in this way. To avoid misleading anyone as
to the status of such modified files, you must delete this exception
notice from such code and/or adjust the licensing conditions notice
accordingly.
4. If you write modifications of your own for this library, it is your
choice whether to permit this exception to apply to your modifications.
If you do not wish that, you must delete the exception notice from such
code and/or adjust the licensing conditions notice accordingly.

BIN
bin/win_x86/lua5.1/wxmsw28_gl_vc_custom.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/wxmsw28_stc_vc_custom.dll

Binary file not shown.

BIN
bin/win_x86/lua5.1/wxmsw28_vc_custom.dll

Binary file not shown.

BIN
bin/win_x86/lua5.2/lua52.dll

Binary file not shown.

BIN
bin/win_x86/lua5.2/lua52.exe

Binary file not shown.

BIN
bin/win_x86/lua5.2/luac52.exe

Binary file not shown.

BIN
bin/win_x86/lua5.2/socket.dll

Binary file not shown.

24
client/3rdparty/lua5.2/include/lapi.h vendored

@ -0,0 +1,24 @@
/*
** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "llimits.h"
#include "lstate.h"
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
#endif

212
client/3rdparty/lua5.2/include/lauxlib.h vendored

@ -0,0 +1,212 @@
/*
** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
/* extra error code for `luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver);
#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM)
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
const char *def, size_t *l);
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def);
LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg);
LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg,
lua_Unsigned def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
const char *const lst[]);
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* pre-defined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API int (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef struct luaL_Buffer {
char *b; /* buffer address */
size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L;
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
} luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,s) ((B)->n += (s))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */
/*
** {======================================================
** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
/* }====================================================== */
/* compatibility with old module system */
#if defined(LUA_COMPAT_MODULE)
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
int sizehint);
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
#endif
#endif

309
client/3rdparty/lua5.2/include/llimits.h vendored

@ -0,0 +1,309 @@
/*
** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
#ifndef llimits_h
#define llimits_h
#include <limits.h>
#include <stddef.h>
#include "lua.h"
typedef unsigned LUA_INT32 lu_int32;
typedef LUAI_UMEM lu_mem;
typedef LUAI_MEM l_mem;
/* chars used as small naturals (so that `char' is reserved for characters) */
typedef unsigned char lu_byte;
#define MAX_SIZET ((size_t)(~(size_t)0)-2)
#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2))
#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
/*
** conversion of pointer to integer
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
*/
#define IntPoint(p) ((unsigned int)(lu_mem)(p))
/* type to ensure maximum alignment */
#if !defined(LUAI_USER_ALIGNMENT_T)
#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
#endif
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
/* result of a `usual argument conversion' over lua_Number */
typedef LUAI_UACNUMBER l_uacNumber;
/* internal assertions for in-house debugging */
#if defined(lua_assert)
#define check_exp(c,e) (lua_assert(c), (e))
/* to avoid problems with conditions too long */
#define lua_longassert(c) { if (!(c)) lua_assert(0); }
#else
#define lua_assert(c) ((void)0)
#define check_exp(c,e) (e)
#define lua_longassert(c) ((void)0)
#endif
/*
** assertion for checking API calls
*/
#if !defined(luai_apicheck)
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(L,e) assert(e)
#else
#define luai_apicheck(L,e) lua_assert(e)
#endif
#endif
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
#endif
#define cast(t, exp) ((t)(exp))
#define cast_byte(i) cast(lu_byte, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
#define cast_uchar(i) cast(unsigned char, (i))
/*
** non-return type
*/
#if defined(__GNUC__)
#define l_noret void __attribute__((noreturn))
#elif defined(_MSC_VER)
#define l_noret void __declspec(noreturn)
#else
#define l_noret void
#endif
/*
** maximum depth for nested C calls and syntactical nested non-terminals
** in a program. (Value must fit in an unsigned short int.)
*/
#if !defined(LUAI_MAXCCALLS)
#define LUAI_MAXCCALLS 200
#endif
/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in an unsigned char.)
*/
#define MAXUPVAL UCHAR_MAX
/*
** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
typedef lu_int32 Instruction;
/* maximum stack for a Lua function */
#define MAXSTACK 250
/* minimum size for the string table (must be power of 2) */
#if !defined(MINSTRTABSIZE)
#define MINSTRTABSIZE 32
#endif
/* minimum size for string buffer */
#if !defined(LUA_MINBUFFER)
#define LUA_MINBUFFER 32
#endif
#if !defined(lua_lock)
#define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0)
#endif
#if !defined(luai_threadyield)
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
#endif
/*
** these macros allow user-specific actions on threads when you defined
** LUAI_EXTRASPACE and need to do something extra when a thread is
** created/deleted/resumed/yielded.
*/
#if !defined(luai_userstateopen)
#define luai_userstateopen(L) ((void)L)
#endif
#if !defined(luai_userstateclose)
#define luai_userstateclose(L) ((void)L)
#endif
#if !defined(luai_userstatethread)
#define luai_userstatethread(L,L1) ((void)L)
#endif
#if !defined(luai_userstatefree)
#define luai_userstatefree(L,L1) ((void)L)
#endif
#if !defined(luai_userstateresume)
#define luai_userstateresume(L,n) ((void)L)
#endif
#if !defined(luai_userstateyield)
#define luai_userstateyield(L,n) ((void)L)
#endif
/*
** lua_number2int is a macro to convert lua_Number to int.
** lua_number2integer is a macro to convert lua_Number to lua_Integer.
** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned.
** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number.
** luai_hashnum is a macro to hash a lua_Number value into an integer.
** The hash must be deterministic and give reasonable values for
** both small and large values (outside the range of integers).
*/
#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */
/* trick with Microsoft assembler for X86 */
#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i}
#define lua_number2integer(i,n) lua_number2int(i, n)
#define lua_number2unsigned(i,n) \
{__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;}
#elif defined(LUA_IEEE754TRICK) /* }{ */
/* the next trick should work on any machine using IEEE754 with
a 32-bit int type */
union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
#if !defined(LUA_IEEEENDIAN) /* { */
#define LUAI_EXTRAIEEE \
static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33)
#else
#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN
#define LUAI_EXTRAIEEE /* empty */
#endif /* } */
#define lua_number2int32(i,n,t) \
{ LUAI_EXTRAIEEE \
volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
(i) = (t)u.l_p[LUA_IEEEENDIANLOC]; }
#define luai_hashnum(i,n) \
{ volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \
(i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */
#define lua_number2int(i,n) lua_number2int32(i, n, int)
#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned)
/* the trick can be expanded to lua_Integer when it is a 32-bit value */
#if defined(LUA_IEEELL)
#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer)
#endif
#endif /* } */
/* the following definitions always work, but may be slow */
#if !defined(lua_number2int)
#define lua_number2int(i,n) ((i)=(int)(n))
#endif
#if !defined(lua_number2integer)
#define lua_number2integer(i,n) ((i)=(lua_Integer)(n))
#endif
#if !defined(lua_number2unsigned) /* { */
/* the following definition assures proper modulo behavior */
#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT)
#include <math.h>
#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1)
#define lua_number2unsigned(i,n) \
((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED))
#else
#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n))
#endif
#endif /* } */
#if !defined(lua_unsigned2number)
/* on several machines, coercion from unsigned to double is slow,
so it may be worth to avoid */
#define lua_unsigned2number(u) \
(((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
#endif
#if defined(ltable_c) && !defined(luai_hashnum)
#include <float.h>
#include <math.h>
#define luai_hashnum(i,n) { int e; \
n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \
lua_number2int(i, n); i += e; }
#endif
/*
** macro to control inclusion of some hard tests on stack reallocation
*/
#if !defined(HARDSTACKTESTS)
#define condmovestack(L) ((void)0)
#else
/* realloc stack keeping its size */
#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize)
#endif
#if !defined(HARDMEMTESTS)
#define condchangemem(L) condmovestack(L)
#else
#define condchangemem(L) \
((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
#endif
#endif

57
client/3rdparty/lua5.2/include/lmem.h vendored

@ -0,0 +1,57 @@
/*
** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#ifndef lmem_h
#define lmem_h
#include <stddef.h>
#include "llimits.h"
#include "lua.h"
/*
** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is
** always constant.
** The macro is somewhat complex to avoid warnings:
** +1 avoids warnings of "comparison has constant result";
** cast to 'void' avoids warnings of "value unused".
*/
#define luaM_reallocv(L,b,on,n,e) \
(cast(void, \
(cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \
luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
#define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0]))
#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s))
#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
#define luaM_newvector(L,n,t) \
cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s))
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
if ((nelems)+1 > (size)) \
((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
#define luaM_reallocvector(L, v,oldn,n,t) \
((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
/* not to be called directly */
LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
size_t size);
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
size_t size_elem, int limit,
const char *what);
#endif

607
client/3rdparty/lua5.2/include/lobject.h vendored

@ -0,0 +1,607 @@
/*
** $Id: lobject.h,v 2.71.1.2 2014/05/07 14:14:58 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
#ifndef lobject_h
#define lobject_h
#include <stdarg.h>
#include "llimits.h"
#include "lua.h"
/*
** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS
#define LUA_TUPVAL (LUA_NUMTAGS+1)
#define LUA_TDEADKEY (LUA_NUMTAGS+2)
/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
#define LUA_TOTALTAGS (LUA_TUPVAL+2)
/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/
#define VARBITS (3 << 4)
/*
** LUA_TFUNCTION variants:
** 0 - Lua function
** 1 - light C function
** 2 - regular C function (closure)
*/
/* Variant tags for functions */
#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */
#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */
#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
/* Variant tags for strings */
#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
/* mark a tag as collectable */
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
/*
** Union of all collectable objects
*/
typedef union GCObject GCObject;
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/*
** Common header in struct form
*/
typedef struct GCheader {
CommonHeader;
} GCheader;
/*
** Union of all Lua values
*/
typedef union Value Value;
#define numfield lua_Number n; /* numbers */
/*
** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
*/
#define TValuefields Value value_; int tt_
typedef struct lua_TValue TValue;
/* macro defining a nil value */
#define NILCONSTANT {NULL}, LUA_TNIL
#define val_(o) ((o)->value_)
#define num_(o) (val_(o).n)
/* raw type tag of a TValue */
#define rttype(o) ((o)->tt_)
/* tag with no variants (bits 0-3) */
#define novariant(x) ((x) & 0x0F)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
#define ttypenv(o) (novariant(rttype(o)))
/* Macros to test type */
#define checktag(o,t) (rttype(o) == (t))
#define checktype(o,t) (ttypenv(o) == (t))
#define ttisnumber(o) checktag((o), LUA_TNUMBER)
#define ttisnil(o) checktag((o), LUA_TNIL)
#define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
#define ttisstring(o) checktype((o), LUA_TSTRING)
#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR))
#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR))
#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION)
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
#define ttislcf(o) checktag((o), LUA_TLCF)
#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
#define ttisequal(o1,o2) (rttype(o1) == rttype(o2))
/* Macros to access values */
#define nvalue(o) check_exp(ttisnumber(o), num_(o))
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts)
#define tsvalue(o) (&rawtsvalue(o)->tsv)
#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u)
#define uvalue(o) (&rawuvalue(o)->uv)
#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl)
#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l)
#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c)
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h)
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th)
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
/* Macros for internal tests */
#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt)
#define checkliveness(g,obj) \
lua_longassert(!iscollectable(obj) || \
(righttt(obj) && !isdead(g,gcvalue(obj))))
/* Macros to set values */
#define settt_(o,t) ((o)->tt_=(t))
#define setnvalue(obj,x) \
{ TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }
#define setpvalue(obj,x) \
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); }
#define setbvalue(obj,x) \
{ TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
#define setgcovalue(L,obj,x) \
{ TValue *io=(obj); GCObject *i_g=(x); \
val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); }
#define setsvalue(L,obj,x) \
{ TValue *io=(obj); \
TString *x_ = (x); \
val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
checkliveness(G(L),io); }
#define setuvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(G(L),io); }
#define setthvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(G(L),io); }
#define setclLvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \
checkliveness(G(L),io); }
#define setclCvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \
checkliveness(G(L),io); }
#define sethvalue(L,obj,x) \
{ TValue *io=(obj); \
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
#define setobj(L,obj1,obj2) \
{ const TValue *io2=(obj2); TValue *io1=(obj1); \
io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
checkliveness(G(L),io1); }
/*
** different types of assignments, according to destination
*/
/* from stack to (same) stack */
#define setobjs2s setobj
/* to stack (not from same stack) */
#define setobj2s setobj
#define setsvalue2s setsvalue
#define sethvalue2s sethvalue
#define setptvalue2s setptvalue
/* from table to same table */
#define setobjt2t setobj
/* to table */
#define setobj2t setobj
/* to new object */
#define setobj2n setobj
#define setsvalue2n setsvalue
/* check whether a number is valid (useful only for NaN trick) */
#define luai_checknum(L,o,c) { /* empty */ }
/*
** {======================================================
** NaN Trick
** =======================================================
*/
#if defined(LUA_NANTRICK)
/*
** numbers are represented in the 'd_' field. All other values have the
** value (NNMARK | tag) in 'tt__'. A number with such pattern would be
** a "signaled NaN", which is never generated by regular operations by
** the CPU (nor by 'strtod')
*/
/* allows for external implementation for part of the trick */
#if !defined(NNMARK) /* { */
#if !defined(LUA_IEEEENDIAN)
#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
#endif
#define NNMARK 0x7FF7A500
#define NNMASK 0x7FFFFF00
#undef TValuefields
#undef NILCONSTANT
#if (LUA_IEEEENDIAN == 0) /* { */
/* little endian */
#define TValuefields \
union { struct { Value v__; int tt__; } i; double d__; } u
#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}}
/* field-access macros */
#define v_(o) ((o)->u.i.v__)
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
#else /* }{ */
/* big endian */
#define TValuefields \
union { struct { int tt__; Value v__; } i; double d__; } u
#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}}
/* field-access macros */
#define v_(o) ((o)->u.i.v__)
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
#endif /* } */
#endif /* } */
/* correspondence with standard representation */
#undef val_
#define val_(o) v_(o)
#undef num_
#define num_(o) d_(o)
#undef numfield
#define numfield /* no such field; numbers are the entire struct */
/* basic check to distinguish numbers from non-numbers */
#undef ttisnumber
#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK)
#define tag2tt(t) (NNMARK | (t))
#undef rttype
#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff)
#undef settt_
#define settt_(o,t) (tt_(o) = tag2tt(t))
#undef setnvalue
#define setnvalue(obj,x) \
{ TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); }
#undef setobj
#define setobj(L,obj1,obj2) \
{ const TValue *o2_=(obj2); TValue *o1_=(obj1); \
o1_->u = o2_->u; \
checkliveness(G(L),o1_); }
/*
** these redefinitions are not mandatory, but these forms are more efficient
*/
#undef checktag
#undef checktype
#define checktag(o,t) (tt_(o) == tag2tt(t))
#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS))
#undef ttisequal
#define ttisequal(o1,o2) \
(ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
#undef luai_checknum
#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; }
#endif
/* }====================================================== */
/*
** {======================================================
** types and prototypes
** =======================================================
*/
union Value {
GCObject *gc; /* collectable objects */
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
numfield /* numbers */
};
struct lua_TValue {
TValuefields;
};
typedef TValue *StkId; /* index to stack elements */
/*
** Header for string value; string bytes follow the end of this structure
*/
typedef union TString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
struct {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
unsigned int hash;
size_t len; /* number of characters in string */
} tsv;
} TString;
/* get the actual string (array of bytes) from a TString */
#define getstr(ts) cast(const char *, (ts) + 1)
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(rawtsvalue(o))
/*
** Header for userdata; memory area follows the end of this structure
*/
typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
CommonHeader;
struct Table *metatable;
struct Table *env;
size_t len; /* number of bytes */
} uv;
} Udata;
/*
** Description of an upvalue for function prototypes
*/
typedef struct Upvaldesc {
TString *name; /* upvalue name (for debug information) */
lu_byte instack; /* whether it is in stack */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;
/*
** Description of a local variable for function prototypes
** (used for debug information)
*/
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
} LocVar;
/*
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines (debug information) */
LocVar *locvars; /* information about local variables (debug information) */
Upvaldesc *upvalues; /* upvalue information */
union Closure *cache; /* last created closure with this prototype */
TString *source; /* used for debug information */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of `k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of `p' */
int sizelocvars;
int linedefined;
int lastlinedefined;
GCObject *gclist;
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg;
lu_byte maxstacksize; /* maximum stack used by this function */
} Proto;
/*
** Lua Upvalues
*/
typedef struct UpVal {
CommonHeader;
TValue *v; /* points to stack or to its own value */
union {
TValue value; /* the value (when closed) */
struct { /* double linked list (when open) */
struct UpVal *prev;
struct UpVal *next;
} l;
} u;
} UpVal;
/*
** Closures
*/
#define ClosureHeader \
CommonHeader; lu_byte nupvalues; GCObject *gclist
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
TValue upvalue[1]; /* list of upvalues */
} CClosure;
typedef struct LClosure {
ClosureHeader;
struct Proto *p;
UpVal *upvals[1]; /* list of upvalues */
} LClosure;
typedef union Closure {
CClosure c;
LClosure l;
} Closure;
#define isLfunction(o) ttisLclosure(o)
#define getproto(o) (clLvalue(o)->p)
/*
** Tables
*/
typedef union TKey {
struct {
TValuefields;
struct Node *next; /* for chaining */
} nk;
TValue tvk;
} TKey;
typedef struct Node {
TValue i_val;
TKey i_key;
} Node;
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
int sizearray; /* size of `array' array */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
struct Table *metatable;
GCObject *gclist;
} Table;
/*
** `module' operation for hashing (size is always a power of 2)
*/
#define lmod(s,size) \
(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
#define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode))
/*
** (address of) a fixed nil value
*/
#define luaO_nilobject (&luaO_nilobject_)
LUAI_DDEC const TValue luaO_nilobject_;
LUAI_FUNC int luaO_int2fb (unsigned int x);
LUAI_FUNC int luaO_fb2int (int x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2);
LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
LUAI_FUNC int luaO_hexavalue (int c);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
#endif

228
client/3rdparty/lua5.2/include/lstate.h vendored

@ -0,0 +1,228 @@
/*
** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
#ifndef lstate_h
#define lstate_h
#include "lua.h"
#include "lobject.h"
#include "ltm.h"
#include "lzio.h"
/*
** Some notes about garbage-collected objects: All objects in Lua must
** be kept somehow accessible until being freed.
**
** Lua keeps most objects linked in list g->allgc. The link uses field
** 'next' of the CommonHeader.
**
** Strings are kept in several lists headed by the array g->strt.hash.
**
** Open upvalues are not subject to independent garbage collection. They
** are collected together with their respective threads. Lua keeps a
** double-linked list with all open upvalues (g->uvhead) so that it can
** mark objects referred by them. (They are always gray, so they must
** be remarked in the atomic step. Usually their contents would be marked
** when traversing the respective threads, but the thread may already be
** dead, while the upvalue is still accessible through closures.)
**
** Objects with finalizers are kept in the list g->finobj.
**
** The list g->tobefnz links all objects being finalized.
*/
struct lua_longjmp; /* defined in ldo.c */
/* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
/* kinds of Garbage Collection */
#define KGC_NORMAL 0
#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */
#define KGC_GEN 2 /* generational collection */
typedef struct stringtable {
GCObject **hash;
lu_int32 nuse; /* number of elements */
int size;
} stringtable;
/*
** information about a call
*/
typedef struct CallInfo {
StkId func; /* function index in the stack */
StkId top; /* top for this function */
struct CallInfo *previous, *next; /* dynamic call link */
short nresults; /* expected number of results from this function */
lu_byte callstatus;
ptrdiff_t extra;
union {
struct { /* only for Lua functions */
StkId base; /* base for this function */
const Instruction *savedpc;
} l;
struct { /* only for C functions */
int ctx; /* context info. in case of yields */
lua_CFunction k; /* continuation in case of yields */
ptrdiff_t old_errfunc;
lu_byte old_allowhook;
lu_byte status;
} c;
} u;
} CallInfo;
/*
** Bits in CallInfo status
*/
#define CIST_LUA (1<<0) /* call is running a Lua function */
#define CIST_HOOKED (1<<1) /* call is running a debug hook */
#define CIST_REENTRY (1<<2) /* call is running on same invocation of
luaV_execute of previous call */
#define CIST_YIELDED (1<<3) /* call reentered after suspension */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
#define CIST_STAT (1<<5) /* call has an error status (pcall) */
#define CIST_TAIL (1<<6) /* call was tail called */
#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
/*
** `global state', shared by all threads of this state
*/
typedef struct global_State {
lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to `frealloc' */
lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCmemtrav; /* memory traversed by the GC */
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
stringtable strt; /* hash table for strings */
TValue l_registry;
unsigned int seed; /* randomized seed for hashes */
lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */
lu_byte gcrunning; /* true if GC is running */
int sweepstrgc; /* position of sweep in `strt' */
GCObject *allgc; /* list of all collectable objects */
GCObject *finobj; /* list of collectable objects with finalizers */
GCObject **sweepgc; /* current position of sweep in list 'allgc' */
GCObject **sweepfin; /* current position of sweep in list 'finobj' */
GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of tables with weak values */
GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
GCObject *allweak; /* list of all-weak tables */
GCObject *tobefnz; /* list of userdata to be GC */
UpVal uvhead; /* head of double-linked list of all open upvalues */
Mbuffer buff; /* temporary buffer for string concatenation */
int gcpause; /* size of pause between successive GCs */
int gcmajorinc; /* pause between major collections (only in gen. mode) */
int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */
struct lua_State *mainthread;
const lua_Number *version; /* pointer to version number */
TString *memerrmsg; /* memory-error message */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
} global_State;
/*
** `per thread' state
*/
struct lua_State {
CommonHeader;
lu_byte status;
StkId top; /* first free slot in the stack */
global_State *l_G;
CallInfo *ci; /* call info for current function */
const Instruction *oldpc; /* last pc traced */
StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */
int stacksize;
unsigned short nny; /* number of non-yieldable calls in stack */
unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask;
lu_byte allowhook;
int basehookcount;
int hookcount;
lua_Hook hook;
GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
};
#define G(L) (L->l_G)
/*
** Union of all collectable objects
*/
union GCObject {
GCheader gch; /* common header */
union TString ts;
union Udata u;
union Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th; /* thread */
};
#define gch(o) (&(o)->gch)
/* macros to convert a GCObject into a specific value */
#define rawgco2ts(o) \
check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts))
#define gco2ts(o) (&rawgco2ts(o)->tsv)
#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gco2u(o) (&rawgco2u(o)->uv)
#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l))
#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c))
#define gco2cl(o) \
check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl))
#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
/* macro to convert any Lua object into a GCObject */
#define obj2gco(v) (cast(GCObject *, (v)))
/* actual number of total bytes allocated */
#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt)
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
#endif

57
client/3rdparty/lua5.2/include/ltm.h vendored

@ -0,0 +1,57 @@
/*
** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
#ifndef ltm_h
#define ltm_h
#include "lobject.h"
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER TM"
*/
typedef enum {
TM_INDEX,
TM_NEWINDEX,
TM_GC,
TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with `fast' access */
TM_ADD,
TM_SUB,
TM_MUL,
TM_DIV,
TM_MOD,
TM_POW,
TM_UNM,
TM_LT,
TM_LE,
TM_CONCAT,
TM_CALL,
TM_N /* number of elements in the enum */
} TMS;
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
#define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1]
#define objtypename(x) ttypename(ttypenv(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event);
LUAI_FUNC void luaT_init (lua_State *L);
#endif

444
client/3rdparty/lua5.2/include/lua.h vendored

@ -0,0 +1,444 @@
/*
** $Id: lua.h,v 1.285.1.4 2015/02/21 14:04:50 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
*/
#ifndef lua_h
#define lua_h
#include <stdarg.h>
#include <stddef.h>
#include "luaconf.h"
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "2"
#define LUA_VERSION_NUM 502
#define LUA_VERSION_RELEASE "4"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
/* mark for precompiled code ('<esc>Lua') */
#define LUA_SIGNATURE "\033Lua"
/* option for multiple returns in 'lua_pcall' and 'lua_call' */
#define LUA_MULTRET (-1)
/*
** pseudo-indices
*/
#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
/* thread status */
#define LUA_OK 0
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRGCMM 5
#define LUA_ERRERR 6
typedef struct lua_State lua_State;
typedef int (*lua_CFunction) (lua_State *L);
/*
** functions that read/write blocks when loading/dumping Lua chunks
*/
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
/*
** prototype for memory-allocation functions
*/
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
/*
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_NUMTAGS 9
/* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20
/* predefined values in the registry */
#define LUA_RIDX_MAINTHREAD 1
#define LUA_RIDX_GLOBALS 2
#define LUA_RIDX_LAST LUA_RIDX_GLOBALS
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
/* type for integer functions */
typedef LUA_INTEGER lua_Integer;
/* unsigned integer type */
typedef LUA_UNSIGNED lua_Unsigned;
/*
** generic extra include file
*/
#if defined(LUA_USER_H)
#include LUA_USER_H
#endif
/*
** RCS ident string
*/
extern const char lua_ident[];
/*
** state manipulation
*/
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
LUA_API const lua_Number *(lua_version) (lua_State *L);
/*
** basic stack manipulation
*/
LUA_API int (lua_absindex) (lua_State *L, int idx);
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
LUA_API void (lua_remove) (lua_State *L, int idx);
LUA_API void (lua_insert) (lua_State *L, int idx);
LUA_API void (lua_replace) (lua_State *L, int idx);
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
LUA_API int (lua_checkstack) (lua_State *L, int sz);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
/*
** access functions (stack -> C)
*/
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_rawlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
/*
** Comparison and arithmetic functions
*/
#define LUA_OPADD 0 /* ORDER TM */
#define LUA_OPSUB 1
#define LUA_OPMUL 2
#define LUA_OPDIV 3
#define LUA_OPMOD 4
#define LUA_OPPOW 5
#define LUA_OPUNM 6
LUA_API void (lua_arith) (lua_State *L, int op);
#define LUA_OPEQ 0
#define LUA_OPLT 1
#define LUA_OPLE 2
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
/*
** push functions (C -> stack)
*/
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n);
LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);
/*
** get functions (Lua -> stack)
*/
LUA_API void (lua_getglobal) (lua_State *L, const char *var);
LUA_API void (lua_gettable) (lua_State *L, int idx);
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawget) (lua_State *L, int idx);
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API void (lua_getuservalue) (lua_State *L, int idx);
/*
** set functions (stack -> Lua)
*/
LUA_API void (lua_setglobal) (lua_State *L, const char *var);
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API void (lua_setuservalue) (lua_State *L, int idx);
/*
** 'load' and 'call' functions (load and run Lua code)
*/
LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
lua_CFunction k);
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
LUA_API int (lua_getctx) (lua_State *L, int *ctx);
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
int ctx, lua_CFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname,
const char *mode);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
/*
** coroutine functions
*/
LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx,
lua_CFunction k);
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
LUA_API int (lua_status) (lua_State *L);
/*
** garbage-collection function and options
*/
#define LUA_GCSTOP 0
#define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3
#define LUA_GCCOUNTB 4
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
#define LUA_GCSETMAJORINC 8
#define LUA_GCISRUNNING 9
#define LUA_GCGEN 10
#define LUA_GCINC 11
LUA_API int (lua_gc) (lua_State *L, int what, int data);
/*
** miscellaneous functions
*/
LUA_API int (lua_error) (lua_State *L);
LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API void (lua_len) (lua_State *L, int idx);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL)
#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL)
#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL)
#define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_newtable(L) lua_createtable(L, 0, 0)
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
#define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_pushglobaltable(L) \
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
/*
** {======================================================================
** Debug API
** =======================================================================
*/
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILCALL 4
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debugger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar);
LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n);
LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n);
LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook (lua_gethook) (lua_State *L);
LUA_API int (lua_gethookmask) (lua_State *L);
LUA_API int (lua_gethookcount) (lua_State *L);
struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */
const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */
const char *source; /* (S) */
int currentline; /* (l) */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
unsigned char nups; /* (u) number of upvalues */
unsigned char nparams;/* (u) number of parameters */
char isvararg; /* (u) */
char istailcall; /* (t) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
struct CallInfo *i_ci; /* active function */
};
/* }====================================================================== */
/******************************************************************************
* Copyright (C) 1994-2015 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#endif

9
client/3rdparty/lua5.2/include/lua.hpp vendored

@ -0,0 +1,9 @@
// lua.hpp
// Lua header files for C++
// <<extern "C">> not supplied automatically because Lua also compiles as C++
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

553
client/3rdparty/lua5.2/include/luaconf.h vendored

@ -0,0 +1,553 @@
/*
** $Id: luaconf.h,v 1.176.1.2 2013/11/21 17:26:16 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
#ifndef lconfig_h
#define lconfig_h
#include <limits.h>
#include <stddef.h>
/*
** ==================================================================
** Search for "@@" to find all configurable definitions.
** ===================================================================
*/
/*
@@ LUA_ANSI controls the use of non-ansi features.
** CHANGE it (define it) if you want Lua to avoid the use of any
** non-ansi feature or library.
*/
#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__)
#define LUA_ANSI
#endif
#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE)
#define LUA_WIN /* enable goodies for regular Windows platforms */
#endif
#if defined(LUA_WIN)
#define LUA_DL_DLL
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* does not need -ldl */
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif
/*
@@ LUA_USE_POSIX includes all functionality listed as X/Open System
@* Interfaces Extension (XSI).
** CHANGE it (define it) if your system is XSI compatible.
*/
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#define LUA_USE_GMTIME_R
#endif
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
@* Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
@* C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua"
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll;" \
LUA_CDIR"?52.dll;" ".\\?52.dll"
#else /* }{ */
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua"
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so;" \
LUA_CDIR"lib?52.so;" "./lib?52.so"
#endif /* } */
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".)
*/
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
/*
@@ LUA_ENV is the name of the variable that holds the current
@@ environment, used to access global names.
** CHANGE it if you do not like this name.
*/
#define LUA_ENV "_ENV"
/*
@@ LUA_API is a mark for all core API functions.
@@ LUALIB_API is a mark for all auxiliary library functions.
@@ LUAMOD_API is a mark for all standard library opening functions.
** CHANGE them if you need to define those functions in some special way.
** For instance, if you want to create one Windows DLL with the core and
** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it).
*/
#if defined(LUA_BUILD_AS_DLL) /* { */
#if defined(LUA_CORE) || defined(LUA_LIB) /* { */
#define LUA_API __declspec(dllexport)
#else /* }{ */
#define LUA_API __declspec(dllimport)
#endif /* } */
#else /* }{ */
#define LUA_API extern
#endif /* } */
/* more often than not the libs go together with the core */
#define LUALIB_API LUA_API
#define LUAMOD_API LUALIB_API
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
@* exported to outside modules.
@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
@* that are not to be exported to outside modules (LUAI_DDEF for
@* definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. Not all elf targets support
** this attribute. Unfortunately, gcc does not offer a way to check
** whether the target offers that support, and those without support
** give a warning about it. To avoid these warnings, change to the
** default definition.
*/
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DDEC LUAI_FUNC
#define LUAI_DDEF /* empty */
#else /* }{ */
#define LUAI_FUNC extern
#define LUAI_DDEC extern
#define LUAI_DDEF /* empty */
#endif /* } */
/*
@@ LUA_QL describes how error messages quote program elements.
** CHANGE it if you want a different appearance.
*/
#define LUA_QL(x) "'" x "'"
#define LUA_QS LUA_QL("%s")
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
@* of a function in debug information.
** CHANGE it if you want a different size.
*/
#define LUA_IDSIZE 60
/*
@@ luai_writestring/luai_writeline define how 'print' prints its results.
** They are only used in libraries and the stand-alone program. (The #if
** avoids including 'stdio.h' everywhere.)
*/
#if defined(LUA_LIB) || defined(lua_c)
#include <stdio.h>
#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout))
#endif
/*
@@ luai_writestringerror defines how to print error messages.
** (A format string with one argument is enough for Lua...)
*/
#define luai_writestringerror(s,p) \
(fprintf(stderr, (s), (p)), fflush(stderr))
/*
@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
** strings that are internalized. (Cannot be smaller than reserved words
** or tags for metamethods, as these strings must be internalized;
** #("function") = 8, #("__newindex") = 10.)
*/
#define LUAI_MAXSHORTLEN 40
/*
** {==================================================================
** Compatibility with previous versions
** ===================================================================
*/
/*
@@ LUA_COMPAT_ALL controls all compatibility options.
** You can define it to get all options, or change specific options
** to fit your specific needs.
*/
#if defined(LUA_COMPAT_ALL) /* { */
/*
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
** You can replace it with 'table.unpack'.
*/
#define LUA_COMPAT_UNPACK
/*
@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'.
** You can replace it with 'package.searchers'.
*/
#define LUA_COMPAT_LOADERS
/*
@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall.
** You can call your C function directly (with light C functions).
*/
#define lua_cpcall(L,f,u) \
(lua_pushcfunction(L, (f)), \
lua_pushlightuserdata(L,(u)), \
lua_pcall(L,1,0,0))
/*
@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library.
** You can rewrite 'log10(x)' as 'log(x, 10)'.
*/
#define LUA_COMPAT_LOG10
/*
@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base
** library. You can rewrite 'loadstring(s)' as 'load(s)'.
*/
#define LUA_COMPAT_LOADSTRING
/*
@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library.
*/
#define LUA_COMPAT_MAXN
/*
@@ The following macros supply trivial compatibility for some
** changes in the API. The macros themselves document how to
** change your code to avoid using them.
*/
#define lua_strlen(L,i) lua_rawlen(L, (i))
#define lua_objlen(L,i) lua_rawlen(L, (i))
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
/*
@@ LUA_COMPAT_MODULE controls compatibility with previous
** module functions 'module' (Lua) and 'luaL_register' (C).
*/
#define LUA_COMPAT_MODULE
#endif /* } */
/* }================================================================== */
/*
@@ LUAI_BITSINT defines the number of bits in an int.
** CHANGE here if Lua cannot automatically detect the number of bits of
** your machine. Probably you do not need to change this.
*/
/* avoid overflows in comparison */
#if INT_MAX-20 < 32760 /* { */
#define LUAI_BITSINT 16
#elif INT_MAX > 2147483640L /* }{ */
/* int has at least 32 bits */
#define LUAI_BITSINT 32
#else /* }{ */
#error "you must define LUA_BITSINT with number of bits in an integer"
#endif /* } */
/*
@@ LUA_INT32 is a signed integer with exactly 32 bits.
@@ LUAI_UMEM is an unsigned integer big enough to count the total
@* memory used by Lua.
@@ LUAI_MEM is a signed integer big enough to count the total memory
@* used by Lua.
** CHANGE here if for some weird reason the default definitions are not
** good enough for your machine. Probably you do not need to change
** this.
*/
#if LUAI_BITSINT >= 32 /* { */
#define LUA_INT32 int
#define LUAI_UMEM size_t
#define LUAI_MEM ptrdiff_t
#else /* }{ */
/* 16-bit ints */
#define LUA_INT32 long
#define LUAI_UMEM unsigned long
#define LUAI_MEM long
#endif /* } */
/*
@@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need a different limit. This limit is arbitrary;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
*/
#if LUAI_BITSINT >= 32
#define LUAI_MAXSTACK 1000000
#else
#define LUAI_MAXSTACK 15000
#endif
/* reserve some space for error handling */
#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
** CHANGE it if it uses too much C-stack space.
*/
#define LUAL_BUFFERSIZE BUFSIZ
/*
** {==================================================================
@@ LUA_NUMBER is the type of numbers in Lua.
** CHANGE the following definitions only if you want to build Lua
** with a number type different from double. You may also need to
** change lua_number2int & lua_number2integer.
** ===================================================================
*/
#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double
/*
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
@* over a number.
*/
#define LUAI_UACNUMBER double
/*
@@ LUA_NUMBER_SCAN is the format for reading numbers.
@@ LUA_NUMBER_FMT is the format for writing numbers.
@@ lua_number2str converts a number to a string.
@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
*/
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
/*
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
*/
#define l_mathop(x) (x)
/*
@@ lua_str2number converts a decimal numeric string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' does both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
*/
#define lua_str2number(s,p) strtod((s), (p))
#if defined(LUA_USE_STRTODHEX)
#define lua_strx2number(s,p) strtod((s), (p))
#endif
/*
@@ The luai_num* macros define the primitive operations over numbers.
*/
/* the following operations need the math library */
#if defined(lobject_c) || defined(lvm_c)
#include <math.h>
#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b))
#define luai_numpow(L,a,b) (l_mathop(pow)(a,b))
#endif
/* these are quite standard operations */
#if defined(LUA_CORE)
#define luai_numadd(L,a,b) ((a)+(b))
#define luai_numsub(L,a,b) ((a)-(b))
#define luai_nummul(L,a,b) ((a)*(b))
#define luai_numdiv(L,a,b) ((a)/(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(L,a,b) ((a)<(b))
#define luai_numle(L,a,b) ((a)<=(b))
#define luai_numisnan(L,a) (!luai_numeq((a), (a)))
#endif
/*
@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
** machines, ptrdiff_t gives a good choice between int or long.)
*/
#define LUA_INTEGER ptrdiff_t
/*
@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
** It must have at least 32 bits.
*/
#define LUA_UNSIGNED unsigned LUA_INT32
/*
** Some tricks with doubles
*/
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
/*
** The next definitions activate some tricks to speed up the
** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
**
@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a
** DirectX idiosyncrasy.
**
@@ LUA_IEEE754TRICK uses a trick that should work on any machine
** using IEEE754 with a 32-bit integer type.
**
@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
** defined when LUA_INTEGER is a 32-bit integer.
**
@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
** (0 for little endian, 1 for big endian); if not defined, Lua will
** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
**
@@ LUA_NANTRICK controls the use of a trick to pack all types into
** a single double value, using NaN values to represent non-number
** values. The trick only works on 32-bit machines (ints and pointers
** are 32-bit values) with numbers represented as IEEE 754-2008 doubles
** with conventional endianess (12345678 or 87654321), in CPUs that do
** not produce signaling NaN values (all NaNs are quiet).
*/
/* Microsoft compiler on a Pentium (32 bit) ? */
#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
#define LUA_MSASMTRICK
#define LUA_IEEEENDIAN 0
#define LUA_NANTRICK
/* pentium 32 bits? */
#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
#define LUA_IEEE754TRICK
#define LUA_IEEELL
#define LUA_IEEEENDIAN 0
#define LUA_NANTRICK
/* pentium 64 bits? */
#elif defined(__x86_64) /* }{ */
#define LUA_IEEE754TRICK
#define LUA_IEEEENDIAN 0
#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */
#define LUA_IEEE754TRICK
#define LUA_IEEEENDIAN 1
#else /* }{ */
/* assume IEEE754 and a 32-bit integer type */
#define LUA_IEEE754TRICK
#endif /* } */
#endif /* } */
/* }================================================================== */
/* =================================================================== */
/*
** Local configuration. You can use this space to add your redefinitions
** without modifying the main part of the file.
*/
#endif

55
client/3rdparty/lua5.2/include/lualib.h vendored

@ -0,0 +1,55 @@
/*
** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
#ifndef lualib_h
#define lualib_h
#include "lua.h"
LUAMOD_API int (luaopen_base) (lua_State *L);
#define LUA_COLIBNAME "coroutine"
LUAMOD_API int (luaopen_coroutine) (lua_State *L);
#define LUA_TABLIBNAME "table"
LUAMOD_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUAMOD_API int (luaopen_io) (lua_State *L);
#define LUA_OSLIBNAME "os"
LUAMOD_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUAMOD_API int (luaopen_string) (lua_State *L);
#define LUA_BITLIBNAME "bit32"
LUAMOD_API int (luaopen_bit32) (lua_State *L);
#define LUA_MATHLIBNAME "math"
LUAMOD_API int (luaopen_math) (lua_State *L);
#define LUA_DBLIBNAME "debug"
LUAMOD_API int (luaopen_debug) (lua_State *L);
#define LUA_LOADLIBNAME "package"
LUAMOD_API int (luaopen_package) (lua_State *L);
/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);
#if !defined(lua_assert)
#define lua_assert(x) ((void)0)
#endif
#endif

65
client/3rdparty/lua5.2/include/lzio.h vendored

@ -0,0 +1,65 @@
/*
** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/
#ifndef lzio_h
#define lzio_h
#include "lua.h"
#include "lmem.h"
#define EOZ (-1) /* end of stream */
typedef struct Zio ZIO;
#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z))
typedef struct Mbuffer {
char *buffer;
size_t n;
size_t buffsize;
} Mbuffer;
#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
#define luaZ_buffer(buff) ((buff)->buffer)
#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_bufflen(buff) ((buff)->n)
#define luaZ_resetbuffer(buff) ((buff)->n = 0)
#define luaZ_resizebuffer(L, buff, size) \
(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
(buff)->buffsize = size)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data);
LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
/* --------- Private Part ------------------ */
struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Reader reader; /* reader function */
void* data; /* additional data */
lua_State *L; /* Lua state (for reader) */
};
LUAI_FUNC int luaZ_fill (ZIO *z);
#endif

BIN
client/3rdparty/lua5.2/liblua52.a vendored

Binary file not shown.

53
client/build/embed.lua.bat

@ -0,0 +1,53 @@
rem = rem --[[
@echo off
cd %~dp0
call ..\..\bin\win_x86\lua5.2\lua52.exe %0 %*
goto :eof
]]
local function embed( name, prefix, srcFileName, dstFileName)
print("Embedding: "..srcFileName)
local codeFile = assert( io.open( srcFileName, "rb" ) )
local code = codeFile:read("*a")
codeFile:close()
local out = assert( io.open( dstFileName, "w" ) )
out:write( "// This file contains lua code encoded from "..srcFileName.."\n" )
out:write( "// Use script embed.lua.bat to re-generate this file if you changed the source code\n" )
out:write( "\n" )
out:write( "const char* "..prefix.."get"..name.."Code()\n" )
out:write( "{\n" )
out:write( "\tstatic unsigned char code[] =\n" )
out:write( "\t{\n" )
out:write( "\t\t" )
local charsInLine = 0
string.gsub( code, ".", function( p )
local c = string.byte(p)
out:write( string.format( "0x%02x, ", c ) )
charsInLine = charsInLine + 1
if charsInLine == 16 then
out:write( "\n\t\t" )
charsInLine = 0
end
end )
out:write( "\n" )
out:write( "\t};\n" )
out:write( "\treturn (const char*)code;\n" )
out:write( "}\n" )
out:write( "int "..prefix.."get"..name.."CodeSize()\n" )
out:write( "{\n" )
out:write( "\treturn "..#code..";\n" )
out:write( "}\n" )
out:close()
end
embed( "ldb", "GRLDC_", "../src/grldc_ldb.lua", "../src/grldc_ldb.lua.c" )
embed( "utilities", "GRLDC_", "../../shared/grldc/utilities.lua", "../src/grldc_utilities.lua.c" )
embed( "net", "GRLDC_", "../../shared/grldc/net.lua", "../src/grldc_net.lua.c" )
embed( "socket", "GRLDC_", "../../shared/grldc/socket.lua", "../src/grldc_socket.lua.c" )

554
client/src/grldc.c

@ -0,0 +1,554 @@
/* see copyright notice in grldc.h */
#include "grldc.h"
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include "windows.h" // for GetTickCount
#else
#include <time.h>
unsigned int GetTickCount()
{
struct timespec t;
clock_gettime( CLOCK_MONOTONIC, &t );
unsigned int ms = (unsigned int)(t.tv_nsec / (long)1000000);
ms += (unsigned int)(t.tv_sec * 1000);
return ms;
}
#endif
#include "lauxlib.h"
#include "lstate.h"
#include "luajit_ex.h"
#include "lapi.h"
#if !defined( LUA_VM_LUAJIT ) && LUA_VERSION_NUM < 502
#define GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS // remove this if you use another VM that is incompatible with low level optimizations
#endif
#define GRLD_ENABLE_THREAD_UNSAFE_OPTIMIZATIONS // remove this if you use GRLD on more than one lua state at the same time, and each state runs from a different system thread
#ifdef _DEBUG
#define assert( cond ) { if( !(cond) ) assertImpl( #cond, __FILE__, __LINE__ ); }
#else
#define assert( cond ) {}
#endif
typedef char bool;
const bool false = 0;
const bool true = 1;
#ifdef _DEBUG
void assertImpl( const char* cond, const char* file, int line )
{
printf( "Assertion failed: %s\n%s(%d)\n", cond, file, line );
__asm
{
int 3;
}
}
#endif
const char* const LUA_GRLDCLIBNAME = "grldc";
#if LUA_VERSION_NUM < 502
#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
int GRLDC_getmainthread( lua_State* L )
{
// I did not find a way to push the main thread on the stack of L by using only the public lua API
// lua_pushthread almost does the job, but unfortunately it pushes the thread on the stack of the same thread
// The consequence is that this code is specific to each VM
#ifdef LUA_VM_LUAJIT
lua_pushthread_ex( L, G(L)->mainthread );
#else
lua_lock(L);
setthvalue(L, L->top, G(L)->mainthread);
api_incr_top(L);
lua_unlock(L);
#endif
return 1;
}
#endif
typedef enum
{
SM_None = 0,
SM_Inside = 1,
SM_Over = 2,
SM_Outside = 3
} StepMode;
typedef struct
{
bool hookActive;
bool inLdb;
#ifndef LUA_VM_LUAJIT
bool hookLineEmulationEnabled;
#endif
unsigned int lastRunningUpdate;
StepMode stepMode;
lua_State* stepThread;
int initialCallstackDepth;
int callstackDepth;
const char* lastBreakFile;
int lastBreakLine;
#ifdef GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS
// cached data (these values must not be garbaged collected)
TValue breakpointAliases;
TValue currentFileBreakpoints;
const char* currentFile;
#endif
} DebugState;
void updateCallstackDepth( lua_State* L, DebugState* state )
{
lua_Debug outAR;
while( lua_getstack( L, state->callstackDepth, &outAR ) )
++state->callstackDepth;
while( state->callstackDepth > 0 && !lua_getstack( L, state->callstackDepth, &outAR ) )
--state->callstackDepth;
}
DebugState* getDebugState( lua_State* L )
{
DebugState* state;
#ifdef GRLD_ENABLE_THREAD_UNSAFE_OPTIMIZATIONS
// these static variables could be protected by a mutex so that the optimization becomes thread safe, but the mutex overhead may be bigger than the time saved by the optimization...
// if your platform supports it, the best way to handle multithreading would be to store these variable as thread local data
static DebugState* lastDebugState = NULL;
static lua_State* lastLuaState = NULL;
if( lastLuaState == L )
return lastDebugState;
#endif
lua_getfield( L, LUA_REGISTRYINDEX, "GRLDC_DebugState" );
state = (DebugState*)lua_touserdata( L, -1 );
assert( state != NULL );
lua_pop( L, 1 );
#ifdef GRLD_ENABLE_THREAD_UNSAFE_OPTIMIZATIONS
lastDebugState = state;
lastLuaState = L;
#endif
return state;
}
#ifdef LUA_VM_LUAJIT
void hook( lua_State *L, lua_Debug *ar )
{
DebugState* state = getDebugState( L );
#else
// standard lua misses a LUA_HOOKLINE event after returning from a function (it only sends the event for the next line executed after the return, not the line that called the function). This means users are not reminded where they were before the function was called, which is not intuitive.
// the following code emulates this missing event
void hookImpl_( lua_State *L, lua_Debug *ar, DebugState* state );
void hook( lua_State *L, lua_Debug *ar )
{
DebugState* state = getDebugState( L );
if( ar->event == LUA_HOOKCOUNT )
ar->event = LUA_HOOKLINE;
hookImpl_( L, ar, state );
if( state->stepMode != SM_None && !state->hookLineEmulationEnabled && (ar->event == LUA_HOOKRET
#if LUA_VERSION_NUM < 502 // LUA_HOOKTAILRET does not exist starting from lua5.1
|| ar->event == LUA_HOOKTAILRET) )
#else
) )
#endif
{
state->hookLineEmulationEnabled = true;
lua_sethook( L, hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, 1 );
}
else if( state->hookLineEmulationEnabled )
{
state->hookLineEmulationEnabled = false;
lua_sethook( L, hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 0 );
}
}
void hookImpl_( lua_State *L, lua_Debug *ar, DebugState* state )
{
#endif
unsigned int now = 0;
bool needBreak = false;
if( !state->hookActive )
return;
// check if we are executing code inside GRLDC (we don't want to break in GRLD internal code)
if( state->inLdb )
{
int err = 0;
//luaL_dostring( L, "print( debug.traceback() )" );
lua_getglobal( L, "grldc" );
lua_getfield( L, -1, "getAppLevel_" );
lua_remove( L, -2 );
lua_pushthread( L );
lua_pushinteger( L, 0 );
err = lua_pcall( L, 2, 1, 0 );
if( err )
{
const char* msg = lua_tostring( L, -1 );
printf( "Error executing grldc.getAppLevel_: %s\n", msg );
assert( false );
}
if( lua_isnil( L, -1 ) )
{
//int oldCsDepth = state->callstackDepth;
state->inLdb = false;
//luaL_dostring( L, "print( \"leaving grldc at \"..debug.traceback() )" );
//updateCallstackDepth( L, state );
//state->initialCallstackDepth += state->callstackDepth - oldCsDepth;
}
else
{
//int level = lua_tointeger( L, -1 );
//printf( "current app level: %d\n", level );
}
lua_pop( L, 1 );
}
if( state->inLdb )
return;
//updateCallstackDepth( L, state );
// periodically check if we have received something from the server
now = GetTickCount();
if( now > state->lastRunningUpdate + 250 ) // update running requests only every 250ms
{
int err = 0;
state->lastRunningUpdate = now;
lua_getglobal( L, "grldc" );
lua_getfield( L, -1, "updateRunningRequests_" );
lua_remove( L, -2 );
err = lua_pcall( L, 0, 0, 0 );
if( err )
{
const char* msg = lua_tostring( L, -1 );
printf( "Error executing grldc.updateRunningRequests: %s\n", msg );
assert( false );
}
}
if( ar->event == LUA_HOOKLINE && state->stepMode != SM_None )
{
bool needCheckThread = state->stepMode != SM_Inside;
bool deadThread = false;
// check if the coroutine we are monitoring is dead (in which case we break, whatever coroutine we are in)
if( needCheckThread && state->stepThread != L && state->stepThread != G(L)->mainthread )
{
assert( state->stepThread != NULL );
switch( lua_status(state->stepThread) )
{
case LUA_YIELD:
break;
case 0:
{
lua_Debug ar;
if( lua_getstack( state->stepThread, 0, &ar) <= 0 /* does it have frames? */
&& lua_gettop( state->stepThread ) == 0 )
deadThread = true;
break;
}
default: /* some error occured */
deadThread = true;
}
}
// update stack depth to know if we need to break because we are stepping in lua code
if( !needCheckThread || deadThread || state->stepThread == L )
{
//printf( "event %d, line %d\n", ar->event, ar->currentline );
//luaL_dostring( L, "print( debug.traceback() )" );
int stepDepth = -1;
if( deadThread )
{
// always break if the tracked coroutine is dead
}
else
{
updateCallstackDepth( L, state );
stepDepth = state->callstackDepth - state->initialCallstackDepth;
}
if( state->stepMode == SM_Inside )
{
if( ar->currentline >= 0 || stepDepth != 0 ) // reject useless emulated HOOKLINE events
needBreak = true;
}
else if( state->stepMode == SM_Over && stepDepth <= 0 && ar->event == LUA_HOOKLINE )
{
lua_getinfo( L, "S", ar );
if( ar->currentline != state->lastBreakLine || ar->source != state->lastBreakFile ) // don't break twice on the same line in step over mode
{
if( ar->currentline >= 0 || stepDepth < 0 ) // reject useless emulated HOOKLINE events
needBreak = true;
}
}
else if( state->stepMode == SM_Outside && stepDepth < 0 )
needBreak = true;
}
}
// check if we have hit a breakpoint
if( !needBreak && ar->event == LUA_HOOKLINE )
{
lua_getinfo( L, "S", ar );
#ifdef GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS
if( ar->source == state->currentFile )
{
lua_lock( L );
setobj2s( L, L->top, &state->currentFileBreakpoints );
api_incr_top( L );
lua_unlock( L );
}
else
{
lua_lock( L );
//lua_getfield( L, LUA_REGISTRYINDEX, "GRLDC_breakPointAliases" );
setobj2s( L, L->top, &state->breakpointAliases );
api_incr_top( L );
lua_unlock( L );
lua_getfield( L, -1, ar->source );
lua_remove( L, -2 );
}
#else
lua_getfield( L, LUA_REGISTRYINDEX, "GRLDC_breakPointAliases" );
lua_getfield( L, -1, ar->source );
lua_remove( L, -2 );
#endif
if( lua_isnil( L, -1 ) )
{
if( ar->source[0] == '@' )
{
int err = 0;
lua_pop( L, 1 );
lua_getglobal( L, "grldc" );
lua_getfield( L, -1, "registerSourceFile_" );
lua_remove( L, -2 );
lua_pushstring( L, ar->source );
err = lua_pcall( L, 1, 1, 0 );
if( err )
{
const char* msg = lua_tostring( L, -1 );
printf( "Error executing grldc.registerSourceFile_: %s\n", msg );
assert( false );
}
}
}
if( !lua_isnil( L, -1 ) )
{
lua_pushinteger( L, ar->currentline );
lua_gettable( L, -2 );
needBreak = (lua_toboolean( L, -1 ) != 0);
lua_pop( L, 1 );
}
#ifdef GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS
if( state->currentFile != ar->source )
{
state->currentFile = ar->source;
lua_lock( L );
state->currentFileBreakpoints = *(L->top-1);
lua_unlock( L );
}
#endif
lua_pop( L, 1 );
}
// break execution, if needed
if( needBreak )
{
int err = 0;
updateCallstackDepth( L, state );
lua_getinfo( L, "Sl", ar );
state->lastBreakFile = ar->source;
state->lastBreakLine = ar->currentline;
lua_getglobal( L, "grldc" );
lua_getfield( L, -1, "breakNow" );
lua_remove( L, -2 );
err = lua_pcall( L, 0, 0, 0 );
if( err )
{
const char* msg = lua_tostring( L, -1 );
printf( "Error executing grldc.breakNow: %s\n", msg );
assert( false );
}
}
}
int GRLDCI_setHook( lua_State* L )
{
lua_State* co = lua_tothread( L, -1 );
lua_sethook( co, hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 0 );
return 0;
}
int GRLDCI_setHookActive( lua_State* L )
{
DebugState* state = getDebugState( L );
state->hookActive = (lua_toboolean( L, -1 ) != 0);
if( state->hookActive )
state->inLdb = true;
//unsigned char oldAllowHook = L->allowhook;
//L->allowhook = 0;
//luaL_dostring( L, "print( debug.traceback() )" );
//L->allowhook = oldAllowHook;
return 0;
}
int GRLDCI_setStepMode( lua_State* L )
{
DebugState* state = getDebugState( L );
state->stepMode = (StepMode)lua_tointeger( L, -2 );
state->stepThread = lua_tothread( L, -1 );
return 0;
}
int GRLDCI_setStepDepth( lua_State* L )
{
DebugState* state = getDebugState( L );
int stepDepth = lua_tointeger( L, -1 );
//updateCallstackDepth( L, state );
state->initialCallstackDepth = state->callstackDepth - stepDepth;
assert( state->initialCallstackDepth >= 0 );
return 0;
}
int GRLDCI_init( lua_State* L )
{
DebugState* state = getDebugState( L );
lua_pushvalue( L, -1 );
assert( lua_istable( L, -1 ) );
#ifdef GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS
lua_lock( L );
state->breakpointAliases = *(L->top-1);
lua_unlock( L );
#endif
lua_setfield( L, LUA_REGISTRYINDEX, "GRLDC_breakPointAliases" );
return 0;
}
const luaL_Reg GRLDClib[] =
{
#if LUA_VERSION_NUM < 502
{ "getmainthread", GRLDC_getmainthread },
#endif
{ NULL, NULL }
};
const luaL_Reg GRLDCIlib[] = // internal functions
{
{ "setHook", GRLDCI_setHook },
{ "setHookActive", GRLDCI_setHookActive },
{ "setStepMode", GRLDCI_setStepMode },
{ "setStepDepth", GRLDCI_setStepDepth },
{ "init", GRLDCI_init },
{ NULL, NULL }
};
void registerLuaLib( lua_State* L, const char* libName, const char* code, int codeSize )
{
char sourceName[128];
int res = 0;
lua_getglobal( L, "package" );
lua_getfield( L, -1, "preload" );
sprintf( sourceName, "%s embedded code", libName );
res = luaL_loadbuffer( L, code, codeSize, sourceName );
if(res == LUA_ERRSYNTAX)
{
const char* message = lua_tostring( L, -1 );
printf("syntax error: %s\n", message);
}
else if (res == LUA_ERRMEM)
{
printf("memory error\n");
}
assert( res == 0 );
lua_setfield( L, -2, libName );
lua_pop( L, 3 );
};
// declare embedded source accessors (they are implemented in the corresponding cpp file)
const char* GRLDC_getldbCode();
int GRLDC_getldbCodeSize();
const char* GRLDC_getutilitiesCode();
int GRLDC_getutilitiesCodeSize();
const char* GRLDC_getnetCode();
int GRLDC_getnetCodeSize();
const char* GRLDC_getsocketCode();
int GRLDC_getsocketCodeSize();
int luaopen_grldc( lua_State* L )
{
DebugState* state = (DebugState*)lua_newuserdata( L, sizeof( DebugState ) );
const char* ldbCode = NULL;
char* ldbDCode = NULL;
int i;
int res = 0;
state->hookActive = false;
#ifndef LUA_VM_LUAJIT
state->hookLineEmulationEnabled = false;
#endif
state->lastRunningUpdate = 0;
state->stepMode = SM_None;
state->stepThread = NULL;
state->callstackDepth = state->initialCallstackDepth = 1;
state->inLdb = true;
state->lastBreakLine = -100;
#ifdef GRLD_ENABLE_STANDARD_LUA_VM_OPTIMIZATIONS
state->breakpointAliases.tt = LUA_TNIL;
state->currentFileBreakpoints.tt = LUA_TNIL;
state->currentFile = NULL;
#endif
lua_setfield( L, LUA_REGISTRYINDEX, "GRLDC_DebugState" );
// register dependent libraries
registerLuaLib( L, "grldc.utilities", GRLDC_getutilitiesCode(), GRLDC_getutilitiesCodeSize() );
registerLuaLib( L, "grldc.net", GRLDC_getnetCode(), GRLDC_getnetCodeSize() );
registerLuaLib( L, "grldc.socket", GRLDC_getsocketCode(), GRLDC_getsocketCodeSize() );
// public GRLDC functions
luaL_register(L, LUA_GRLDCLIBNAME, GRLDClib);
// internal GRLDC functions (stored in GRLDC.internal_ table)
lua_newtable( L );
lua_pushvalue( L, -1 );
lua_setfield( L, -3, "internal_" );
luaL_register(L, NULL, GRLDCIlib );
lua_pop( L, 1 );
// add lua functions to the module
ldbCode = GRLDC_getldbCode();
res = luaL_loadbuffer( L, ldbCode, GRLDC_getldbCodeSize(), "ldb embedded code" );
lua_remove( L, -2 );
assert( res == 0 );
lua_call( L, 0, 0 );
return 1; // return GRLDC table
}

51
client/src/grldc.h

@ -0,0 +1,51 @@
// Copyright (C) 2010-2016 Youen Toupin.
// This file is part of GRLD, a Graphical Remote Lua Debugger
// GRLD is distributed under the MIT license (http://www.opensource.org/licenses/mit-license.html), a copy of which is included below.
/*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _GRLD_GRLDC_h_
#define _GRLD_GRLDC_h_
#ifdef _LIB
#define GRLDC_API
#else
#ifdef GRLDC_EXPORTS
#define GRLDC_API __declspec(dllexport)
#else
#define GRLDC_API __declspec(dllimport)
#endif
#endif
typedef struct lua_State lua_State;
#ifdef __cplusplus
extern "C" {
#endif
GRLDC_API int luaopen_grldc( lua_State* L );
#ifdef __cplusplus
}
#endif
#endif // _GRLD_GRLDC_h_

808
client/src/grldc_ldb.lua

@ -0,0 +1,808 @@
-- see copyright notice in grldc.h
local debug = require( "debug" )
local net = require( "grldc.net" )
local socket = require( "grldc.socket" )
local utilities = require( "grldc.utilities" )
local assert = assert
local print = print
local type = type
local debug = debug
local xpcall = xpcall
local pcall = pcall
local tostring = tostring
local string = string
local table = table
local unpack = unpack
local error = error
local setmetatable = setmetatable
local getmetatable = getmetatable
local coroutine = coroutine
local pairs = pairs
local ipairs = ipairs
local loadstring = loadstring
local originalCoroutineCreate = coroutine.create
local globals = _G
local getfenv = getfenv
local setfenv = setfenv
local findfenv = getfenv
-- luabind functions
local class_info = class_info
if getfenv == nil then
-- lua 5.2: no get/set environment
findfenv = function( f )
local idx = 1
while true do
local name, value = debug.getupvalue( f, idx )
if name == nil then break end
--print( "\""..name.."\"" )
if name == "_ENV" then return value end
idx = idx + 1
end
return nil
end
getfenv = function( f )
local env = findfenv( f )
if env == nil then
error( "Can't find function environment" )
end
return env
end
assert( setfenv == nil )
setfenv = function( f, env )
local idx = 1
while true do
local name, value = debug.getupvalue( f, idx )
if name == nil then break end
--print( "\""..name.."\"" )
if name == "_ENV" then
debug.setupvalue( f, idx, env )
return
end
idx = idx + 1
end
error( "Can't find function environment" )
end
end
module( "grldc" )
local server = nil
local status = "running"
local hookActiveCount = 0
local callstack
local coroutines = {}
setmetatable( coroutines, { __mode = "k" } )
local commands = {}
local runningCommands = {} -- commands that can be issued even when the debugged code is running
local breakPoints = {}
local breakPointAliases = {}
internal_.init( breakPointAliases )
local values = {}
local proxyMeta = {}
local envMeta = {}
local function releaseValue( id )
--print( "Releasing value with ID "..id )
assert( values[id] ~= nil )
values[id] = nil
end
local function splitValue( value )
local t = type( value )
if t == "nil" then
return { type = t, short = tostring( value ) }
elseif t == "number" then
return value
elseif t == "string" then
local maxStringLength = 48
if #value > maxStringLength then
local id = #values + 1 -- table 'values' can have holes, but this will always give a free id
--print( "Created string value with ID "..id )
values[id] = value
return { type = t, short = "\""..string.sub( value, 1, maxStringLength-3 ).."\"...", id = id }
else
return value
end
elseif t == "boolean" then
return value
elseif t == "table" then
local id = #values + 1 -- table 'values' can have holes, but this will always give a free id
--print( "Created table value with ID "..id )
values[id] = value
local res = { type = t, short = tostring( value ), id = id }
if getmetatable( value ) == proxyMeta then
res.type = "proxy"
res.short = value.short
end
return res
elseif t == "function" then
local id = #values + 1 -- table 'values' can have holes, but this will always give a free id
--print( "Created function value with ID "..id )
values[id] = value
return { type = t, short = tostring( value ), id = id }
elseif t == "thread" then
return { type = t, short = tostring( value ) }
elseif t == "userdata" then
local m = getmetatable(value)
if m and m.__luabind_class then
local tostr = m.__tostring
m.__tostring = nil -- temporarily disable tostring, so that we can get native lua info
local ok, ptr = pcall(tostring,value)
m.__tostring = tostr
_, _, ptr = string.find( ptr, "userdata: (.+)" )
local info = class_info( value )
local id = #values + 1 -- table 'values' can have holes, but this will always give a free id
values[id] = value
return { type = t, short = "[luabind] "..info.name..": "..ptr, id = id }
end
return { type = t, short = tostring(value) }
end
end
local function getValue( id )
local value = assert( values[id], "No value associated to ID "..tostring(id) )
local t = type( value )
local res
if t == "table" and getmetatable( value ) == proxyMeta then
res = {}
for _, entry in ipairs( value ) do
table.insert( res, { name = entry.name, value = splitValue( entry.value ) } )
end
elseif t == "table" then
res = {}
local meta = getmetatable( value )
if meta ~= nil then
table.insert( res, { name = "<metatable>", value = splitValue( meta ) } )
end
for k, v in pairs( value ) do
local key = splitValue(k)
local val = splitValue(v)
if type( key ) == "table" and key.id ~= nil then -- the key is a complex value
local proxy = { { name = "<key>", value = k }, { name = "<value>", value = v } }
if type( val ) == "table" then
proxy.short = val.short
else
if type( val ) == "string" then
proxy.short = "\""..val.."\""
else
proxy.short = tostring( val )
end
end
setmetatable( proxy, proxyMeta )
proxy = splitValue( proxy )
table.insert( res, { name = "["..key.short.."]", value = proxy } )
releaseValue( key.id )
if type( val ) == "table" and val.id ~= nil then
releaseValue( val.id )
end
else
local name
if type( key ) == "table" then
name = "["..key.short.."]"
else
local simpleKey = false
if type( key ) == "string" then
simpleKey = (string.find( key, "^[%a_][%a%d_]*$" ) ~= nil)
end
if simpleKey then
name = key
else
local keyStr = tostring( key )
if type( key ) == "string" then
keyStr = "\""..keyStr.."\""
end
name = "["..keyStr.."]"
end
end
table.insert( res, { name = name, value = val } )
end
end
elseif t == "function" then
res = {}
local upvaluesProxy = {}
setmetatable( upvaluesProxy, proxyMeta )
local upIdx = 1
while true do
local upName, upValue = debug.getupvalue( value, upIdx )
if upName == nil then break end
table.insert( upvaluesProxy, { name = upIdx..": "..upName, value = upValue } )
upIdx = upIdx + 1
end
local info = debug.getinfo( value, "S" )
table.insert( res, { name = "<what>", value = splitValue( info.what ) } )
if string.sub( info.source, 1, 1 ) == "@" then
table.insert( res, { name = "<source>", value = splitValue( info.source.."("..info.linedefined..")" ) } )
else
table.insert( res, { name = "<source>", value = splitValue( info.source ) } )
end
table.insert( res, { name = "<environment>", value = splitValue( findfenv( value ) ) } )
table.insert( res, { name = "<upvalues>", value = splitValue( upvaluesProxy ) } )
elseif t == "string" then
res = { { name = "<value>", value = value } }
elseif t == "userdata" then
local m = getmetatable( value )
if m and m.__luabind_class then
local info = class_info( value )
local res = {}
table.insert( res, { name = "<class methods>", value = splitValue( info.methods ) } )
for _, attrName in pairs( info.attributes ) do
table.insert( res, { name = attrName, value = splitValue( value[attrName] ) } )
end
return res
else
error( "Unknown value type: "..t.." (value = "..tostring( value )..")" )
end
else
error( "Unknown value type: "..t.." (value = "..tostring( value )..")" )
end
if res[1] == nil then
res[1] = { name = "<empty>" }
end
return res
end
local function checkClosed( f, ... )
local results = { xpcall( f, function( msg ) if msg == "closed" then return msg end return debug.traceback( msg ) end ) }
if not results[1] then
if results[2] == "closed" then
print( "Connection with debugger lost" )
server = nil
else
error( results[2], 0 )
end
return ...
end
return unpack( results, 2 )
end
local function synchronize()
print( "sending synchronization request..." )
server:send( "synchronize" )
print( "receiving breakpoints..." )
local numBreakpoints = server:receive()
print( tostring(numBreakpoints).." breakpoint(s)" )
assert( numBreakpoints == 0 ) -- not yet implemented
local breakOnConnection = server:receive()
return breakOnConnection
end
function updateRunningRequests_()
while true do
if server == nil then break end
local command = server:tryReceive( "running" )
if command == nil then break end
local func = runningCommands[command]
assert( func ~= nil, "Unknown running command: "..tostring( command ) )
local ok, msg = xpcall( func, debug.traceback )
if not ok then
print( "Error processing running command "..command..": "..tostring( msg ) )
end
end
end
function registerSourceFile_( fileName )
local nsource = "@"..utilities.normalizePath( string.sub( fileName, 2 ) )
s = breakPoints[nsource]
if s == nil then
s = {}
breakPoints[nsource] = s
end
breakPointAliases[fileName] = s
return s
end
local function getinfo( thread, level, what )
if type(level) ~= "function" then
level = level + 1 -- do not count ourself
end
if thread == nil then
thread = getmainthread()
end
return debug.getinfo( thread, level, what )
end
local function getlocal( thread, level, idx )
level = level + 1 -- do not count ourself
if thread == nil then
thread = getmainthread()
end
return debug.getlocal( thread, level, idx )
end
local function setlocal( thread, level, idx, value )
level = level + 1 -- do not count ourself
if thread == nil then
thread = getmainthread()
end
return debug.setlocal( thread, level, idx, value )
end
function getAppLevel_( thread, fromLevel )
-- find where the application code starts in the callstack (we want to ignore grldc functions)
local level = (fromLevel or 1) + 1
local appLevel
local grldcFunction = { [breakNow] = true, [connect] = true, [globals.coroutine.create] = true, [updateRunningRequests_] = true }
--[[print( "GRLDC functions:" )
for f in pairs( grldcFunction ) do
print( "\t"..tostring(f).." ("..tostring(getinfo(thread,f,"nf").name)..")" )
end
print( "Current stack:" )]]
while true do
local info = getinfo( thread, level, "f" )
if info == nil then break end
--print( "\t"..level.." "..tostring(info.func).." ("..tostring(info.name)..")" )
if grldcFunction[info.func] then appLevel = level end -- actual appLevel is level + 1, but we don't count ourself
level = level + 1
end
return appLevel
end
local function getCallstack( thread )
local appLevel = getAppLevel_( thread )
if appLevel == nil then appLevel = 0 end
local callstack = {}
local level = appLevel
while true do
local info = getinfo( thread, level, "nSl" )
if info == nil then break end
level = level + 1
local data =
{
name = info.name,
namewhat = info.namewhat,
what = info.what,
source = info.source,
line = info.currentline,
}
table.insert( callstack, data )
end
return callstack
end
local function setHook()
hookActiveCount = hookActiveCount + 1
if hookActiveCount == 1 then
internal_.setHookActive( true )
end
end
local function removeHook()
hookActiveCount = hookActiveCount - 1
if hookActiveCount == 0 then
internal_.setHookActive( false )
end
--debug.sethook( nil )
end
function suspendHook()
removeHook()
end
function resumeHook()
setHook()
end
local function registerCoroutine( co )
--debug.sethook( co, hook, "crl" )
internal_.setHook( co )
coroutines[co] = {}
end
globals.coroutine.create = function( f )
local co = originalCoroutineCreate( f )
registerCoroutine( co )
return co
end
local function setBreakPoint( source, line, value )
assert( string.sub( source, 1, 1 ) == "@" )
local nsource = "@"..utilities.normalizePath( string.sub( source, 2 ) )
assert( nsource == source, "Source must be normalized before setting a breakpoint, but source "..source.." is not normalized to "..nsource )
print( "Setting breakpoint at "..source.."("..line..") to "..tostring( value ) )
local s = breakPoints[source]
if s == nil then s = {} breakPoints[source] = s end
if value then
s[line] = true
else
s[line] = nil
end
end
function connect( address, port, name, maxRetry )
local retryCount = maxRetry
assert( name ~= nil )
assert( server == nil, "Already connected" )
print( "grldc: connecting to GRLD server..." )
while true do
local ok, msg = pcall( function()
server = net.connect( address, port )
end )
if ok then break end
if not ok and msg ~= "connection refused" then
error( msg )
end
if maxRetry ~= nil then
retryCount = retryCount - 1
if retryCount < 0 then
print( "grldc: can't connect to GRLD server after "..(maxRetry+1).." attempt(s) ; debugging disabled" )
return false
end
end
end
print( "grldc module connected to the GRLD server" )
checkClosed( function()
print( "sending client name..." )
server:send( name )
print( "synchronizing with server..." )
local breakOnConnection = synchronize()
local co, mainthread = coroutine.running()
assert( co == nil or mainthread, "Connection to the debugger must be done from the main thread" )
if mainthread then
-- lua 5.2: we can access the main thread directly
getmainthread = function() return co end
end
print( "setting debug hook..." )
internal_.setHook( getmainthread() )
print( "hook set" )
setHook()
if breakOnConnection then
breakNow()
end
end )
return true
end
local function breakNowImpl()
assert( status == "running" )
status = "break"
internal_.setStepMode( 0, nil )
server:send( "break" )
--assert( server:receive() == "ack_break" )
callstack = getCallstack( coroutine.running() )
server:send( callstack[1].source )
server:send( callstack[1].line )
while status == "break" do
--print( "waiting data..." )
server:waitData()
--print( "received data" )
updateRunningRequests_()
local command = server:tryReceive()
if command ~= nil then
assert( commands[command] ~= nil, "Received unknown command: "..tostring(command) )
commands[command]()
end
end
callstack = nil
end
local function getCoroutineId( co )
if co == nil then
return "main"
else
local _, _, id = string.find( tostring( co ), "thread: (.*)" )
assert( id ~= nil )
return id
end
end
local function getCoroutineFromId( id )
if id == "current" then
return coroutine.running()
else
local co = nil
if id ~= "main" then
for c, info in pairs( coroutines ) do
if coroutine.status( c ) ~= "dead" and id == getCoroutineId( c ) then
co = c
break
end
end
if co == nil then
return "no such coroutine"
end
end
return co
end
end
function commands.run()
--server:send( "ack_run" )
status = "running"
--assert( stepMode == nil )
end
function commands.stepover()
--server:send( "ack_stepover" )
status = "running"
internal_.setStepMode( 2, coroutine.running() or getmainthread() )
end
function commands.stepin()
--server:send( "ack_stepin" )
status = "running"
internal_.setStepMode( 1, nil )
end
function commands.stepout()
--server:send( "ack_stepout" )
status = "running"
internal_.setStepMode( 3, coroutine.running() or getmainthread() )
end
function commands.callstack()
local thread = server:receive()
if thread == "current" then
server:send( callstack )
else
local co = getCoroutineFromId( thread )
if type( co ) ~= "string" then
server:send( getCallstack( co ) )
else
server:send( co )
end
end
end
function commands.coroutines()
local res = {}
for co, info in pairs( coroutines ) do
if coroutine.status( co ) ~= "dead" then
local id = getCoroutineId( co )
table.insert( res, { id = id } )
end
end
server:send( res )
end
function commands.currentthread()
server:send( getCoroutineId( coroutine.running() ) )
end
function commands.breakpoints()
server:send( breakPoints )
end
function commands.locals()
local res = {}
local thread = server:receive()
local level = server:receive()
local co = getCoroutineFromId( thread )
if type( co ) ~= "string" then
local idx = 1
local appLevel = getAppLevel_( co, 1 )
if appLevel == nil then
appLevel = 0
end
level = level + appLevel - 1
while true do
local name, value = getlocal( co, level, idx )
if name == nil then break end
if name ~= "(*temporary)" then
table.insert( res, { name = name, value = splitValue( value ) } )
end
idx = idx + 1
end
server:send( res )
else
server:send( "no such coroutine" )
end
end
function commands.upvalues()
local res = {}
local thread = server:receive()
local level = server:receive()
local co = getCoroutineFromId( thread )
if type( co ) ~= "string" then
local idx = 1
local appLevel = getAppLevel_( co, 1 )
if appLevel == nil then
appLevel = 0
end
level = level + appLevel - 1
local info = getinfo( co, level, "f" )
while true do
local name, value = debug.getupvalue( info.func, idx )
if name == nil then break end
table.insert( res, { name = name, value = splitValue( value ) } )
idx = idx + 1
end
server:send( res )
else
server:send( "no such coroutine" )
end
end
function commands.evaluate()
local expr = server:receive()
local thread = server:receive()
local level = server:receive()
local co = getCoroutineFromId( thread )
if type( co ) ~= "string" then
if string.sub( expr, 1, 1 ) == "=" then
expr = "return "..string.sub( expr, 2 )
end
local ok, results = pcall( function()
local f = assert( loadstring( expr ) )
local appLevel = getAppLevel_( co, 1 )
if appLevel == nil then
appLevel = 0
end
local orgLevel = level
level = level + appLevel - 1
local info = getinfo( co, level, "f" )
local upvalues = {}
local idx = 1
while true do
local name, value = debug.getupvalue( info.func, idx )
if name == nil then break end
upvalues[name] = idx
idx = idx + 1
end
local locals = {}
idx = 1
while true do
local name, value = getlocal( co, level, idx )
if name == nil then break end
locals[name] = idx
idx = idx + 1
end
local env = setmetatable( { func = info.func, thread = co, level = orgLevel, locals = locals, upvalues = upvalues, environment = getfenv( info.func ) }, envMeta )
setfenv( f, env )
return { f() }
end )
if ok then
local res = {}
local lastResult = 0 -- TODO : check if there is a way to know the actual number of results, even if the last ones are nil values
for idx, value in pairs( results ) do
if idx > lastResult then lastResult = idx end
res[idx] = { name = "result #"..tostring(idx), value = splitValue( value ) }
end
for idx = 1, lastResult - 1 do
if res[idx] == nil then
res[idx] = { name = "result #"..tostring(idx), value = splitValue( nil ) }
end
end
if res[1] == nil then
res[1] = { name = "<no result>" }
end
server:send( res )
else
server:send( { { name = "<error>", value = splitValue( results ) } } )
end
else
server:send( { { name = "<error>", value = "no such coroutine" } } )
end
end
envMeta.__index = function( self, key )
if key == "__globals__" then
return globals
elseif key == "_G" then
return self
end
local lv = self.locals[key]
if lv ~= nil then
local appLevel = getAppLevel_( self.thread, 1 )
if appLevel == nil then
appLevel = 0
end
level = self.level + appLevel - 1
local k, v = getlocal( self.thread, level, lv )
return v
end
local uv = self.upvalues[key]
if uv ~= nil then
local k, v = debug.getupvalue( self.func, uv )
return v
end
return self.environment[key]
end
envMeta.__newindex = function( self, key, value )
if key == "__globals__" then
globals[key] = value
return
elseif key == "_G" then
error( "Can't override _G when remotely evaluating an expression" )
end
local lv = self.locals[key]
if lv ~= nil then
local appLevel = getAppLevel_( self.thread, 1 )
if appLevel == nil then
appLevel = 0
end
level = self.level + appLevel - 1
setlocal( self.thread, level, lv, value )
return
end
local uv = self.upvalues[key]
if uv ~= nil then
debug.setupvalue( self.func, uv, value )
return
end
self.environment[key] = value
end
function commands.getValue()
local id = server:receive()
server:send( getValue( id ) )
end
function runningCommands.releaseValue()
local id = server:receive( "running" )
releaseValue( id )
end
runningCommands["break"] = function()
if status == "running" then
breakNow()
else
print( "Break command ignored: already breaked" )
end
end
runningCommands.setbreakpoint = function()
local data = server:receive( "running" )
setBreakPoint( data.source, data.line, data.value )
end
function breakNow()
removeHook()
print( "Breaking execution..." )
while true do
if server == nil then
print( "Can't break execution: not connected to a debugger" )
return
end
local ok, msg = xpcall( breakNowImpl,
function( msg )
if msg == "closed" then return msg end
return debug.traceback( msg )
end
)
if ok then
break
else
if msg == "closed" then
print( "Connection with debugger lost" )
server = nil
break
else
print( "Error during break: "..msg )
end
end
socket.sleep( 0.1 )
status = "running"
end
print( "Resuming execution..." )
internal_.setStepDepth( 0 )
setHook()
end

1404
client/src/grldc_ldb.lua.c

File diff suppressed because it is too large Load Diff

376
client/src/grldc_net.lua.c

@ -0,0 +1,376 @@
// This file contains lua code encoded from ../../shared/grldc/net.lua
// Use script embed.lua.bat to re-generate this file if you changed the source code
const char* GRLDC_getnetCode()
{
static unsigned char code[] =
{
0x2d, 0x2d, 0x20, 0x73, 0x65, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x67, 0x72, 0x6c, 0x64, 0x63,
0x2e, 0x68, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x6f, 0x63, 0x6b,
0x65, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x20, 0x22, 0x67,
0x72, 0x6c, 0x64, 0x63, 0x2e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x20, 0x29, 0x0d, 0x0a,
0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x20, 0x3d,
0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73,
0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65,
0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x0d,
0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65,
0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74,
0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20,
0x3d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65,
0x20, 0x3d, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x0d, 0x0a, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x5f,
0x47, 0x0d, 0x0a, 0x0d, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x28, 0x20, 0x22, 0x67, 0x72,
0x6c, 0x64, 0x63, 0x2e, 0x6e, 0x65, 0x74, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
0x20, 0x3d, 0x20, 0x7b, 0x20, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x7b,
0x7d, 0x20, 0x7d, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x5f, 0x5f,
0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
0x65, 0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x2e, 0x2e, 0x2e, 0x20,
0x29, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x20, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x20,
0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65,
0x72, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28,
0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x73,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x28, 0x20, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x2c, 0x20, 0x22, 0x5b, 0x5e, 0x25, 0x2e, 0x2c, 0x25, 0x2d, 0x30, 0x2d, 0x39, 0x5d, 0x22,
0x20, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a,
0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, 0x2f, 0x30, 0x20,
0x65, 0x6e, 0x64, 0x22, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65,
0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e,
0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22,
0x74, 0x72, 0x75, 0x65, 0x22, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x22, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x22, 0x0d, 0x0a, 0x09, 0x65, 0x6c,
0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28,
0x20, 0x22, 0x25, 0x71, 0x22, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a,
0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x74, 0x61,
0x62, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x7b, 0x20, 0x22, 0x0d, 0x0a, 0x09,
0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x20, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69,
0x72, 0x73, 0x28, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x20, 0x64, 0x6f, 0x0d, 0x0a,
0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x2e, 0x2e, 0x22, 0x5b,
0x22, 0x2e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x20, 0x6b, 0x20,
0x29, 0x2e, 0x2e, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x65, 0x28, 0x20, 0x76, 0x20, 0x29, 0x2e, 0x2e, 0x22, 0x2c, 0x20, 0x22, 0x0d,
0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20,
0x72, 0x65, 0x73, 0x2e, 0x2e, 0x22, 0x20, 0x7d, 0x22, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a,
0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x20, 0x22, 0x43, 0x61, 0x6e, 0x27, 0x74, 0x20,
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x22, 0x2e, 0x2e, 0x74, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x69,
0x78, 0x55, 0x70, 0x28, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x20, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d,
0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09,
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0d,
0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x20, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70,
0x61, 0x69, 0x72, 0x73, 0x28, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x29, 0x20, 0x64, 0x6f,
0x0d, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x5b, 0x66, 0x69, 0x78, 0x55, 0x70, 0x28, 0x6b,
0x29, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x78, 0x55, 0x70, 0x28, 0x76, 0x29, 0x0d, 0x0a, 0x09,
0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72,
0x65, 0x73, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3d, 0x3d,
0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x28, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x64, 0x65, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x20, 0x73, 0x74,
0x72, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20,
0x6c, 0x6f, 0x61, 0x64, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x20, 0x22, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x22, 0x2e, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x69,
0x66, 0x20, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x69, 0x78, 0x55, 0x70, 0x28, 0x20, 0x72, 0x65, 0x73,
0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x28, 0x20, 0x22, 0x55, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70,
0x61, 0x72, 0x73, 0x65, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x22, 0x2e, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x28, 0x73, 0x74, 0x72, 0x29, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20,
0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73,
0x65, 0x6c, 0x66, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x20, 0x3d, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x20,
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x20,
0x7d, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65,
0x28, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72,
0x4d, 0x65, 0x74, 0x61, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
0x73, 0x65, 0x6c, 0x66, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4d, 0x65,
0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x61, 0x63, 0x63, 0x65, 0x70,
0x74, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x20,
0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a,
0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65,
0x73, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09,
0x09, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x20, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x73,
0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x20, 0x72, 0x65, 0x73,
0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61,
0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x73, 0x3a, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x28,
0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x28, 0x20, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a,
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x3d, 0x20, 0x7b, 0x20,
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x6f, 0x63,
0x6b, 0x65, 0x74, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x28, 0x20, 0x61, 0x64, 0x64,
0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x20, 0x7d, 0x0d, 0x0a,
0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x2e, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
0x2e, 0x2e, 0x22, 0x3a, 0x22, 0x2e, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09,
0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x20, 0x73, 0x65,
0x6c, 0x66, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65,
0x74, 0x61, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x69, 0x6e, 0x69, 0x74,
0x5f, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c,
0x66, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74,
0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x28,
0x29, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x64, 0x5f, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a,
0x67, 0x65, 0x74, 0x70, 0x65, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x09,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x67, 0x65, 0x74, 0x70, 0x65, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x73, 0x65, 0x6e,
0x64, 0x28, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
0x20, 0x29, 0x0d, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x63,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x22, 0x0d, 0x0a, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x74,
0x28, 0x20, 0x22, 0x53, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x2e, 0x74, 0x6f,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x29, 0x2e, 0x2e,
0x22, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x22, 0x2e, 0x2e,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x73, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x69, 0x7a, 0x65, 0x28, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x63, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x2e, 0x22, 0x5c, 0x6e, 0x22, 0x2e, 0x2e, 0x28, 0x23, 0x73, 0x64,
0x61, 0x74, 0x61, 0x29, 0x2e, 0x2e, 0x22, 0x5c, 0x6e, 0x22, 0x2e, 0x2e, 0x73, 0x64, 0x61, 0x74,
0x61, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x2c, 0x20, 0x6d,
0x73, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x28, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65,
0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x3d, 0x20,
0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x28, 0x20, 0x6d, 0x73, 0x67, 0x2c, 0x20, 0x30, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6c,
0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73,
0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x77,
0x61, 0x69, 0x74, 0x44, 0x61, 0x74, 0x61, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b,
0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x67, 0x6c,
0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x73, 0x75, 0x73, 0x70,
0x65, 0x6e, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
0x6c, 0x64, 0x63, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x6f,
0x61, 0x64, 0x65, 0x64, 0x2c, 0x20, 0x77, 0x65, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f,
0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67,
0x20, 0x68, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65,
0x69, 0x76, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x62, 0x65,
0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6f, 0x6b, 0x20, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x72,
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x67,
0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x73, 0x75, 0x73,
0x70, 0x65, 0x6e, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x6e, 0x65,
0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x3d, 0x20, 0x74,
0x72, 0x75, 0x65, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x68, 0x61, 0x73, 0x44, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73,
0x65, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x5f, 0x2c, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69,
0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x20, 0x73, 0x65,
0x6c, 0x66, 0x2e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x20, 0x29, 0x20, 0x64,
0x6f, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x23, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x64, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x68,
0x61, 0x73, 0x44, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0d, 0x0a, 0x09,
0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x68, 0x61, 0x73, 0x44, 0x61, 0x74,
0x61, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x65, 0x65,
0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x72,
0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x75,
0x70, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73,
0x2e, 0x2e, 0x2e, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x5f, 0x28, 0x20, 0x6e,
0x69, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65,
0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x67, 0x6c,
0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x72, 0x65, 0x73, 0x75,
0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x65, 0x6e,
0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69,
0x6e, 0x64, 0x65, 0x78, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x20, 0x63, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
0x6c, 0x20, 0x3d, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x22,
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x0d, 0x0a, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67,
0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67,
0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x6e,
0x6e, 0x65, 0x6c, 0x20, 0x22, 0x2e, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20,
0x73, 0x65, 0x6c, 0x66, 0x3a, 0x70, 0x6f, 0x70, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
0x5f, 0x28, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x77,
0x68, 0x69, 0x6c, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c,
0x20, 0x64, 0x6f, 0x0d, 0x0a, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x5f, 0x28, 0x20, 0x6e, 0x69, 0x6c,
0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c,
0x66, 0x3a, 0x70, 0x6f, 0x70, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x28, 0x20,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x72,
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x22, 0x2e, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x28, 0x64, 0x61, 0x74, 0x61, 0x29, 0x2e, 0x2e, 0x22, 0x20, 0x6f, 0x6e, 0x20,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x22, 0x2e, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e,
0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x61,
0x74, 0x61, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65,
0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x74, 0x72, 0x79, 0x52, 0x65,
0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x63, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
0x22, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d,
0x20, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x70, 0x6f, 0x70, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x64, 0x5f, 0x28, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09,
0x69, 0x66, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x5f, 0x28, 0x20, 0x30, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x09, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x3a,
0x70, 0x6f, 0x70, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x28, 0x20, 0x63, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09,
0x69, 0x66, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e,
0x74, 0x28, 0x20, 0x22, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x22, 0x2e, 0x2e,
0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x64, 0x61, 0x74, 0x61, 0x29, 0x2e, 0x2e,
0x22, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x22, 0x2e, 0x2e,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d,
0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x65,
0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f,
0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e,
0x6e, 0x65, 0x6c, 0x73, 0x5f, 0x28, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73,
0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0d,
0x0a, 0x09, 0x69, 0x66, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c,
0x64, 0x63, 0x2e, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x7e,
0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x2d, 0x2d,
0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x2c, 0x20, 0x77, 0x65, 0x20,
0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x74, 0x68,
0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x68, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x6f, 0x20,
0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65,
0x20, 0x68, 0x6f, 0x6f, 0x6b, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79,
0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f,
0x6f, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72,
0x6c, 0x64, 0x63, 0x2e, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x48, 0x6f, 0x6f, 0x6b, 0x28,
0x29, 0x0d, 0x0a, 0x09, 0x09, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48,
0x6f, 0x6f, 0x6b, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64,
0x0d, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20,
0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66,
0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x74, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09,
0x69, 0x66, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69,
0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x74, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x69,
0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67, 0x72,
0x6c, 0x64, 0x63, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x28, 0x29,
0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0d, 0x0a,
0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x69, 0x7a,
0x65, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x7e,
0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65,
0x62, 0x75, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x72, 0x65, 0x63, 0x65, 0x69,
0x76, 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x73, 0x69,
0x7a, 0x65, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76,
0x65, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x73, 0x69, 0x7a, 0x65,
0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09,
0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x20, 0x74,
0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x29, 0x20,
0x29, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d,
0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x64, 0x61, 0x74, 0x61,
0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09,
0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f,
0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2e, 0x67,
0x72, 0x6c, 0x64, 0x63, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x28,
0x29, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x20,
0x6d, 0x73, 0x67, 0x2c, 0x20, 0x30, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
0x09, 0x69, 0x66, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x3d, 0x3d, 0x20, 0x22,
0x6b, 0x61, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x73,
0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x6b,
0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x77, 0x65, 0x20, 0x73, 0x69, 0x6d,
0x70, 0x6c, 0x79, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20,
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d,
0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x64, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x64, 0x5f, 0x5b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5d, 0x0d, 0x0a, 0x09, 0x09, 0x69,
0x66, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69,
0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x63, 0x65, 0x69,
0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6c,
0x66, 0x2e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x5b, 0x63, 0x68, 0x61, 0x6e,
0x6e, 0x65, 0x6c, 0x5d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x0d,
0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
0x2c, 0x20, 0x64, 0x65, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x28, 0x20, 0x64,
0x61, 0x74, 0x61, 0x20, 0x29, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67,
0x50, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x20, 0x22,
0x2e, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x64, 0x61, 0x74, 0x61, 0x29,
0x2e, 0x2e, 0x22, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x22,
0x2e, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e,
0x64, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d,
0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61,
0x6c, 0x73, 0x2e, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x48,
0x6f, 0x6f, 0x6b, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65,
0x78, 0x3a, 0x70, 0x6f, 0x70, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x28, 0x20,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c,
0x66, 0x2e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x5b, 0x63, 0x68, 0x61, 0x6e,
0x6e, 0x65, 0x6c, 0x5d, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76,
0x65, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x63, 0x65,
0x69, 0x76, 0x65, 0x64, 0x5b, 0x31, 0x5d, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73,
0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x74, 0x61,
0x62, 0x6c, 0x65, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x20, 0x72, 0x65, 0x63, 0x65,
0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x31, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
};
return (const char*)code;
}
int GRLDC_getnetCodeSize()
{
return 5789;
}

190
client/src/grldc_socket.lua.c

@ -0,0 +1,190 @@
// This file contains lua code encoded from ../../shared/grldc/socket.lua
// Use script embed.lua.bat to re-generate this file if you changed the source code
const char* GRLDC_getsocketCode()
{
static unsigned char code[] =
{
0x2d, 0x2d, 0x20, 0x73, 0x65, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x67, 0x72, 0x6c, 0x64, 0x63,
0x2e, 0x68, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x70, 0x70,
0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x61, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x75, 0x61, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x47, 0x52, 0x4c, 0x44, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x73, 0x69, 0x65, 0x72,
0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c, 0x75, 0x61, 0x20, 0x73, 0x6f, 0x63, 0x6b,
0x65, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70,
0x6f, 0x72, 0x74, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x6f, 0x63,
0x6b, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x20, 0x22,
0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
0x3d, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x69,
0x70, 0x61, 0x69, 0x72, 0x73, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x61, 0x62,
0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72,
0x74, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x3d,
0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72,
0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0d, 0x0a,
0x0d, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x28, 0x20, 0x22, 0x67, 0x72, 0x6c, 0x64, 0x63,
0x2e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
0x20, 0x3d, 0x20, 0x7b, 0x20, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x7b,
0x7d, 0x20, 0x7d, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x5f, 0x5f,
0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x20,
0x74, 0x69, 0x6d, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e,
0x73, 0x6c, 0x65, 0x65, 0x70, 0x28, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x65,
0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x57, 0x61, 0x69, 0x74, 0x20, 0x75, 0x6e,
0x74, 0x69, 0x6c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
0x63, 0x76, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65,
0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x74,
0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x65,
0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x20, 0x28, 0x69, 0x66, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f,
0x75, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x77, 0x61, 0x69, 0x74, 0x20,
0x66, 0x6f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x20, 0x72, 0x65, 0x63, 0x76, 0x74,
0x2c, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d,
0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x5f, 0x2c, 0x20, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x20, 0x72, 0x65, 0x63, 0x76, 0x74, 0x20, 0x29, 0x20, 0x64,
0x6f, 0x0d, 0x0a, 0x09, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72,
0x74, 0x28, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x73,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x2c, 0x20,
0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29, 0x0d, 0x0a,
0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20,
0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x53, 0x65, 0x65, 0x20, 0x6c,
0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x3a, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x0d, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x20, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a,
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x20,
0x3d, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74,
0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20,
0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65,
0x6e, 0x65, 0x72, 0x3a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20,
0x30, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x6c, 0x66,
0x20, 0x3d, 0x20, 0x7b, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x20, 0x3d,
0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x20, 0x7d, 0x0d, 0x0a, 0x09, 0x73, 0x65,
0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x20, 0x73, 0x65, 0x6c, 0x66,
0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x0d, 0x0a,
0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e,
0x67, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x72, 0x6f, 0x77, 0x73,
0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x22, 0x20, 0x69, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73,
0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x28, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x28, 0x20, 0x22, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20,
0x74, 0x6f, 0x20, 0x22, 0x2e, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x2e, 0x22,
0x3a, 0x22, 0x2e, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x2e, 0x22, 0x2e, 0x2e, 0x2e, 0x22, 0x20,
0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x2c, 0x20, 0x6d,
0x73, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x28, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x70, 0x6f,
0x72, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f,
0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64,
0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x20, 0x6d, 0x73,
0x67, 0x2c, 0x20, 0x30, 0x20, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73,
0x65, 0x72, 0x74, 0x28, 0x20, 0x63, 0x6f, 0x6e, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x74, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x28,
0x20, 0x22, 0x74, 0x63, 0x70, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x22, 0x2c, 0x20,
0x74, 0x72, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72,
0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x20, 0x7d, 0x0d, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x6d,
0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x20, 0x72, 0x65, 0x73, 0x2c, 0x20, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x65, 0x6e,
0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e,
0x67, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x74, 0x2c,
0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x73, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x28, 0x6e, 0x6f, 0x20, 0x77, 0x61, 0x69, 0x74, 0x69,
0x6e, 0x67, 0x29, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x69,
0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64,
0x65, 0x78, 0x3a, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x3d, 0x20, 0x73,
0x65, 0x6c, 0x66, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x3a, 0x61, 0x63,
0x63, 0x65, 0x70, 0x74, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x20,
0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x7e,
0x3d, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0d, 0x0a, 0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x20, 0x6d, 0x73, 0x67, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x20,
0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
0x3a, 0x73, 0x65, 0x74, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x20, 0x22, 0x74, 0x63, 0x70,
0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x22, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20,
0x29, 0x0d, 0x0a, 0x09, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x74, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x28, 0x20, 0x22, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x22,
0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x72, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x20, 0x7d, 0x0d, 0x0a, 0x09, 0x73, 0x65,
0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x20, 0x72, 0x65, 0x73, 0x2c,
0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x20,
0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x0d, 0x0a,
0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f,
0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x67, 0x65, 0x74, 0x70, 0x65, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65,
0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x67, 0x65,
0x74, 0x70, 0x65, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x65, 0x6e, 0x64,
0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e,
0x64, 0x65, 0x78, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x28, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x28, 0x20,
0x64, 0x61, 0x74, 0x61, 0x20, 0x29, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d,
0x2d, 0x20, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20,
0x22, 0x5c, 0x6e, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x20, 0x69,
0x66, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x6f,
0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20,
0x69, 0x66, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
0x69, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6c,
0x6f, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x6e, 0x20,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x22, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x22, 0x0d, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a,
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x3d,
0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x20, 0x77,
0x68, 0x61, 0x74, 0x20, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
0x22, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c,
0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x72, 0x65, 0x63,
0x65, 0x69, 0x76, 0x65, 0x28, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x65, 0x6e,
0x64, 0x0d, 0x0a, 0x0d, 0x0a, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65,
0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65,
0x20, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x70,
0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74,
0x61, 0x2e, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6d,
0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29, 0x0d,
0x0a, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x3a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x20, 0x74, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x29, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
};
return (const char*)code;
}
int GRLDC_getsocketCodeSize()
{
return 2814;
}

121
client/src/grldc_utilities.lua.c

@ -0,0 +1,121 @@
// This file contains lua code encoded from ../../shared/grldc/utilities.lua
// Use script embed.lua.bat to re-generate this file if you changed the source code
const char* GRLDC_getutilitiesCode()
{
static unsigned char code[] =
{
0x2d, 0x2d, 0x20, 0x73, 0x65, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x67, 0x72, 0x6c, 0x64, 0x63,
0x2e, 0x68, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x73, 0x65,
0x72, 0x74, 0x0d, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20,
0x3d, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x0d, 0x0a, 0x0d, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
0x65, 0x28, 0x20, 0x22, 0x67, 0x72, 0x6c, 0x64, 0x63, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74,
0x69, 0x65, 0x73, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x74, 0x68,
0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x29, 0x0d, 0x0a,
0x09, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x22, 0x4e, 0x6f, 0x72, 0x6d, 0x61,
0x6c, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20,
0x31, 0x20, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x40, 0x22, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68,
0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73, 0x75, 0x62, 0x28, 0x70,
0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x29, 0x0d,
0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e,
0x6c, 0x6f, 0x77, 0x65, 0x72, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x29, 0x0d, 0x0a, 0x09,
0x0d, 0x0a, 0x09, 0x2d, 0x2d, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74,
0x68, 0x65, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x2c,
0x20, 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x75, 0x70, 0x70, 0x65,
0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x28, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x5e,
0x2e, 0x3a, 0x2f, 0x22, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d,
0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x2e, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75,
0x62, 0x28, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x29, 0x29, 0x2e, 0x2e,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x70, 0x61, 0x74, 0x68, 0x2c,
0x20, 0x32, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x31,
0x2c, 0x20, 0x31, 0x20, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x2f, 0x22, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65,
0x20, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x70, 0x61, 0x74,
0x68, 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f,
0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32,
0x20, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x2e, 0x2f, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d,
0x0a, 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x20, 0x72,
0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x6e, 0x6f,
0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x0d, 0x0a, 0x09, 0x65, 0x6c,
0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x2f,
0x22, 0x2e, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09,
0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62,
0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x29, 0x20, 0x3d,
0x3d, 0x20, 0x22, 0x2e, 0x2f, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20,
0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x2d,
0x2d, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x66, 0x73, 0x20, 0x6d, 0x6f, 0x64,
0x75, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
0x2c, 0x20, 0x77, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x72, 0x65, 0x6c,
0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x62,
0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d,
0x20, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75,
0x62, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x32, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09,
0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73,
0x75, 0x62, 0x28, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x2c, 0x20, 0x22,
0x2f, 0x22, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x2d,
0x2d, 0x61, 0x64, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x22, 0x2f, 0x22, 0x20, 0x69, 0x66, 0x20,
0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x28, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69,
0x65, 0x73, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x69, 0x6e, 0x67, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x29, 0x0d, 0x0a, 0x09, 0x69, 0x66,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x70, 0x61, 0x74, 0x68,
0x2c, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x22, 0x2f, 0x22, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x70, 0x61, 0x74, 0x68,
0x2e, 0x2e, 0x22, 0x2f, 0x22, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x0d, 0x0a,
0x09, 0x2d, 0x2d, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x22, 0x2f, 0x2f, 0x22, 0x20,
0x62, 0x79, 0x20, 0x22, 0x2f, 0x22, 0x0d, 0x0a, 0x09, 0x6e, 0x20, 0x3d, 0x20, 0x31, 0x0d, 0x0a,
0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x64, 0x6f, 0x0d,
0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73, 0x75, 0x62, 0x28, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22,
0x2f, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x31, 0x29, 0x0d, 0x0a, 0x09, 0x65,
0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x2d, 0x2d, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63,
0x65, 0x20, 0x22, 0x2f, 0x2e, 0x2f, 0x22, 0x20, 0x62, 0x79, 0x20, 0x22, 0x2f, 0x22, 0x0d, 0x0a,
0x09, 0x6e, 0x20, 0x3d, 0x20, 0x31, 0x0d, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x6e,
0x20, 0x3e, 0x20, 0x30, 0x20, 0x64, 0x6f, 0x0d, 0x0a, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x2c,
0x20, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73, 0x75, 0x62,
0x28, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x2f, 0x25, 0x2e, 0x2f, 0x22, 0x2c, 0x20, 0x22,
0x2f, 0x22, 0x2c, 0x20, 0x31, 0x29, 0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x0d,
0x0a, 0x09, 0x2d, 0x2d, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x22, 0x2f, 0x73, 0x6f,
0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x2e, 0x2e, 0x2f, 0x22, 0x20, 0x62, 0x79, 0x20,
0x22, 0x2f, 0x22, 0x0d, 0x0a, 0x09, 0x6e, 0x20, 0x3d, 0x20, 0x31, 0x0d, 0x0a, 0x09, 0x77, 0x68,
0x69, 0x6c, 0x65, 0x20, 0x6e, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x64, 0x6f, 0x0d, 0x0a, 0x09, 0x09,
0x6e, 0x20, 0x3d, 0x20, 0x30, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73,
0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x2e,
0x22, 0x0d, 0x0a, 0x09, 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74,
0x68, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x2e, 0x2e, 0x22, 0x20, 0x64, 0x6f, 0x0d,
0x0a, 0x09, 0x09, 0x09, 0x73, 0x2c, 0x20, 0x65, 0x2c, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x66, 0x69, 0x6e,
0x64, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x2f, 0x28, 0x5b, 0x5e, 0x2f, 0x5d,
0x2a, 0x29, 0x2f, 0x25, 0x2e, 0x25, 0x2e, 0x2f, 0x22, 0x2c, 0x20, 0x73, 0x2b, 0x31, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x73, 0x20,
0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0d, 0x0a, 0x09, 0x09, 0x09,
0x6e, 0x20, 0x3d, 0x20, 0x31, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70, 0x61, 0x74,
0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x2d, 0x31, 0x20, 0x29, 0x2e, 0x2e, 0x22, 0x2f, 0x22,
0x2e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70, 0x61,
0x74, 0x68, 0x2c, 0x20, 0x65, 0x2b, 0x31, 0x20, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64,
0x0d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68,
0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x20, 0x70,
0x61, 0x74, 0x68, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x2d, 0x32, 0x20, 0x29, 0x20, 0x2d, 0x2d, 0x20,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x22, 0x2f, 0x22, 0x0d, 0x0a,
0x09, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x29,
0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x61, 0x74,
0x68, 0x0d, 0x0a, 0x65, 0x6e, 0x64, 0x0d, 0x0a,
};
return (const char*)code;
}
int GRLDC_getutilitiesCodeSize()
{
return 1704;
}

15
client/src/luajit_ex.c

@ -0,0 +1,15 @@
/* see copyright notice in grldc.h */
#include "luajit_ex.h"
#ifdef LUA_VM_LUAJIT
#include "../../../luajit/src/lj_obj.h"
#include "../../../luajit/src/lj_state.h"
int lua_pushthread_ex(lua_State *L, lua_State* thread)
{
lua_pushthread( L );
setthreadV(L, L->top, thread);
return 1;
}
#endif

12
client/src/luajit_ex.h

@ -0,0 +1,12 @@
/* see copyright notice in grldc.h */
#ifndef _GRLDC_LUAJIT_EX_H_
#define _GRLDC_LUAJIT_EX_H_
#include "lua.h"
#ifdef LUA_VM_LUAJIT
int lua_pushthread_ex(lua_State *L, lua_State* thread);
#endif
#endif

28
client/visual/grldc.sln

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grldc", "grldc.vcxproj", "{1EFDD9D6-7AC5-454D-B32A-5872BA117740}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Debug|x64.ActiveCfg = Debug|x64
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Debug|x64.Build.0 = Debug|x64
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Debug|x86.ActiveCfg = Debug|Win32
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Debug|x86.Build.0 = Debug|Win32
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Release|x64.ActiveCfg = Release|x64
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Release|x64.Build.0 = Release|x64
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Release|x86.ActiveCfg = Release|Win32
{1EFDD9D6-7AC5-454D-B32A-5872BA117740}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

243
client/visual/grldc.vcxproj

@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1EFDD9D6-7AC5-454D-B32A-5872BA117740}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>grldc</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>LUA_COMPAT_MODULE;WIN32;_DEBUG;_WINDOWS;_USRDLL;GRLDC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\3rdparty\lua5.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\3rdparty\lua5.2</AdditionalLibraryDirectories>
<AdditionalDependencies>liblua52.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>
</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>LUA_COMPAT_MODULE;_DEBUG;_WINDOWS;_USRDLL;GRLDC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\3rdparty\lua5.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\3rdparty\lua5.2</AdditionalLibraryDirectories>
<AdditionalDependencies>liblua52.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>
</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>LUA_COMPAT_MODULE;WIN32;NDEBUG;_WINDOWS;_USRDLL;GRLDC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\3rdparty\lua5.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\3rdparty\lua5.2</AdditionalLibraryDirectories>
<AdditionalDependencies>liblua52.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>
</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>LUA_COMPAT_MODULE;NDEBUG;_WINDOWS;_USRDLL;GRLDC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\3rdparty\lua5.2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\3rdparty\lua5.2</AdditionalLibraryDirectories>
<AdditionalDependencies>liblua52.a;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>
</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\3rdparty\lua5.2\include\lapi.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lauxlib.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\llimits.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lmem.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lobject.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lstate.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\ltm.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lua.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lua.hpp" />
<ClInclude Include="..\3rdparty\lua5.2\include\luaconf.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lualib.h" />
<ClInclude Include="..\3rdparty\lua5.2\include\lzio.h" />
<ClInclude Include="..\src\grldc.h" />
<ClInclude Include="..\src\luajit_ex.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\grldc.c" />
<ClCompile Include="..\src\grldc_ldb.lua.c" />
<ClCompile Include="..\src\grldc_net.lua.c" />
<ClCompile Include="..\src\grldc_socket.lua.c" />
<ClCompile Include="..\src\grldc_utilities.lua.c" />
<ClCompile Include="..\src\luajit_ex.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\build\embed.lua.bat">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">call ..\build\embed.lua.bat</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Embedding lua files...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">always_generate_me</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">call ..\build\embed.lua.bat</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Embedding lua files...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">always_generate_me</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">call ..\build\embed.lua.bat</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Embedding lua files...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">always_generate_me</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">call ..\build\embed.lua.bat</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Embedding lua files...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">always_generate_me</Outputs>
</CustomBuild>
<None Include="..\src\grldc_ldb.lua" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

83
client/visual/grldc.vcxproj.filters

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="lua">
<UniqueIdentifier>{090b6d1e-9eaf-4b74-8b68-88d15d77f5cf}</UniqueIdentifier>
</Filter>
<Filter Include="grldc">
<UniqueIdentifier>{8cb57c93-bc88-4296-a89c-c8d9e2d6c5c2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\grldc.h">
<Filter>grldc</Filter>
</ClInclude>
<ClInclude Include="..\src\luajit_ex.h">
<Filter>grldc</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lapi.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lauxlib.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\llimits.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lmem.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lobject.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lstate.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\ltm.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lua.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lua.hpp">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\luaconf.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lualib.h">
<Filter>lua</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\lua5.2\include\lzio.h">
<Filter>lua</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\grldc.c">
<Filter>grldc</Filter>
</ClCompile>
<ClCompile Include="..\src\luajit_ex.c">
<Filter>grldc</Filter>
</ClCompile>
<ClCompile Include="..\src\grldc_ldb.lua.c">
<Filter>grldc</Filter>
</ClCompile>
<ClCompile Include="..\src\grldc_net.lua.c">
<Filter>grldc</Filter>
</ClCompile>
<ClCompile Include="..\src\grldc_socket.lua.c">
<Filter>grldc</Filter>
</ClCompile>
<ClCompile Include="..\src\grldc_utilities.lua.c">
<Filter>grldc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\src\grldc_ldb.lua">
<Filter>grldc</Filter>
</None>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\build\embed.lua.bat" />
</ItemGroup>
</Project>

109
doc/generate-toc.lua

@ -0,0 +1,109 @@
local firstLevel = 2
local function parseTitle( line )
local level, text
_, _, level, text = string.find( line, "<h(.)>([^<]+)</h.>" )
if level ~= nil then
level = assert( tonumber( level ) )
assert( text ~= nil )
if level >= firstLevel then
--print( level, text )
return { level = level - firstLevel + 1, text = text }
end
end
end
local function getAnchor( number )
return "section"..string.gsub( number, "%.", "_" )
end
local function createTitle( titleInfo )
local l = titleInfo.level + firstLevel - 1
return "<h"..l.." id=\""..getAnchor( titleInfo.number ).."\"> "..titleInfo.number.." "..titleInfo.text.." </h"..l..">"
end
local function createToc( titles )
local res = ""
local numeration = {}
for _, titleInfo in ipairs( titles ) do
--print( titleInfo.level, titleInfo.text )
local open = false
local numClose = 0
local prevLevel = #numeration
if titleInfo.level == prevLevel + 1 then
open = true
table.insert( numeration, 0 )
elseif titleInfo.level < prevLevel then
numClose = prevLevel - titleInfo.level
else
assert( titleInfo.level == prevLevel, "Title "..titleInfo.text.." with level "..titleInfo.level.." follows title with level "..prevLevel.." which is not a valid title sequence" )
end
if open then
res = res.."<ul>\n"
end
for i = 1, numClose do
res = res.."</ul>\n"
numeration[#numeration] = nil
end
if titleInfo.level > 0 then
numeration[titleInfo.level] = numeration[titleInfo.level] + 1
res = res.."<li>"
titleInfo.number = ""
for _, num in ipairs( numeration ) do
titleInfo.number = titleInfo.number..num.."."
end
res = res.."<a href=\"#"..getAnchor( titleInfo.number ).."\">"
res = res..titleInfo.number.." "..titleInfo.text.."</a></li>\n"
end
end
assert( #numeration == 0, "Missing closing title" )
return res
end
function generateToc( srcHtml, dstHtml )
local src = assert( io.open( srcHtml, "r" ) )
local titles = {}
while true do
local line = src:read( "*l" )
if line == nil then break end
local titleInfo = parseTitle( line )
if titleInfo ~= nil then
table.insert( titles, titleInfo )
end
end
table.insert( titles, { level = 0 } )
local nextTitle = 1
src:close()
local src = assert( io.open( srcHtml, "r" ) )
local dst = assert( io.open( dstHtml, "w" ) )
while true do
local line = src:read( "*l" )
if line == nil then break end
line = string.gsub( line, "[\n\r]+", "" )
local titleInfo = parseTitle( line )
if titleInfo ~= nil then
titleInfo = titles[nextTitle]
nextTitle = nextTitle + 1
dst:write( createTitle( titleInfo ).."\n" )
else
dst:write( line.."\n" )
end
if string.find( line, "@generated_toc@" ) ~= nil then
dst:write( createToc( titles ).."\n" )
end
end
src:close()
dst:close()
end

206
doc/index.html

@ -0,0 +1,206 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>GRLD documentation</title>
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8">
<style type="text/css">
div.content
{
max-width: 800px;
text-align: justify;
}
.copyright
{
font-size: 0.7em;
color: #666666;
}
div.code, span.code
{
font-family: monospace;
background-color: #E8E8E8;
}
.code .comment
{
color: #008000;
}
div.code
{
padding: 5px;
border-style: solid;
border-width: 1px;
width: 600px;
margin: 10px;
}
img.thumb
{
height: 140px;
border-style: none;
float: left;
margin: 10px;
margin-top: 0px;
}
h1, h2, h3, h4, h5, h6, h7, h8, h9
{
clear: both;
}
</style>
</head>
<body>
<div class="content">
<p class="copyright">
copyright © 2010-2016 Youen Toupin<br/>
GRLD uses wxLua which is freely available under the terms of the <a href="http://www.gnu.org/licenses/lgpl.txt">GNU LGPL</a>.<br/>
GRLD uses lua, luasocket, LuaFileSystem and coxpcall, which are freely available under the terms of the <a href="http://www.lua.org/license.html">MIT license</a>.<br/>
GRLD itself is also distributed under the <a href="http://www.lua.org/license.html">MIT license</a>.<br/>
</p>
<h1>Graphical Remote Lua Debugger documentation</h1>
<!-- @generated_toc@ -->
<h2>What is GRLD?</h2>
<p>GRLD is a <b>G</b>raphical <b>R</b>emote <b>L</b>ua <b>D</b>ebugger, designed to help find bugs in lua programs.</p>
<ul>
<li><b>Graphical</b> user interface, intuitive and easy to use,</li>
<li><b>Remote</b> connection to the debugged program, to be able to debug on any plateform, including video game consoles,</li>
<li><b>Lua Debugger</b> wich features step-by-step execution, breakpoints, complete lua state exploration, custom expression evaluation, etc.</li>
</ul></p>
<h2>Installation</h2>
<p>GRLD is structured as a client/server architecture. The client must be integrated in the application to debug. The server is a standalone application with a graphical user interface, that, once connected to one or more clients, will allow to control them, and gather information from them. The server uses only portable components (mainly lua, wxWidgets, and luasocket), so it should work on other platforms, but it has only been tested on Windows at this time.</p>
<h3>Building</h3>
If for some reason you don't want to use a prebuilt release, here is the process to build GRLD:
<h4>Client build</h4>
The client (the part that must be integrated in the application to debug) requires some C code, and thus must either be built as a separate dynamic link library, or directly integrated in your application source code (which is not descibed here as it would vary depending on your application and the tools you use to build it ; but since you already know how to build your own application, integration should be easy).
To build the dynamic link library (DLL) on Windows, you can use visual studio. Once visual studio is installed, open client/visual/grldc.sln and build the solution. This should result in a grldc.dll file in the Debug or Release folder.
One thing to note is that the dll embeds lua files for convenience (so that you don't have to copy them with your application data and load them with lua). This is done by client/build/embed.lua.bat which will generate some .lua.c files that are then built into the DLL. This is done automatically if you use the provided visual studio solution file.
<h4>Server build</h4>
As opposed to the client, the server only uses lua code (and third-party lua modules), so you don't need to build anything.
<h3>Client installation</h3>
<h4>If the application to debug runs under Windows</h4>
<ul>
<li>Copy grldc.dll somewhere your application can access it</li>
<li>If your application does not already use lua socket, copy the socket.dll and socket.lua files as well</li>
<li>Run the following lua code at your application startup:<br/>
<div class="code">
package.cpath = package.cpath..";path/to/grldc/?.dll" <span class="comment">-- This line is not required if the DLLs are already accessible by your application, for example in the same directory as the lua executable.</span><br/>
require( "grldc" )<br/>
<span class="comment">-- [server address] is the IP address of the server, [server port] is the port to connect to, and [application name] is a name that will be displayed in the server to identify the debugged application.</span><br/>
<span class="comment">-- This can typically be something like grldc.connect( "127.0.0.1", 4242, "MyApp" )</span><br/>
grldc.connect( "[server address]", [server port], "[application name]" )
</div>
</li>
</ul>
<p>With this setup, you need to use lua from a DLL (this is the case with the standard windows distribution), and use the same lua version as the one used to build grldc.dll. Do not use GRLDC.dll if lua is statically linked to your application. Make sure your application and GRLDC.dll all using the same lua dll file.</p>
<h4>If the application to debug does not run under Windows</h4>
<p>You must either build a dynamic library yourself, or include the grld C files in your application.</p>
<h3>Server installation</h3>
<h4>On Windows</h4>
<p>Simply copy the server directory anywhere on a PC running Windows (it can be the same machine that runs the debugged program), and double click on GRLD-server.bat to run the graphical interface. The server will then wait for the client connection (i.e. the program to debug).</p>
<p>By default, the server listens on any network interface, on port 4242. You can change this in server/wxLdb/wxLdb.lua, or in GRLD-server.bat by replacing %* by the interface to listen on and the port, or call GRLD-server.bat with two arguments (again, the interface to listen on, and the port).</p>
<h4>On Linux</h4>
<a href="screenshots/wine.png"><img class="thumb" src="screenshots/wine-thumb.png"></a>
<p>The GRLD server is known to work on Linux using Wine (tested with GRLD 1.1.0, wine-1.3.19, on ubuntu 11.4 with gnome 2.32.1, thanks to Laurian for testing it). Follow the same procedure as explained for the Windows installation, and use Wine to run the server. I think it can work with native Linux libraries too, as all dependencies of GRLD are available for Linux, but as far as I know, this has not been tested yet.</p>
<h2>Using the GRLD server</h2>
<p>If you just want to try the debugger, you can start a sample, double click on samples/demo01/start.bat. This will start two processes: the server and a client that will run a simple demonstration application. If you actually want to debug an application, start the server (see section "Server installation"), and then start your application.</p>
<p>When you start the server, and assuming you did not start a program to debug yet, you should see something similar to this:</p>
<a href="screenshots/startup.png"><img class="thumb" src="screenshots/startup-thumb.png"></a>
<p>In this state, the server is waiting for a client connection. You can't do much in this state, excepted open source files and set breakpoints in them, that will be used later by clients that will connect to the server.</p>
<h3>Connect clients to the server</h3>
<p>If you followed the installation steps to integrate the client in the application you want to debug, there is not much more to do. Run your application, and it should connect to the server, then immediately break execution.</p>
<p>When the client breaks execution, the server will want to display the corresponding source file. However, because G<b>R</b>LD is a <b>R</b>emote debugger, it may happen that the server can not directly access source files used by the debugged application. The debugged application might even use precompiled files, but you clearly want to display the source files in the server window. This is why the server will prompt you to select the file where the client has broken its execution. You should see a popup similar to this one:</p>
<a href="screenshots/source-popup.png"><img class="thumb" src="screenshots/source-popup-thumb.png"></a>
<p>Browse to select the file on the server machine that corresponds to the one used by the debugged application. It can be the same file if the debugged application runs on the same machine than the server. When you have done that, you will see another popup to confirm how to make the correspondance between the client directory which contains the source file, and the corresponding directory on the server machine. You may want to modify the paths to set up the correspondance higher in the directories hierarchy, typically up to the root of your project directory. Doing this will avoid further popups to show up, as the server should find all the source files relatively to your project root, assuming the corresponding hierarchy on the server machine is similar. You can set up more complex directory mappings, see section "Source files setup"</p>
<p style="clear: both;">Once the server has found the source file, it will display something similar to this:</p>
<a href="screenshots/client-connected.png"><img class="thumb" src="screenshots/client-connected-thumb.png"></a>
<p>The biggest part of the screen is occupied by the source code window. It displays the source code of the application to debug, and have markers on the left side to indicate breakpoints (big red points), and the line where your application broke its execution (the yellow arrow).</p>
<p>On the bottom left corner, you have the "threads" window, which lists all the connected clients, with all their threads (I mean <i>lua</i> threads, which include the main thread, and coroutines, if any).</p>
<p>Next to it, you have the callstack window, which displays the callstack of the currently selected coroutine (or the main thread). See section "Working with multiple clients and coroutines" for more details.</p>
<p>Notice that you can run other applications, the server can handle multiple clients simultaneously (once again, this is detailed in section "Working with multiple clients and coroutines"). Your application can also have multiple lua states, in which case each state will need to run the grldc.connect function, and will appear as a different client in the server.</p>
<h3>Control execution of the application to debug</h3>
<p>All commands to control the execution of the debugged application are in the Debug menu. You can see the keyboard shortcuts in this menu too. If you want to modify the shortcuts, you can edit file server/wxLdb/ui/mainWindow.lua. Look for lines like this one: <span class="code">debugMenu:Append( ID_STEP_OVER, "&Step over\tF10", "Step over a line" )</span>, and replace the shortuct (F10 in this example) by another one.</p>
<ul>
<li><b>Break:</b> This will break execution of the client as soon as possible (meaning at the next lua statement executed after the client receives the command from the network). It has no effect if the client execution is already broken.</li>
<li><b>Continue:</b> This is the reverse of the break command. It will resume the normal execution of the client. It has no effect if the client is already running.</li>
<li><b>Step over:</b> Asks the client to step over function calls to the next line. This means the client won't stop inside new function calls. It won't either stop if the current coroutine (or the main thread) transmit execution to another coroutine (trough coroutine.resume or coroutine.yield), untill execution control comes back to the initial coroutine. It has no effect if the client is already running.</li>
<li><b>Step into:</b> Asks the client to step into the next lua statement. Execution will stop at the next executed lua statement, even if it is inside a newly called function, or even in another coroutine, or if a C function executes some lua code. It has no effect if the client is already running.</li>
<li><b>Step out:</b> Asks the client to step out of the current function. As Step over, it won't make the client stop in another coroutine. Execution will be resumed untill the current function exits by any way (a return statement, or an execution error). It has no effect if the client is already running.</li>
</ul>
<h3>Inspect the lua state</h3>
<p>When the client execution is broken, you can inspect the corresponding lua state. This involves mostly the debug window on the bottom right corner, although you may need the two other windows to select another coroutine (or another client, see section "Working with multiple clients and coroutines"), and another level in the callstack (in case you want to inspect local variables). To change the level of the callstack, simply click on it. The source code window will be udpated to focus on the corresponding line, and the automatic variables and watch windows will be updated.</p>
<h4>Using the automatic variables window</h4>
<p>The automatic variables window is the easier to use. It will display all local variables and upvalues of the current function selected in the callstack. You can unfold complex values to show details. This means navigating inside tables, or looking at function details (upvalues, environment, etc.).</p>
<h4>Using the watch window</h4>
<a href="screenshots/watch.png"><img class="thumb" src="screenshots/watch-thumb.png"></a>
<p>If the value you want to inspect is not in the automatic variables window, you can use the watch window. Select a line, then click again on it to edit it. Then type a lua chunk, it will be executed on the client and you will be able to browse the results.</p>
<p>If your lua chunk does not contain a return statement, it will not return any value. You can, instead, prefix it with the equal sign, for example <span class="code">=1 + 1</span></p>
<p>Notice that executing the chunk on the client may have side effects. This can both be useful or problematic if you don't want to disturb the normal client execution, so be careful. Lua errors will be caught (and displayed on the server), so they should not propagate and crash the client, but if you call a C function, anything could happen.</p>
<p>If you fold your chunk, and then unfold it back, it will be executed again.</p>
<p>Local variables and upvalues are looked up in the function currently selected in the callstack. You can read and write them as you would normaly do in that function source code. The environment of this function is also used as the environment of your chunk, so you may not have directly access to the global variables. To do so, use the special name <span class="code">__globals__</span> (notice it has two underscores on each side).</p>
<h3>Setting breakpoints</h3>
<p>To set a breakpoint, simply click in the column on the left of the source file displayed on the server window. This will enable/disable the breakpoint at this location.</p>
<p>Breakpoints are relative to a particular client, if that client is selected. See section "Working with multiple clients and coroutines" for more details. Notice that if multiple clients have the same application name (as defined in the call to grldc.connect), they will share the same breakpoints.</p>
<p>When no client is selected (for example because no client is connected), breakpoints that are set will apply to the first client you will select. This can be used to set breakpoints before a client connects ; the first client to connect will use these breakpoints.</p>
<p>Another implicit breakpoint can be specified (and is enabled by default): break on connection. When enabled, the client execution will break as soon as it connects to the server. You can enable/disable this behavior by right clicking on the client in the threads window.</p>
<p>In most cases, breakpoints will just work as expected. However, you may encounter problems if your application has multiple ways to access the same source file. Typically, if you have a filesystem that allows the use of aliases to point on directories. For example if the path some/path/to/file.lua references the same file than some/other/path/to/file.lua, the client may not break as expected. The breakpoint will be set to only one of those paths. See section "Source files setup" for more details.</p>
<h3>Working with multiple clients and coroutines</h3>
<p>As stated earlier, the GRLD server can handle multiple clients. The connected clients are displayed in the bottom left window.</p>
<p>Settings for each client (open files, breakpoints, etc.) are shared for clients that have the same name.</p>
<p>To change the active client, simply click on one of them. This will change the focus to the top function in the callstack of the current thread, i.e. the thread (the main thread or a coroutine) in which execution has been broken. If the client is currently running, you can't see anything about it (try using the Break command of the Debug menu).</p>
<p>You may also want to inspect a different coroutine than the one in which execution has been broken. To do so, just click on it. Notice that the active coroutine (the one you are inspecting) is displayed in bold, while the current one (the one that has broken execution) is indicated by an arrow on its left.</p>
<p>When no thread is displayed in bold, it means the active thread is the current one. This means that when stepping in the code, you will always stay focused on where the execution has been broken. This is the recommended way to step in the code.</p>
<p>Be careful when clicking on the active thread: it will become the active and the current thread at the same time (bold and with an arrow on its left). But if the current thread changes (because you step into a coroutine.resume or coroutine.yield call for example), the active thread will not change because you have explicitely selected it. This means you won't see the new break location, which can be confusing. To go back to the "normal" configuration, click on the <i>client</i>, not on the current <i>thread</i>.</p>
<h3>Source files setup</h3>
<h4>Normal usage</h4>
<p>As explained in section "Connect clients to the server", source files displayed in the server are not always those used by the client, because the server may not always have a possibility to access the same files as the client. To handle this problem, GRLD uses a mechanism that maps client (remote) directories to server (local) directories.</p>
<p>When the server can't resolve the path to a local source file (if the client breaks execution somewhere unknown to the server for example), or when it can't resolve the path to a remote source file (when you set a breakpoint in a file that is not yet mapped for example), you will be prompted to add a directory mapping.</p>
<p>The first popup will ask you to pick the file on the server machine filesystem. This implies that the server should have access to a copy of the client source files (or directly to the client source files if it is possible). If you can not access this file, you can cancel the popup, but in this case you won't be able to see the source code.</p>
<p>The second popup will allow you to edit both the remote path and the local path. This allows for example to create a more general mapping, such as mapping "./" on "C:/path/to/local/files", instead of "./subdir/" to "C:/path/to/local/files/subdir". The more general your mapping is, the less you will be prompted when new files are accessed. The ideal case is when your client has a root directory, in which all its source files are located, and the server has a copy of that hierarchy (or can access the same directory).</p>
<p>See section "Managing client configurations" if you make a mistake that creates a bad mapping and you need to remove it.</p>
<h4>Potential issues</h4>
<p>This section explains more deeply how the system works, and why it may not always give the expected results. If you don't have problems, you do not have to read this.</p>
<p>Sometimes, multiple paths can be used to access the same file. On Windows for example, path "C:\some\path\to\file.lua" references the same file as "C:/SOME/path\other\directory/..\../TO/fIlE.LUA". GRLD handles these problems by transforming paths to a canonical form before using them. In the current implementation, it will remove "." and ".." where possible, replace "\" by "/" and make all letters lower case. If this doesn't fit your configuration, you can modify the algorithm in grldc/utilities.lua. This file is compiled and embedded in grldc_utilities.c on the client; the server loads the lua file directly. Because the server exchanges paths with the client, you should keep the same implementation on both sides if possible, otherwise you may need to further modify the way paths are handled by GRLD. If the current implementation does not fit your needs, see the "Troubleshooting" section.</p>
<p>In some cases, everything may seem to work correctly, as the server displays the correct source file when you step in the code, but yet the client may think two paths do not refer to the same file, while they actually do. In this case, setting a breakpoint on the server may not set it to the correct path on the client, which would not correctly break execution when it should encounter the breakpoint. I have no absolute solution for this problem at this time, you may fix the problem by reorganizing your mappings, or change the way canonical paths are computed. See also function <span class="code">getRemoteSource_</span> in server/wxLdb/wxLdbController.lua. This is the function that resolves a local path to find the corresponding remote path, and the server uses the result to tell the client to break on that path. On its side, the client converts all source file paths to a canonical form before testing if they contain a breakpoint (it is not that simple, the code contains optimizations or lua execution would be just horribly slow). If the canonical form computed by the client does not match the result of <span class="code">getRemoteSource_</span>, then the client won't correctly detect the breakpoint.</p>
<h3>Managing client configurations</h3>
<p>When a client connects to the debugger, it sends its application name (the third parameter of grldc.connect). This name is used to identify the clients in the threads window, and to associate a configuration to these clients. The configuration is saved automatically when modified.</p>
<p>At this time, there is no graphical interface to edit client configurations (this is planned for a future version of GRLD). Most of the time, you won't need to do such a thing. If needed, however, you can look in the directory server/clients, it will be filled with client configurations (what files were open last time you debugged the client, which breakpoints were set, etc). Files are saved as lua chunks, so they should be quite easy to edit manually if needed. You'll have to restart the server for your modifications to take effect.</p>
<h2>Troubleshooting</h2>
<p>As you can see, this section is empty. I intend to add here solutions about problems users might encounter. For this purpose, don't hesitate to <a href="contact.txt">contact me</a> if you have problems using GRLD. GRLD development is not my main activity, so I can't promise I will have enough time for support, but I'll do my best.</p>
<h2>External Control Interface (ECI)</h2>
<p>ECI is a lua module that can be used to control the server from an external application. I use it for automated tests, but it may be useful for users too, so I've included it in the distribution. It is located in server/eci/eci.lua. You can also find useful to use directly the server debugging engine, located in server/grld/engine.lua. This is the module used by the user interface to communicate with the clients. It could be used to write a command line interface for example (I've done it before, but I've drop this part of the project because it was less important than the graphical user interface, but if you're interested I can send you the old files as a starting point).</p>
</div>
</body>
</html>

BIN
doc/screenshots/client-connected-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
doc/screenshots/client-connected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
doc/screenshots/source-popup-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/screenshots/source-popup.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
doc/screenshots/startup-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
doc/screenshots/startup.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
doc/screenshots/watch-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
doc/screenshots/watch.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
doc/screenshots/wine-thumb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
doc/screenshots/wine.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

3
samples/demo01/demo01.bat

@ -0,0 +1,3 @@
rem this scripts starts a client (the program to debug)
rem you should start the debugging server before (with script server/GRLD-server.bat)
..\..\bin\win_x86\lua5.2\lua52.exe demo01.lua

64
samples/demo01/demo01.lua

@ -0,0 +1,64 @@
-- Initialize search paths so that lua can find the required DLLs
-- path to socket.dll
package.cpath = package.cpath..";../../client/3rdparty/lua5.2/?.dll"
-- path to grldc.dll
package.cpath = package.cpath..";../../client/visual/Debug/?.dll"
-- Load the GRLD client package and connect to the server which we assume to be running on the same machine and listening on port 4242
require( "grldc" )
grldc.connect( "127.0.0.1", 4242, "demo01" )
-- Now execute some basic lua statements with no particular purpose, just to demonstrate the debugger functionalities
-- some variables that can be explored from the server
local someTable = { "a", "a big string that won't be downloaded until requested by the user", subtable = setmetatable( { "another table" }, { "and its metatable" } ) }
someGlobalVariable = "Hello world"
local aRecursiveTable = { test = someTable }
aRecursiveTable.r = aRecursiveTable
local tableWithComplexKeys = { [aRecursiveTable] = function() print( "bouh" ) end }
tableWithComplexKeys[tableWithComplexKeys[aRecursiveTable]] = someTable
-- some functions to demonstrate stepping in code
function test()
local a = 1
return a
end
local function test1()
local b = 2
test()
return b
end
function testMulCall( a, b )
local c = a + b
print( c )
end
function testTail()
return test()
end
-- lua call
test()
-- C call
print( "a" )
-- tail call
testTail()
-- multiple calls, same line
testMulCall( test(), test1() )
-- and this file does not demonstrates all the debugger features, you can debug code that uses coroutines, userdata, multiple source files, directory mappings to make the server use a copy of the source files if the debugged program does not run on the same machine, etc.
print( "done" )

2
server/GRLD-server.bat

@ -0,0 +1,2 @@
cd %~dp0
..\bin\win_x86\lua5.1\lua51.exe wxLdb\wxLdb.lua %*

302
server/grld/engine.lua

@ -0,0 +1,302 @@
-- see copyright notice in wxLdb.lua
local net = require( "grldc.net" )
local socket = require( "grldc.socket" )
local print = print
local assert = assert
local pairs = pairs
local ipairs = ipairs
local type = type
local debug = debug
local xpcall = xpcall
local setmetatable = setmetatable
local error = error
local table = table
local tonumber = tonumber
module( "grld.engine" )
local clients
local activeClient
local nextClient = 1
local listeners = {}
local nextListener = 1
local events =
{
onNewClient = {},
onClientBreak = {},
onClientLost = {},
}
local clientMeta = { __index = {} }
local function addClient( listenerIdx, connection, name )
print( "New client connected on listener "..listenerIdx.." : assigned client ID "..nextClient )
local client = { clientId = nextClient, listenerIdx = listenerIdx, connection = connection, status_ = "running", activeThread_ = "current", name_ = name, ip_ = connection:getpeername(), breakPoints_ = {} }
setmetatable( client, clientMeta )
clients[nextClient] = client
if activeClient == nil or clients[activeClient] == nil then
setactiveclient( nextClient )
end
runEvents_( "onNewClient", nextClient )
nextClient = nextClient + 1
end
function init()
print( "Initializing grld.engine..." )
assert( clients == nil, "Trying to initialize grld.engine twice" )
clients = {}
end
function initialized()
return clients ~= nil
end
function listen( address, port )
print( "Listening for new clients on "..address..":"..port..", listener ID "..nextListener )
local listener = net.bind( address, port )
listeners[nextListener] = listener
nextListener = nextListener + 1
end
function registerEvent( eventName, callback )
assert( events[eventName] ~= nil, "Unknown event name "..eventName )
table.insert( events[eventName], callback )
end
function runEvents_( eventName, ... )
for _, callback in pairs( events[eventName] ) do
callback( ... )
end
end
function update( timeout )
local active = false
for idx, listener in pairs( listeners ) do
local connection = listener:accept()
if connection ~= nil then
local name = connection:receive()
addClient( idx, connection, name )
active = true
end
end
local sockets = {}
for idx, client in pairs( clients ) do
table.insert( sockets, client.connection )
end
socket.select( sockets, timeout )
for idx, client in pairs( clients ) do
local ok, msg = xpcall( function() active = active or client:update() end, client.errorHandler )
if not ok then
active = true
if msg == "closed" then
print( "Connection with client "..idx.." closed" )
runEvents_( "onClientLost", idx )
clients[idx] = nil
else
error( msg )
end
end
end
return active
end
function clientMeta.__index:checkConnection()
self.connection:send( "", "ka" )
end
function clientMeta.__index:update()
local command = self.connection:tryReceive()
if command ~= nil then
self["cmd_"..command]( self )
return true
end
return false
end
function clientMeta.__index:setactivethread( thread )
self.activeThread_ = thread
end
function clientMeta.__index:getactivethread()
return self.activeThread_
end
function clientMeta.__index:getcurrentthread()
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "currentthread" )
return self.connection:receive()
end
function clientMeta.__index:name()
return self.name_
end
function clientMeta.__index:ip()
return self.ip_
end
function clientMeta.__index:status()
return self.status_
end
function clientMeta.__index:source()
assert( self.status_ == "break", "Bad status: "..self.status_ )
return self.source_
end
function clientMeta.__index:line()
assert( self.status_ == "break", "Bad status: "..self.status_ )
return self.line_
end
function clientMeta.__index:setbreakpoint( source, line, value )
local setValue = value or nil
local sourceBp = self.breakPoints_[source]
if sourceBp == nil then
sourceBp = {}
self.breakPoints_[source] = sourceBp
end
sourceBp[line] = setValue
self.connection:send( "setbreakpoint", "running" )
self.connection:send( { source = source, line = line, value = value }, "running" )
end
function clientMeta.__index:callstack()
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "callstack" )
self.connection:send( self.activeThread_ )
return self.connection:receive()
end
function clientMeta.__index:breakpoints()
--if self.status_ == "break" then
-- self.connection:send( "breakpoints" )
-- self.breakPoints_ = self.connection:receive()
--end
return self.breakPoints_
end
function clientMeta.__index:locals( level )
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "locals" )
self.connection:send( self.activeThread_ )
self.connection:send( level )
return self.connection:receive()
end
function clientMeta.__index:upvalues( level )
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "upvalues" )
self.connection:send( self.activeThread_ )
self.connection:send( level )
return self.connection:receive()
end
function clientMeta.__index:evaluate( expr, level )
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "evaluate" )
self.connection:send( expr )
self.connection:send( self.activeThread_ )
self.connection:send( level )
return self.connection:receive()
end
function clientMeta.__index:releaseValue( id )
self.connection:send( "releaseValue", "running" )
self.connection:send( id, "running" )
end
function clientMeta.__index:getValue( id )
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "getValue" )
self.connection:send( id )
return self.connection:receive()
end
function clientMeta.__index:coroutines()
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( "coroutines" )
return self.connection:receive()
end
for _, command in ipairs( { "run", "stepover", "stepin", "stepout" } ) do
clientMeta.__index[command] = function( self )
assert( self.status_ == "break", "Bad status: "..self.status_ )
self.connection:send( command )
--assert( self.connection:receive() == "ack_"..command )
self.status_ = "running"
end
end
function clientMeta.__index:breaknow()
assert( self.status_ == "running", "Bad status: "..self.status_ )
self.connection:send( "break", "running" )
end
function clientMeta.__index:cmd_synchronize()
self.connection:send( 0 )
self.connection:send( true )
end
function clientMeta.__index:cmd_break()
assert( self.status_ == "running" )
--self.connection:send( "ack_break" )
self.source_ = self.connection:receive()
self.line_ = self.connection:receive()
self.status_ = "break"
assert( type( self.source_ ) == "string" )
assert( type( self.line_ ) == "number" )
print( "Client "..self.clientId.." break at "..self.source_.."("..self.line_..")" )
runEvents_( "onClientBreak", self.clientId )
end
function clientMeta.__index.errorHandler( msg )
if msg == "closed" then return msg end
return debug.traceback( msg )
end
function listclients()
local res = {}
for idx, client in pairs( clients ) do
table.insert( res, { clientId = idx } )
end
return res
end
function getactiveclient()
return activeClient or 0
end
function setactiveclient( idx )
idx = assert( tonumber( idx ) )
print( "Setting active client: "..idx )
activeClient = idx
if clients[idx] == nil then
print( "Warning: no such client" )
end
end
function getClient( clientId )
return clients[clientId]
end
for _, func in ipairs( { "name", "ip", "status", "source", "line", "callstack", "locals", "coroutines", "run", "breaknow", "stepover", "stepin", "stepout", "setactivethread", "getactivethread", "getcurrentthread" } ) do
_M[func] = function( ... )
local idx = getactiveclient()
local client = clients[idx]
if client == nil then return "no such client" end
return client[func]( client, ... )
end
end
function shutdown()
print( "Shuting down grld.engine..." )
clients = nil
listeners = {}
end

64
server/wxLdb/coxpcall-LICENSE.html

@ -0,0 +1,64 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Coxpcall License</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div id="content">
<h2>Coxpcall License</h2>
<p>Coxpcall is free software: it can be used for both academic and
commercial purposes at absolutely no cost. There are no royalties
or GNU-like "copyleft" restrictions. Coxpcall qualifies as <a href=
"http://www.opensource.org/docs/definition.html">Open Source</a>
software. Its licenses are compatible with <a href=
"http://www.gnu.org/licenses/gpl.html">GPL</a>. Coxpcall is not in
the public domain and
<a href="http://www.keplerproject.org">Kepler Project</a>
keep its copyright. The legal details are below.
</p>
<p>The spirit of the license is that you are free to use Coxpcall for
any purpose at no cost without having to ask us. The only
requirement is that if you do use Coxpcall, then you should give us
credit by including the appropriate copyright notice somewhere in
your product or its documentation.</p>
<p>Coxpcall was designed and implemented by Roberto Ierusalimschy and
Andr&eacute; Carregal. The implementation is not derived from licensed software.</p>
<p>
<!-- ===================================================================== -->
</p>
<hr />
<p>Copyright &copy; 2005 Kepler Project.</p>
<p>Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.</p>
</div> <!-- id="content" -->
</body>
</html>

81
server/wxLdb/coxpcall.lua

@ -0,0 +1,81 @@
-------------------------------------------------------------------------------
-- Coroutine safe xpcall and pcall versions
--
-- Encapsulates the protected calls with a coroutine based loop, so errors can
-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines
-- yielding inside the call to pcall or xpcall.
--
-- Authors: Roberto Ierusalimschy and Andre Carregal
-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fábio Mascarenhas
--
-- Copyright 2005 - Kepler Project (www.keplerproject.org)
--
-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $
-------------------------------------------------------------------------------
-- This version has been modified to handle the case where a child coroutine
-- (created by copcall or coxpcall) is directly resumed, instead of resuming
-- its parent coroutine, because the coroutine reference was obtained by
-- calling coroutine.running from the child coroutine. The modification
-- implemented here is to override coroutine.running so that it returns the
-- parent coroutine instead of the child one.
local oldrunning = coroutine.running
local parents = {}
setmetatable( parents, { __mode = "kv" } )
local function getRoot( co )
return parents[co] or co
end
coroutine.running = function()
return getRoot( oldrunning() )
end
-------------------------------------------------------------------------------
-- Implements xpcall with coroutines
-------------------------------------------------------------------------------
local performResume, handleReturnValue
local oldpcall, oldxpcall = pcall, xpcall
function handleReturnValue(err, co, status, ...)
if not status then
return false, err(debug.traceback(co, (...)), ...)
end
if coroutine.status(co) == 'suspended' then
return performResume(err, co, coroutine.yield(...))
else
return true, ...
end
end
function performResume(err, co, ...)
return handleReturnValue(err, co, coroutine.resume(co, ...))
end
function coxpcall(f, err, ...)
local res, co = oldpcall(coroutine.create, f)
if not res then
local params = {...}
local newf = function() return f(unpack(params)) end
co = coroutine.create(newf)
end
parents[co] = getRoot( oldrunning() )
return performResume(err, co, ...)
end
-------------------------------------------------------------------------------
-- Implements pcall with coroutines
-------------------------------------------------------------------------------
local function id(trace, ...)
return ...
end
function copcall(f, ...)
return coxpcall(f, id, ...)
end
-------------------------------------------------------------------------------
-- Override coroutine.running
-------------------------------------------------------------------------------

46
server/wxLdb/mainthread.lua

@ -0,0 +1,46 @@
-- see copyright notice in wxLdb.lua
local wx = require( "wx" )
local coroutine = coroutine
local assert = assert
local debug = debug
module( "mainthread" )
local mainObj = nil
local eventsData = {}
local id = 194283
function init( obj )
assert( coroutine.running() == nil )
assert( obj ~= nil )
assert( mainObj == nil )
mainObj = obj
mainObj:Connect( wx.wxEVT_NULL, function( event )
if event:GetId() == id then
local data = assert( eventsData[event:GetInt()] )
eventsData[event:GetInt()] = nil
local ok, msg = coroutine.resume( data.coroutine, data.func() )
assert( ok, debug.traceback( data.coroutine, msg ) )
end
end )
end
function execute( f )
assert( mainObj ~= nil )
if coroutine.running() == nil then
return f()
else
local e = wx.wxCommandEvent() -- event ID is wxEVT_NULL ; if someone else post this event for another purpose, it will conflict with this system...
local data = {}
data.coroutine = coroutine.running()
data.func = f
local dataId = #eventsData + 1 -- we don't care if dataId does not increment each time a new event is created ; in any case, we are sure that, by definition of the length operator, eventsData[#eventsData+1] is nil
eventsData[dataId] = data
e:SetInt( dataId )
e:SetId( id )
wx.wxPostEvent( mainObj, e )
return coroutine.yield()
end
end

11
server/wxLdb/ui/about.lua

@ -0,0 +1,11 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
module( "ui.about" )
function popup()
wx.wxMessageBox( "Graphical Remote Lua Debugger @VERSION@\nCopyright (C) 2010-2012 Youen Toupin. All rights reserved.\nSee file GRLD-license.txt for permission notice.\nSee file contact.txt if you have any question,\nor go to http://cushy-code.com/grld/", "About GRLD" )
end

76
server/wxLdb/ui/callstack.lua

@ -0,0 +1,76 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local setmetatable = setmetatable
local table = table
local debug = debug
local xpcall = xpcall
local pairs = pairs
local ipairs = ipairs
local assert = assert
local tostring = tostring
local string = string
module( "ui.callstack" )
local meta = { __index = {} }
function new( ... )
local res = {}
setmetatable( res, meta )
res:init( ... )
return res
end
function meta.__index:init( parentWidget )
self.grid = wx.wxGrid( parentWidget, wx.wxID_ANY )
self.grid:CreateGrid( 0, 4, wx.wxGrid.wxGridSelectRows )
self.grid:SetRowLabelSize( 0 )
self.grid:SetColLabelSize( 20 )
self.grid:SetColLabelValue( 0, "Name" )
self.grid:SetColSize( 0, 120 )
self.grid:SetColLabelValue( 1, "Type" )
self.grid:SetColSize( 1, 50 )
self.grid:SetColLabelValue( 2, "Source" )
self.grid:SetColSize( 2, 250 )
self.grid:SetColLabelValue( 3, "Line" )
self.grid:SetColSize( 3, 50 )
self.grid:EnableEditing( false )
self.grid:Connect( wx.wxEVT_GRID_CELL_LEFT_CLICK, function( event )
self:runEvents_( "onCallstackClicked", event:GetRow() + 1 )
event:Skip()
end )
self.events = { onCallstackClicked = {} }
end
function meta.__index:registerEvent( eventName, callback )
assert( self.events[eventName] ~= nil, "Unknown event name "..eventName )
table.insert( self.events[eventName], callback )
end
function meta.__index:runEvents_( eventName, ... )
for _, callback in pairs( self.events[eventName] ) do
callback( ... )
end
end
function meta.__index:getRoot()
return self.grid
end
function meta.__index:setData( callstack )
self.grid:DeleteRows( 0, self.grid:GetNumberRows() )
if callstack ~= nil then
self.grid:AppendRows( #callstack )
for level, entry in ipairs( callstack ) do
self.grid:SetCellValue( level - 1, 0, entry.name )
self.grid:SetCellValue( level - 1, 1, entry.type )
self.grid:SetCellValue( level - 1, 2, string.gsub( entry.source, "[\n\r]+", " " ) )
self.grid:SetCellValue( level - 1, 3, entry.line )
end
end
end

236
server/wxLdb/ui/editor.lua

@ -0,0 +1,236 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local wxstc = require( "wxstc" )
local mainthread = require( "mainthread" )
local setmetatable = setmetatable
module( "ui.editor" )
local font
local fontItalic
-- Pick some reasonable fixed width fonts to use for the editor
if wx.__WXMSW__ then
font = wx.wxFont(10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, "Andale Mono")
fontItalic = wx.wxFont(10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, "Andale Mono")
else
font = wx.wxFont(10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, "")
fontItalic = wx.wxFont(10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, "")
end
-- Markers for editor margin
markers =
{
breakpoint = 1,
badBreakpoint = 2,
currentLine = 3,
otherLine = 4,
}
local function createEditor( parent, owner )
local editor = wxstc.wxStyledTextCtrl( parent, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxSUNKEN_BORDER )
editor:SetBufferedDraw(true)
editor:StyleClearAll()
editor:SetFont(font)
editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, font)
for i = 0, 32 do
editor:StyleSetFont(i, font)
end
editor:StyleSetForeground(0, wx.wxColour(128, 128, 128)) -- White space
editor:StyleSetForeground(1, wx.wxColour(0, 127, 0)) -- Block Comment
editor:StyleSetFont(1, fontItalic)
--editor:StyleSetUnderline(1, false)
editor:StyleSetForeground(2, wx.wxColour(0, 127, 0)) -- Line Comment
editor:StyleSetFont(2, fontItalic) -- Doc. Comment
--editor:StyleSetUnderline(2, false)
editor:StyleSetForeground(3, wx.wxColour(127, 127, 127)) -- Number
editor:StyleSetForeground(4, wx.wxColour(0, 127, 127)) -- Keyword
editor:StyleSetForeground(5, wx.wxColour(0, 0, 127)) -- Double quoted string
editor:StyleSetBold(5, true)
--editor:StyleSetUnderline(5, false)
editor:StyleSetForeground(6, wx.wxColour(127, 0, 127)) -- Single quoted string
editor:StyleSetForeground(7, wx.wxColour(127, 0, 127)) -- not used
editor:StyleSetForeground(8, wx.wxColour(0, 127, 127)) -- Literal strings
editor:StyleSetForeground(9, wx.wxColour(127, 127, 0)) -- Preprocessor
editor:StyleSetForeground(10, wx.wxColour(0, 0, 0)) -- Operators
--editor:StyleSetBold(10, true)
editor:StyleSetForeground(11, wx.wxColour(0, 0, 0)) -- Identifiers
editor:StyleSetForeground(12, wx.wxColour(0, 0, 0)) -- Unterminated strings
editor:StyleSetBackground(12, wx.wxColour(224, 192, 224))
editor:StyleSetBold(12, true)
editor:StyleSetEOLFilled(12, true)
editor:StyleSetForeground(13, wx.wxColour(0, 0, 95)) -- Keyword 2 highlighting styles
editor:StyleSetForeground(14, wx.wxColour(0, 95, 0)) -- Keyword 3
editor:StyleSetForeground(15, wx.wxColour(127, 0, 0)) -- Keyword 4
editor:StyleSetForeground(16, wx.wxColour(127, 0, 95)) -- Keyword 5
editor:StyleSetForeground(17, wx.wxColour(35, 95, 175)) -- Keyword 6
editor:StyleSetForeground(18, wx.wxColour(0, 127, 127)) -- Keyword 7
editor:StyleSetBackground(18, wx.wxColour(240, 255, 255)) -- Keyword 8
editor:StyleSetForeground(19, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(19, wx.wxColour(224, 255, 255))
editor:StyleSetForeground(20, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(20, wx.wxColour(192, 255, 255))
editor:StyleSetForeground(21, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(21, wx.wxColour(176, 255, 255))
editor:StyleSetForeground(22, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(22, wx.wxColour(160, 255, 255))
editor:StyleSetForeground(23, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(23, wx.wxColour(144, 255, 255))
editor:StyleSetForeground(24, wx.wxColour(0, 127, 127))
editor:StyleSetBackground(24, wx.wxColour(128, 155, 255))
editor:StyleSetForeground(32, wx.wxColour(224, 192, 224)) -- Line number
editor:StyleSetBackground(33, wx.wxColour(192, 192, 192)) -- Brace highlight
editor:StyleSetForeground(34, wx.wxColour(0, 0, 255))
editor:StyleSetBold(34, true) -- Brace incomplete highlight
editor:StyleSetForeground(35, wx.wxColour(255, 0, 0))
editor:StyleSetBold(35, true) -- Indentation guides
editor:StyleSetForeground(37, wx.wxColour(192, 192, 192))
editor:StyleSetBackground(37, wx.wxColour(255, 255, 255))
editor:SetUseTabs(true)
editor:SetIndentationGuides(true)
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_SLOP, 3)
--editor:SetXCaretPolicy(wxstc.wxSTC_CARET_SLOP, 10)
--editor:SetYCaretPolicy(wxstc.wxSTC_CARET_SLOP, 3)
editor:SetMarginWidth(0, editor:TextWidth(32, "9999_")) -- line # margin
editor:SetMarginWidth(1, 16) -- marker margin
editor:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginSensitive(1, true)
editor:MarkerDefine(markers.breakpoint, wxstc.wxSTC_MARK_ROUNDRECT, wx.wxWHITE, wx.wxRED)
editor:MarkerDefine(markers.badBreakpoint, wxstc.wxSTC_MARK_ROUNDRECT, wx.wxRED, wx.wxColour(192,192,192))
editor:MarkerDefine(markers.currentLine, wxstc.wxSTC_MARK_SHORTARROW, wx.wxBLACK, wx.wxColour(255,255,0))
editor:MarkerDefine(markers.otherLine, wxstc.wxSTC_MARK_ARROW, wx.wxBLACK, wx.wxGREEN)
editor:SetMarginWidth(2, 16) -- fold margin
editor:SetMarginType(2, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginMask(2, wxstc.wxSTC_MASK_FOLDERS)
editor:SetMarginSensitive(2, true)
editor:SetFoldFlags(wxstc.wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED +
wxstc.wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED)
editor:SetProperty("fold", "1")
editor:SetProperty("fold.compact", "1")
editor:SetProperty("fold.comment", "1")
local grey = wx.wxColour(128, 128, 128)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDEROPEN, wxstc.wxSTC_MARK_BOXMINUS, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDER, wxstc.wxSTC_MARK_BOXPLUS, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDERSUB, wxstc.wxSTC_MARK_VLINE, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDERTAIL, wxstc.wxSTC_MARK_LCORNER, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDEREND, wxstc.wxSTC_MARK_BOXPLUSCONNECTED, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDEROPENMID, wxstc.wxSTC_MARK_BOXMINUSCONNECTED, wx.wxWHITE, grey)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, wxstc.wxSTC_MARK_TCORNER, wx.wxWHITE, grey)
grey:delete()
editor:SetLexer(wxstc.wxSTC_LEX_LUA)
-- Note: these keywords are shamelessly ripped from scite 1.68
editor:SetKeyWords(0,
[[and break do else elseif end false for function if
in local nil not or repeat return then true until while]])
editor:SetKeyWords(1,
[[_VERSION assert collectgarbage dofile error gcinfo loadfile loadstring
print rawget rawset require tonumber tostring type unpack]])
editor:SetKeyWords(2,
[[_G getfenv getmetatable ipairs loadlib next pairs pcall
rawequal setfenv setmetatable xpcall
string table math coroutine io os debug
load module select]])
editor:SetKeyWords(3,
[[string.byte string.char string.dump string.find string.len
string.lower string.rep string.sub string.upper string.format string.gfind string.gsub
table.concat table.foreach table.foreachi table.getn table.sort table.insert table.remove table.setn
math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.deg math.exp
math.floor math.frexp math.ldexp math.log math.log10 math.max math.min math.mod
math.pi math.pow math.rad math.random math.randomseed math.sin math.sqrt math.tan
string.gmatch string.match string.reverse table.maxn
math.cosh math.fmod math.modf math.sinh math.tanh math.huge]])
editor:SetKeyWords(4,
[[coroutine.create coroutine.resume coroutine.status
coroutine.wrap coroutine.yield
io.close io.flush io.input io.lines io.open io.output io.read io.tmpfile io.type io.write
io.stdin io.stdout io.stderr
os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename
os.setlocale os.time os.tmpname
coroutine.running package.cpath package.loaded package.loadlib package.path
package.preload package.seeall io.popen
debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal
debug.getmetatable debug.getregistry debug.getupvalue debug.setfenv
debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.traceback]])
mainthread.execute( function()
editor:Connect(wxstc.wxEVT_STC_MARGINCLICK, function( event )
local line = editor:LineFromPosition(event:GetPosition())
local margin = event:GetMargin()
if margin == 1 then
owner:toggleBreakpoint( line )
elseif margin == 2 then
--[[if wx.wxGetKeyState(wx.WXK_SHIFT) and wx.wxGetKeyState(wx.WXK_CONTROL) then
FoldSome()
else
local level = editor:GetFoldLevel(line)
if HasBit(level, wxstc.wxSTC_FOLDLEVELHEADERFLAG) then
editor:ToggleFold(line)
end
end]]
end
end )
end )
return editor
end
local function splitMarkers( m )
local maxMarker = 31
local res = {}
for marker = maxMarker, 0, -1 do
local value = 2^marker
res[marker] = m >= value
if res[marker] then
m = m - value
end
end
return res
end
local meta = { __index = {} }
function new( parent )
local res = {}
setmetatable( res, meta )
res.editor = createEditor( parent, res )
return res
end
function meta.__index:toggleBreakpoint( line )
local editor = self.editor
--[[local m = editor:MarkerGet(line)
m = splitMarkers( m )
if m[markers.breakpoint] then
editor:MarkerDelete( line, markers.breakpoint )
else
editor:MarkerAdd( line, markers.breakpoint )
end]]
self.breakpointCallback( line + 1 )
end
function meta.__index:destroy()
-- nothing to do (the parent widget will destroy the editor widget)
end

12
server/wxLdb/ui/id.lua

@ -0,0 +1,12 @@
-- see copyright notice in wxLdb.lua
local wx = require( "wx" )
module( "ui.id" )
local lastId = wx.wxID_HIGHEST + 1
function new()
lastId = lastId + 1
return lastId
end

211
server/wxLdb/ui/luaExplorer.lua

@ -0,0 +1,211 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local mainthread = require( "mainthread" )
local assert = assert
local setmetatable = setmetatable
local getmetatable = getmetatable
local string = string
local tostring = tostring
local pairs = pairs
local ipairs = ipairs
local table = table
local type = type
local next = next
module( "ui.luaExplorer" )
local meta = { __index = {} }
local evaluableItemMeta = { __index = {} }
local promptString = "<type new expression here>"
local function escapeString( str )
for i = 1, #str do
if string.sub( str, i, i ) == "\000" then
str = string.sub( str, 1, i-1 ).."(NULL)"..string.sub( str, i+1 )
end
end
return str
end
function new( parent, interactive )
local self = { interactive = interactive }
setmetatable( self, meta )
local flags = wx.wxTR_HIDE_ROOT + wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS
if interactive then flags = flags + wx.wxTR_EDIT_LABELS end
self.tree = wx.wxTreeCtrl( parent, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, flags )
self.root = self.tree:AddRoot( "root" )
self.complexValues = {}
self.tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING, function( event ) self:onExpanding_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED, function( event ) self:onCollapsed_( event ) end )
if interactive then
self.tree:Connect( wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, function( event ) self:onBeginEdit_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT, function( event ) self:onEdited_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_KEY_DOWN, function( event ) self:onKeyDown_( event ) end )
self.tree:AppendItem( self.root, promptString )
end
return self
end
function meta.__index:getRoot()
return self.tree
end
function meta.__index:setData( data )
self:releaseHierarchy_( self.root )
assert( next( self.complexValues ) == nil )
--for _, cval in pairs( self.complexValues ) do
-- cval:release()
--end
--self.complexValues = {}
self.tree:DeleteChildren( self.root )
if data ~= nil then
for _, entry in ipairs( data ) do
self:append_( self.root, entry )
end
end
end
function meta.__index:append_( parent, entry )
local value
local t = type( entry.value )
local isComplex = false
if t == "table" then
value = entry.value.short
if value ~= nil and (entry.value.type == "string" or entry.value.type == "proxy") then
value = escapeString( value )
end
if entry.value.id ~= nil then
isComplex = true
end
elseif t == "string" then
value = "\""..escapeString( entry.value ).."\""
elseif t == "nil" then
value = nil
else
value = tostring( entry.value )
end
local node
if value == nil then
node = self.tree:AppendItem( parent, entry.name )
else
node = self.tree:AppendItem( parent, entry.name.." = "..value )
end
if isComplex then
self.tree:SetItemHasChildren( node, true )
self.complexValues[node:GetValue()] = entry.value
end
end
function meta.__index:onExpanding_( event )
local item = event:GetItem()
local cval = assert( self.complexValues[item:GetValue()] )
local value = cval:get()
for _, entry in ipairs( value ) do
self:append_( item, entry )
end
end
function meta.__index:onCollapsed_( event )
local item = event:GetItem()
self:releaseHierarchy_( item )
self.tree:DeleteChildren( item )
self.tree:SetItemHasChildren( item, true )
end
function meta.__index:releaseHierarchy_( item )
local child = self.tree:GetFirstChild( item )
while child:IsOk() do
local cval = self.complexValues[child:GetValue()]
if cval ~= nil then
cval:release()
self.complexValues[child:GetValue()] = nil
end
self:releaseHierarchy_( child )
child = self.tree:GetNextSibling( child )
end
end
function meta.__index:refresh()
assert( self.interactive )
local exprItem = self.tree:GetFirstChild( self.root )
while exprItem:IsOk() do
self:releaseHierarchy_( exprItem )
self.tree:Collapse( exprItem )
self.tree:DeleteChildren( exprItem )
if self.complexValues[exprItem:GetValue()] ~= nil then
self.tree:SetItemHasChildren( exprItem, true )
end
exprItem = self.tree:GetNextSibling( exprItem )
end
for _, cval in pairs( self.complexValues ) do
assert( getmetatable( cval ) == evaluableItemMeta ) -- all other values should have been released
end
end
function meta.__index:clear()
local item = self.root
self:releaseHierarchy_( item )
self.tree:DeleteChildren( item )
end
function meta.__index:onBeginEdit_( event )
local item = event:GetItem()
local parent = self.tree:GetItemParent( item )
if parent:GetValue() ~= self.root:GetValue() then
event:Veto() -- only direct children of root can be edited
end
end
function meta.__index:onEdited_( event )
local item = event:GetItem()
assert( self.tree:GetItemParent( item ):GetValue() == self.root:GetValue() )
self:releaseHierarchy_( item )
self.tree:Collapse( item )
self.tree:DeleteChildren( item )
local expr = event:GetLabel()
local cval = { evaluate = function() return self.evaluateCallback( expr ) end }
setmetatable( cval, evaluableItemMeta )
self.complexValues[item:GetValue()] = cval
self.tree:SetItemHasChildren( item, true )
if self.tree:GetLastChild( self.root ):GetValue() == item:GetValue() then
self.tree:AppendItem( self.root, promptString )
end
self.tree:Expand( item )
end
function meta.__index:onKeyDown_( event )
if event:GetKeyCode() == wx.WXK_DELETE then
local item = self.tree:GetSelection()
if item:IsOk() then
local parent = self.tree:GetItemParent( item )
if parent:GetValue() == self.root:GetValue() and item:GetValue() ~= self.tree:GetLastChild( self.root ):GetValue() then
self:releaseHierarchy_( item )
self.tree:Delete( item )
end
end
end
end
function evaluableItemMeta.__index:get()
return self.evaluate()
end
function evaluableItemMeta.__index:release()
-- nothing to do
end

364
server/wxLdb/ui/mainWindow.lua

@ -0,0 +1,364 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local socket = require( "socket" )
local mainthread = require( "mainthread" )
local ui =
{
threads = require( "ui.threads" ),
callstack = require( "ui.callstack" ),
sourcePage = require( "ui.sourcePage" ),
promptMountPath = require( "ui.promptMountPath" ),
id = require( "ui.id" ),
luaExplorer = require( "ui.luaExplorer" ),
notification = require( "ui.notification" ),
about = require( "ui.about" ),
}
local setmetatable = setmetatable
local table = table
local debug = debug
local xpcall = xpcall
local pairs = pairs
local assert = assert
local string = string
local type = type
local os = os
local io = io
module( "ui.mainWindow" )
ID_BREAK = ui.id.new()
ID_CONTINUE = ui.id.new()
ID_STEP_OVER = ui.id.new()
ID_STEP_INTO = ui.id.new()
ID_STEP_OUT = ui.id.new()
ID_TOGGLE_BREAKPOINT = ui.id.new()
ID_FILE_OPEN = ui.id.new()
ID_FILE_CLOSE = ui.id.new()
ID_HELP_MANUAL = ui.id.new()
ID_HELP_ABOUT = ui.id.new()
ID_EXIT = wx.wxID_EXIT
local meta = { __index = {} }
function new()
local res = {}
setmetatable( res, meta )
res:init()
return res
end
function meta.__index:init()
self.frame = wx.wxFrame( wx.NULL, wx.wxID_ANY, "GRLD server", wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxDEFAULT_FRAME_STYLE + wx.wxMAXIMIZE)
mainthread.init( self.frame )
self:initLayout_()
self.mountPathPopup = ui.promptMountPath.new()
self.notificationPopup = ui.notification.new()
self.idleUpdates = {}
self.frame:Connect( wx.wxEVT_IDLE, function( event ) self:onIdleUpdate_( event ) end )
self.events = { onBreakPointChanged = {}, onFileOpen = {}, onFileClosed = {}, onApplicationExiting = {} }
end
function meta.__index:show( show )
self.frame:Show( show )
end
function meta.__index:close()
self.frame:Close()
end
function meta.__index:initLayout_()
self.root = wx.wxSplitterWindow( self.frame, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, 0 ) -- root widget
self.sourceBook = wx.wxNotebook( self.root, wx.wxID_ANY ) -- book of source code pages
self.debugRoot = wx.wxSplitterWindow( self.root, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
-- threads window
self.threads = ui.threads.new( self.debugRoot, self.frame )
self.debugBooks = wx.wxSplitterWindow( self.debugRoot, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
self.debugBookL = wx.wxNotebook( self.debugBooks, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxNB_BOTTOM )
self.debugBookR = wx.wxNotebook( self.debugBooks, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxNB_BOTTOM )
-- callstack window
self.callstack = ui.callstack.new( self.debugBookL )
self.debugBookL:AddPage( self.callstack:getRoot(), "Call stack" )
-- automatic variables window
self.auto = ui.luaExplorer.new( self.debugBookR, false )
self.debugBookR:AddPage( self.auto:getRoot(), "Automatic variables" )
-- watch window
self.watch = ui.luaExplorer.new( self.debugBookR, true )
self.debugBookR:AddPage( self.watch:getRoot(), "Watch" )
self.root:SplitHorizontally( self.sourceBook, self.debugRoot, -200 )
self.debugRoot:SplitVertically( self.threads:getRoot(), self.debugBooks, 250 )
self.debugBooks:SplitVertically( self.debugBookL, self.debugBookR )
self.sourcePages = {}
local fileMenu = wx.wxMenu()
fileMenu:Append( ID_FILE_OPEN, "&Open\tCtrl-O", "Open a source file" )
fileMenu:Append( ID_FILE_CLOSE, "&Close\tCtrl-F4", "Close the current source file" )
fileMenu:Append( ID_EXIT, "E&xit\tAlt-F4", "Exit the GRLD server" )
local debugMenu = wx.wxMenu()
debugMenu:Append( ID_BREAK, "&Break\tF12", "Stop execution of the program at the next executed line of code" )
debugMenu:Append( ID_CONTINUE, "&Continue\tF5", "Run the program at full speed" )
debugMenu:Append( ID_STEP_OVER, "&Step over\tF10", "Step over a line" )
debugMenu:Append( ID_STEP_INTO, "Step &into\tF11", "Step into a line" )
debugMenu:Append( ID_STEP_OUT, "Step &out\tShift-F11", "Step out of the current function" )
debugMenu:Append( ID_TOGGLE_BREAKPOINT, "&Toggle breakpoint\tF9", "Toggle the breakpoint on the current line" )
local helpMenu = wx.wxMenu()
helpMenu:Append( ID_HELP_MANUAL, "&Manual", "Send the GRLD manual to your web browser" )
helpMenu:Append( ID_HELP_ABOUT, "&About", "Open a window with various information about GRLD" )
local menuBar = wx.wxMenuBar()
menuBar:Append( fileMenu, "&File" )
menuBar:Append( debugMenu, "&Debug" )
menuBar:Append( helpMenu, "&Help" )
self.frame:SetMenuBar( menuBar )
self.frame:Connect( ID_FILE_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... ) self:onFileOpen_( ... ) end )
self.frame:Connect( ID_FILE_CLOSE, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... ) self:onFileClose_( ... ) end )
self.frame:Connect( ID_HELP_MANUAL, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... ) self:onHelpManual_( ... ) end )
self.frame:Connect( ID_HELP_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... ) self:onHelpAbout_( ... ) end )
self.frame:Connect( ID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... ) self:onExitCommand_( ... ) end )
self.frame:Connect( wx.wxEVT_CLOSE_WINDOW, function( ... ) self:onWindowClosed_( ... ) end )
end
function meta.__index:registerEvent( ID, callback )
if type( ID ) == "string" then
assert( self.events[ID] ~= nil, "Unknown event name "..ID )
table.insert( self.events[ID], callback )
else
if self.events[ID] == nil then
self.events[ID] = {}
mainthread.execute( function()
self.frame:Connect( ID, wx.wxEVT_COMMAND_MENU_SELECTED, function( ... )
for _, callback in ipairs( self.events[ID] ) do
callback( ... )
end
end )
end )
end
table.insert( self.events[ID], callback )
end
end
function meta.__index:runEvents_( eventName, ... )
for _, callback in pairs( self.events[eventName] ) do
callback( ... )
end
end
function meta.__index:onFileOpen_( event )
local fullPath = nil
local fileDialog = wx.wxFileDialog( self.frame, "Open file", "", "", "Lua files (*.lua)|*.lua|Text files (*.txt)|*.txt|All files (*)|*", wx.wxOPEN + wx.wxFILE_MUST_EXIST )
if fileDialog:ShowModal() == wx.wxID_OK then
fullPath = fileDialog:GetPath()
end
fileDialog:Destroy()
if fullPath ~= nil then
self:runEvents_( "onFileOpen", fullPath )
end
end
function meta.__index:onFileClose_( event )
local idx = self.sourceBook:GetSelection()
if idx >= 0 and idx < self.sourceBook:GetPageCount() then
local page = nil
local source = nil
for s, p in pairs( self.sourcePages ) do
if p.pageIdx == idx then
page = p
source = s
elseif p.pageIdx > idx then
p.pageIdx = p.pageIdx - 1
end
end
assert( page ~= nil )
self.sourceBook:DeletePage( page.pageIdx )
page:destroy()
self.sourcePages[source] = nil
self:runEvents_( "onFileClosed", source )
end
end
function meta.__index:onHelpManual_()
local docPath = "../doc/index.html"
-- get the command to start the default web browser from the registry (MS Windows only)
local pipe = io.popen( "reg query HKEY_CLASSES_ROOT\\HTTP\\shell\\open\\command" )
local data = pipe:read( "*a" )
pipe:close()
-- example of returned data (Windows XP):
--! REG.EXE VERSION 3.0
--
--HKEY_CLASSES_ROOT\HTTP\shell\open\command
-- <SANS NOM> REG_SZ "E:\Outils\Firefox\firefox.exe" -requestPending -osint -url "%1"
-- other example (on Vista)
--HKEY_CLASSES_ROOT\HTTP\shell\open\command
-- (par défaut) REG_SZ "C:\Program Files\Mozilla Firefox\firefox.exe" -requestPending -osint -url "%1"
-- parse returned data
local _, _, cmd = string.find( data, "REG_SZ%s+(.+)" )
local result = -1
if cmd ~= nil then
if string.find( cmd, "%%1" ) ~= nil then
cmd = string.gsub( cmd, "%%1", docPath )
else
if string.sub( cmd, -1 ) ~= " " then
cmd = cmd.." "
end
cmd = cmd.."\""..docPath.."\""
end
print( cmd )
-- start the default browser with the GRLD documentation as parameter
result = os.execute( "start \"GRLD documentation\" "..cmd )
end
if result ~= 0 then
wx.wxMessageBox( "Unable to start your default web browser to display the GRLD manual. You can instead open the following file with any HTML or text viewer: "..string.sub(docPath,4), "Error" )
end
end
function meta.__index:onHelpAbout_()
ui.about.popup()
end
function meta.__index:onExitCommand_( event )
self.frame:Close()
end
function meta.__index:onWindowClosed_( event )
print( "Main window closed" )
self:runEvents_( "onApplicationExiting" )
event:Skip( true ) -- allow it to really exit
self.mountPathPopup:destroy()
self.notificationPopup:destroy()
self.frame:Destroy()
end
function meta.__index:getSourcePages()
return self.sourcePages
end
function meta.__index:getSourcePage( source )
local page = self.sourcePages[source]
if page == nil then
page = mainthread.execute( function() return ui.sourcePage.new( self.sourceBook, source ) end )
self.sourcePages[source] = page
local _, _, name = string.find( source, ".*[/\\](.*)" )
if name == nil then name = source end
local maxLen = 16
if #name > 16 then
name = string.sub( name, 1, 7 ).."..."..string.sub( name, -7 )
end
page.pageIdx = self.sourceBook:GetPageCount()
self.sourceBook:AddPage( page:getRoot(), name )
page:registerEvent( "onBreakPointChanged", function( ... ) self:runEvents_( "onBreakPointChanged", source, ... ) end )
end
return page
end
function meta.__index:findSourcePage( source )
return self.sourcePages[source]
end
function meta.__index:setSourcePageFocus( source )
local page = self:getSourcePage( source )
self.sourceBook:ChangeSelection( page.pageIdx )
end
function meta.__index:findSourcePageFocus()
local idx = self.sourceBook:GetSelection()
if idx >= 0 and idx < self.sourceBook:GetPageCount() then
local page = nil
local source = nil
for s, p in pairs( self.sourcePages ) do
if p.pageIdx == idx then
return s, p:getFocus()
end
end
end
return nil
end
function meta.__index:clearMarkers()
for _, page in pairs( self.sourcePages ) do
page:clearMarkers()
end
end
function meta.__index:clearOtherLines()
for _, page in pairs( self.sourcePages ) do
page:clearOtherLines()
end
end
function meta.__index:clearBreakPoints()
for _, page in pairs( self.sourcePages ) do
page:clearBreakPoints()
end
end
function meta.__index:setCurrentLine( source, line )
for _, page in pairs( self.sourcePages ) do
page:setCurrentLine( nil )
end
local page = self:getSourcePage( source )
page:setCurrentLine( line )
end
function meta.__index:addIdleUpdate( func )
table.insert( self.idleUpdates, func )
end
function meta.__index:promptMountPath( ... )
return self.mountPathPopup:run( ... )
end
function meta.__index:notification( text )
return self.notificationPopup:run( text )
end
function meta.__index:setActive()
self.active = true
end
function meta.__index:onIdleUpdate_( event )
local currentPageIdx = self.sourceBook:GetSelection()
for _, page in pairs( self.sourcePages ) do
if currentPageIdx == page.pageIdx then
if page:update() then
assert( string.sub( page.source, 1, 1 ) == "@" )
self:runEvents_( "onFileOpen", string.sub( page.source, 2 ) )
end
end
end
self.active = false
for _, func in pairs( self.idleUpdates ) do
local ok, msg = xpcall( func, debug.traceback )
if not ok then print( "Error in idle update: "..msg ) end
end
if not self.active then
--socket.sleep( 0.05 )
end
event:RequestMore( true )
end

84
server/wxLdb/ui/notification.lua

@ -0,0 +1,84 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local mainthread = require( "mainthread" )
local utilities = require( "grldc.utilities" )
local setmetatable = setmetatable
local assert = assert
local coroutine = coroutine
local debug = debug
local error = error
local string = string
module( "ui.notification" )
local meta = { __index = {} }
function new()
local self = {}
setmetatable( self, meta )
self:initLayout_()
return self
end
function meta.__index:destroy()
self.dialog:Destroy()
end
function meta.__index:run( message )
assert( self.waiting == nil )
self.waiting = coroutine.running()
assert( self.waiting ~= nil )
self.message:SetLabel( message )
self.mainSizer:SetSizeHints( self.dialog )
self.dialog:Show( true )
local ok = coroutine.yield()
assert( self.waiting == coroutine.running() )
self.waiting = nil
self.dialog:Show( false )
return ok
end
function meta.__index:initLayout_()
self.dialog = wx.wxDialog( wx.NULL, wx.wxID_ANY, "Notification", wx.wxDefaultPosition, wx.wxDefaultSize )
local panel = wx.wxPanel( self.dialog, wx.wxID_ANY )
local vSizer = wx.wxBoxSizer( wx.wxVERTICAL )
self.mainSizer = vSizer
local sizer
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
self.message = wx.wxStaticText( panel, wx.wxID_ANY, "test message" )
sizer:Add( self.message )
vSizer:Add( sizer )
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
local ok = wx.wxButton( panel, wx.wxID_ANY, "OK" )
mainthread.execute( function()
self.dialog:Connect( ok:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( true ) end )
end )
sizer:Add( ok )
local cancel = wx.wxButton( panel, wx.wxID_ANY, "Cancel" )
mainthread.execute( function()
self.dialog:Connect( cancel:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( false ) end )
end )
sizer:Add( cancel )
vSizer:Add( sizer )
panel:SetSizer( vSizer )
vSizer:SetSizeHints( self.dialog )
mainthread.execute( function()
self.dialog:Connect( wx.wxEVT_CLOSE_WINDOW, function() self:onEnd_( false ) end )
end )
end
function meta.__index:onEnd_( ok )
local status, msg = coroutine.resume( self.waiting, ok )
assert( status, debug.traceback( self.waiting, msg ) )
end

154
server/wxLdb/ui/promptMountPath.lua

@ -0,0 +1,154 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local mainthread = require( "mainthread" )
local utilities = require( "grldc.utilities" )
local setmetatable = setmetatable
local assert = assert
local coroutine = coroutine
local debug = debug
local error = error
local string = string
module( "ui.promptMountPath" )
local meta = { __index = {} }
local function checkPath( user, auto )
if auto == nil then return true end
if string.sub( auto, 1, #user ) ~= user then
wx.wxMessageBox( "Bad path: "..user.." not prefix of "..auto, "Error" )
return false
end
local s = string.sub( auto, #user, #user )
if s ~= "/" and s ~= "\\" then
--print( user.." does not finish with /" )
s = string.sub( auto, #user+1, #user+1 )
end
if s ~= "/" and s ~= "\\" and s ~= "" then
wx.wxMessageBox( "Bad path: "..user.." does not finish with / and is not a parent directory of "..auto, "Error" )
return false
end
return true
end
function new()
local self = {}
setmetatable( self, meta )
self:initLayout_()
return self
end
function meta.__index:destroy()
self.dialog:Destroy()
end
function meta.__index:run( remotePath, localPath, fileName )
if remotePath ~= nil and localPath == nil and fileName ~= nil then
-- we can use the file open dialog to select the local file
local fullPath = nil
local fileDialog = wx.wxFileDialog( wx.NULL, "Find source file: "..remotePath..fileName, "", fileName, "Lua files (*.lua)|*.lua|Text files (*.txt)|*.txt|All files (*)|*", wx.wxOPEN + wx.wxFILE_MUST_EXIST )
if fileDialog:ShowModal() == wx.wxID_OK then
fullPath = fileDialog:GetPath()
end
fileDialog:Destroy()
if fullPath == nil then return nil end
fullPath = utilities.normalizePath( fullPath )
if string.sub( fullPath, -#fileName-1 ) ~= "/"..fileName then
wx.wxMessageBox( "Remote file and local file must have the same name", "Invalid local source file" )
return nil
else
local lPath = string.sub( fullPath, 1, -#fileName-2 )
local rPath = utilities.normalizePath( remotePath )
--[[while true do
print( lPath, rPath )
local suffix
_, _, suffix = string.find( lPath, ".*(/.+)$" )
if suffix == nil then break end
if string.sub( rPath, -#suffix ) ~= suffix then break end
lPath = string.sub( lPath, 1, -#suffix-1 )
rPath = string.sub( rPath, 1, -#suffix-1 )
end]]
--return rPath, lPath
localPath = lPath
end
end
assert( self.waiting == nil )
self.waiting = coroutine.running()
assert( self.waiting ~= nil )
self.mount:SetValue( remotePath or "" )
self.path:SetValue( localPath or "" )
self.dialog:Show( true )
local ok = coroutine.yield()
assert( self.waiting == coroutine.running() )
self.waiting = nil
self.dialog:Show( false )
if ok then
local mount = self.mount:GetValue()
local path = self.path:GetValue()
if not checkPath( mount, remotePath ) or not checkPath( path, localPath ) then
return self:run( remotePath, localPath )
end
return mount, path
else
return nil
end
end
function meta.__index:initLayout_()
self.dialog = wx.wxDialog( wx.NULL, wx.wxID_ANY, "Unknown path", wx.wxDefaultPosition, wx.wxDefaultSize )
local panel = wx.wxPanel( self.dialog, wx.wxID_ANY )
local vSizer = wx.wxBoxSizer( wx.wxVERTICAL )
local sizer
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
local label = wx.wxStaticText( panel, wx.wxID_ANY, "Please map the following remote path, or a part of it, to the corresponding local path" )
sizer:Add( label )
vSizer:Add( sizer )
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
label = wx.wxStaticText( panel, wx.wxID_ANY, "remote path" )
sizer:Add( label )
self.mount = wx.wxTextCtrl( panel, wx.wxID_ANY )
sizer:Add( self.mount )
vSizer:Add( sizer )
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
label = wx.wxStaticText( panel, wx.wxID_ANY, "local path" )
sizer:Add( label )
self.path = wx.wxTextCtrl( panel, wx.wxID_ANY )
sizer:Add( self.path )
vSizer:Add( sizer )
sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
local ok = wx.wxButton( panel, wx.wxID_ANY, "OK" )
mainthread.execute( function()
self.dialog:Connect( ok:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( true ) end )
end )
sizer:Add( ok )
local cancel = wx.wxButton( panel, wx.wxID_ANY, "Cancel" )
mainthread.execute( function()
self.dialog:Connect( cancel:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( false ) end )
end )
sizer:Add( cancel )
vSizer:Add( sizer )
panel:SetSizer( vSizer )
vSizer:SetSizeHints( self.dialog )
mainthread.execute( function()
self.dialog:Connect( wx.wxEVT_CLOSE_WINDOW, function() self:onEnd_( false ) end )
end )
end
function meta.__index:onEnd_( ok )
local status, msg = coroutine.resume( self.waiting, ok )
assert( status, debug.traceback( self.waiting, msg ) )
end

136
server/wxLdb/ui/sourcePage.lua

@ -0,0 +1,136 @@
-- see copyright notice in wxLdb.lua
local ui =
{
editor = require( "ui.editor" ),
}
local lfs = require( "lfs" )
local assert = assert
local setmetatable = setmetatable
local string = string
local pairs = pairs
local print = print
local table = table
local os = os
module( "ui.sourcePage" )
local meta = { __index = {} }
function new( parent, source )
local page = {}
setmetatable( page, meta )
page.editor = ui.editor.new( parent )
page.events = { onBreakPointChanged = {} }
page:setSource_( source )
page.editor.breakpointCallback = function( line )
page:runEvents_( "onBreakPointChanged", line )
end
return page
end
function meta.__index:getRoot()
return self.editor.editor
end
function meta.__index:setSource_( source )
assert( string.sub( source, 1, 1 ) == "@" )
local fileName = string.sub( source, 2 )
self.source = source
self.editor.editor:SetReadOnly( false )
self.sourceDate = lfs.attributes( fileName, "modification" ) or 0
self.editor.editor:LoadFile( fileName )
self.editor.editor:SetReadOnly( true )
self.lastUpdate = os.time()
end
function meta.__index:update()
local now = os.time()
if now > self.lastUpdate + 2 then
self.lastUpdate = now
assert( string.sub( self.source, 1, 1 ) == "@" )
local fileName = string.sub( self.source, 2 )
local newDate = lfs.attributes( fileName, "modification" ) or 0
if newDate > self.sourceDate then
print( "reloading source file "..fileName )
self.sourceDate = newDate
self.editor.editor:SetReadOnly( false )
self.editor.editor:LoadFile( fileName )
self.editor.editor:SetReadOnly( true )
return true
end
end
return false
end
function meta.__index:setFocus( line )
self.editor.editor:GotoLine( line-4 )
self.editor.editor:GotoLine( line+4 )
self.editor.editor:GotoLine( line-1 )
end
function meta.__index:getFocus()
local ed = self.editor.editor
return ed:GetCurrentLine() + 1
end
function meta.__index:setCurrentLine( line )
local editor = self.editor.editor
if self.currentLine == line then return end
if self.currentLine ~= nil then
editor:MarkerDelete( self.currentLine - 1, ui.editor.markers.currentLine )
end
self.currentLine = line
if self.currentLine ~= nil then
editor:MarkerAdd( self.currentLine - 1, ui.editor.markers.currentLine )
end
end
function meta.__index:addOtherLine( line )
self.editor.editor:MarkerAdd( line - 1, ui.editor.markers.otherLine )
end
function meta.__index:clearOtherLines()
self.editor.editor:MarkerDeleteAll( ui.editor.markers.otherLine )
end
function meta.__index:addBreakPoint( line, bad )
local mt = ui.editor.markers.breakpoint
if bad then
mt = ui.editor.markers.badBreakpoint
end
self.editor.editor:MarkerAdd( line - 1, mt )
end
function meta.__index:clearBreakPoints()
self.editor.editor:MarkerDeleteAll( ui.editor.markers.breakpoint )
self.editor.editor:MarkerDeleteAll( ui.editor.markers.badBreakpoint )
end
function meta.__index:clearMarkers()
self.currentLine = nil
self.editor.editor:MarkerDeleteAll( ui.editor.markers.currentLine )
self.editor.editor:MarkerDeleteAll( ui.editor.markers.otherLine )
end
function meta.__index:registerEvent( eventName, callback )
assert( self.events[eventName] ~= nil, "Unknown event name "..eventName )
table.insert( self.events[eventName], callback )
end
function meta.__index:runEvents_( eventName, ... )
for _, callback in pairs( self.events[eventName] ) do
callback( ... )
end
end
function meta.__index:destroy()
self.editor:destroy()
end

135
server/wxLdb/ui/threads.lua

@ -0,0 +1,135 @@
-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local setmetatable = setmetatable
local table = table
local debug = debug
local xpcall = xpcall
local pairs = pairs
local ipairs = ipairs
local assert = assert
local tostring = tostring
local ui =
{
id = require( "ui.id" ),
}
module( "ui.threads" )
local meta = { __index = {} }
local ID_CLIENT_BREAK_ON_CONNECT = ui.id.new()
function new( ... )
local res = {}
setmetatable( res, meta )
res:init( ... )
return res
end
function meta.__index:init( parentWidget, frame )
self.events = { onThreadClicked = {}, onBreakOnConnectionChanged = {} }
self.popups = {}
setmetatable( self.popups, { __mode = "v" } )
self.frame = frame
self.tree = wx.wxTreeCtrl( parentWidget, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxTR_HIDE_ROOT + wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS )
local imageList = wx.wxImageList(16, 16)
imageList:Add(wx.wxArtProvider.GetBitmap(wx.wxART_GO_FORWARD, wx.wxART_TOOLBAR, wx.wxSize(16, 16)))
imageList:Add(wx.wxArtProvider.GetBitmap(wx.wxART_EXECUTABLE_FILE, wx.wxART_TOOLBAR, wx.wxSize(16, 16)))
self.tree:AssignImageList( imageList )
self.root = self.tree:AddRoot( "clients" )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED, function( event )
if self.disableInputs then return end
local item = event:GetItem()
local data = assert( self.nodeData[item:GetValue()] )
--print( "thread selected: "..data.clientId..", "..data.threadId )
self:runEvents_( "onThreadClicked", data.clientId, data.threadId )
end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, function( event )
local item = event:GetItem()
local data = assert( self.nodeData[item:GetValue()] )
if data.threadId == "current" then -- right click on a client
menu = wx.wxMenu()
self.popups[menu] = data
menu:Append( ID_CLIENT_BREAK_ON_CONNECT, "Break on connection", "Specify if the client should break execution each time it connects to the server", wx.wxITEM_CHECK )
menu:Check( ID_CLIENT_BREAK_ON_CONNECT, data.breakOnConnection )
self.tree:PopupMenu( menu )
end
end )
self.frame:Connect( ID_CLIENT_BREAK_ON_CONNECT, wx.wxEVT_COMMAND_MENU_SELECTED, function( event )
local data = assert( self.popups[event:GetEventObject():DynamicCast( "wxMenu" )] )
data.breakOnConnection = event:IsChecked()
self:runEvents_( "onBreakOnConnectionChanged", data.clientId, data.breakOnConnection )
end )
end
function meta.__index:getRoot()
return self.tree
end
function meta.__index:registerEvent( eventName, callback )
assert( self.events[eventName] ~= nil, "Unknown event name "..eventName )
table.insert( self.events[eventName], callback )
end
function meta.__index:runEvents_( eventName, ... )
for _, callback in pairs( self.events[eventName] ) do
callback( ... )
end
end
function meta.__index:setData( data )
self.disableInputs = true
if self.data ~= nil then
self.tree:DeleteChildren( self.root )
self.data = nil
end
if data ~= nil then
self.data = {}
self.nodeData = {}
for _, client in pairs( data ) do
local cdata = {}
cdata.node = self.tree:AppendItem( self.root, client.name.." ["..client.ip.."]", 1 )
if client.active then
self.tree:SetItemBold( cdata.node, true )
self.tree:SelectItem( cdata.node, true )
end
--print( "client:", cdata.node, cdata.node:GetValue() )
self.nodeData[cdata.node:GetValue()] = { clientId = client.clientId, threadId = "current", breakOnConnection = client.breakOnConnection }
cdata.coroutines = {}
for _, co in ipairs( client.coroutines ) do
local codata = {}
local label = ""
--if co.current then
-- label = "-> "
--end
label = label..co.id
local imageIdx = -1
if co.current then
imageIdx = 0
end
codata.node = self.tree:AppendItem( cdata.node, label, imageIdx )
self.nodeData[codata.node:GetValue()] = { clientId = client.clientId, threadId = co.id }
--print( "\tthread:", codata.node, codata.node:GetValue() )
if co.active then
self.tree:SetItemBold( codata.node, true )
self.tree:SelectItem( codata.node, true )
end
table.insert( cdata.coroutines, codata )
end
self.tree:Expand( cdata.node )
table.insert( self.data, cdata )
end
end
self.disableInputs = false
end

59
server/wxLdb/wxLdb.lua

@ -0,0 +1,59 @@
-- Copyright (C) 2010-2016 Youen Toupin.
-- This file is part of GRLD, a Graphical Remote Lua Debugger
-- GRLD is distributed under the MIT license (http://www.opensource.org/licenses/mit-license.html), a copy of which is included below.
--[[
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local listenIP = arg[1] or "*"
local listenPort = tonumber( arg[2] ) or 4242
package.cpath = package.cpath..";../lua/?.dll"
package.path = package.path..";wxLdb/?.lua"
package.path = package.path..";../shared/?.lua"
local window = require( "ui.mainWindow" ).new()
local engine = require( "grld.engine" )
local controller = require( "wxLdbController" ).new( engine, window )
controller:addListener( listenIP, listenPort )
local function updateEngine()
local active = false
if engine.initialized() then
active = engine.update( 0.01 )
end
if active then
window:setActive()
end
controller:update()
end
window:addIdleUpdate( updateEngine )
if wxLdb_hook ~= nil then
-- used by automatic tests : they need to get the controller before entering the wxWidgets main loop
wxLdb_hook( controller )
end
wx.wxGetApp():MainLoop()
engine.shutdown()

810
server/wxLdb/wxLdbController.lua

@ -0,0 +1,810 @@
-- see copyright notice in wxLdb.lua
local grldc =
{
net = require( "grldc.net" ),
utilities = require( "grldc.utilities" )
}
local ui =
{
mainWindow = require( "ui.mainWindow" )
}
local lfs = require( "lfs" )
require( "coxpcall" )
local coxpcall = coxpcall
local copcall = copcall
local setmetatable = setmetatable
local ipairs = ipairs
local type = type
local assert = assert
local pairs = pairs
local next = next
local print = print
local tostring = tostring
local string = string
local coroutine = coroutine
local io = io
local debug = debug
local xpcall = xpcall
local table = table
local os = os
module( "wxLdbController" )
local meta = { __index = {} }
local complexValueManagerMeta = { __index = {} }
function new( engine, window )
local res =
{
engine = engine,
window = window,
clients = {},
configs = {},
activeClient = nil,
threadsDirty = true,
exiting = false,
requests_ = {},
toListen = {},
}
setmetatable( res, meta )
res.runCoroutine = coroutine.create( function() res:run_() end )
local ok, msg = coroutine.resume( res.runCoroutine )
assert( ok, debug.traceback( res.runCoroutine, msg ) )
return res
end
function meta.__index:ready_()
return self.sleeping and #self.requests_ == 0
end
function meta.__index:addListener( ip, port )
if self.engine.initialized() then
self.engine.listen( ip, port )
else
table.insert( self.toListen, { ip = ip, port = port } )
end
end
function meta.__index:update()
if self:ready_() then
self.sleeping = false
local ok, msg = coroutine.resume( self.runCoroutine )
assert( ok, debug.traceback( self.runCoroutine, msg ) )
elseif self.currentRequest_ ~= nil then
if coroutine.status( self.currentRequest_ ) ~= "suspended" then
print( "Asynchronous request has terminated" )
table.remove( self.requests_, 1 )
self.currentRequest_ = nil
end
elseif self.requests_[1] ~= nil then
print( "Starting asynchronous request..." )
local req = self.requests_[1]
local co = coroutine.create( req )
self.currentRequest_ = co
local ok, msg = coroutine.resume( co )
assert( ok, debug.traceback( co, msg ) )
end
end
function meta.__index:sleep_()
self.sleeping = true
coroutine.yield()
end
function meta.__index:queueRequest_( req )
table.insert( self.requests_, req )
end
function meta.__index:run_()
self:sleep_()
--@GRLD_PROTECTION@
self.engine.init()
for _, listener in ipairs( self.toListen ) do
self.engine.listen( listener.ip, listener.port )
end
self.toListen = {}
self.window:show( true )
for _, cbName in ipairs( { "onNewClient", "onClientBreak", "onClientLost" } ) do
self.engine.registerEvent( cbName, function( ... ) return self[cbName.."_"]( self, ... ) end )
end
local wrapCb = function( cb )
return function( ... )
if self:ready_() then
return cb( ... )
end
end
end
self.window:registerEvent( ui.mainWindow.ID_BREAK, wrapCb( function() self:onDebugCommand_( "breaknow", "running" ) end ) )
self.window:registerEvent( ui.mainWindow.ID_CONTINUE, wrapCb( function() self:onDebugCommand_( "run", "break" ) end ) )
self.window:registerEvent( ui.mainWindow.ID_STEP_OVER, wrapCb( function() self:onDebugCommand_( "stepover", "break" ) end ) )
self.window:registerEvent( ui.mainWindow.ID_STEP_INTO, wrapCb( function() self:onDebugCommand_( "stepin", "break" ) end ) )
self.window:registerEvent( ui.mainWindow.ID_STEP_OUT, wrapCb( function() self:onDebugCommand_( "stepout", "break" ) end ) )
self.window:registerEvent( ui.mainWindow.ID_TOGGLE_BREAKPOINT, wrapCb( function() self:onToggleBreakpoint_() end ) )
self.window:registerEvent( "onBreakPointChanged", wrapCb( function( ... ) self:onBreakPointChanged_( ... ) end ) )
self.window:registerEvent( "onFileOpen", wrapCb( function( ... ) self:onFileOpen_( ... ) end ) )
self.window:registerEvent( "onFileClosed", wrapCb( function( ... ) self:onFileClosed_( ... ) end ) )
self.window:registerEvent( "onApplicationExiting", wrapCb( function( ... ) self:onApplicationExiting_( ... ) end ) )
self.window.threads:registerEvent( "onThreadClicked", wrapCb( function( ... ) self:onThreadClicked_( ... ) end ) )
self.window.threads:registerEvent( "onBreakOnConnectionChanged", wrapCb( function( ... ) self:onBreakOnConnectionChanged_( ... ) end ) )
self.window.callstack:registerEvent( "onCallstackClicked", wrapCb( function( ... ) self:onCallstackClicked_( ... ) end ) )
self.window.watch.evaluateCallback = wrapCb( function( expr ) return self:evaluateExpression_( expr ) end )
self.configs.global = { name = "global", breakpoints = {} }
self:loadConfig_( "global" )
self:sleep_()
while not self.exiting do
for clientId, clientData in pairs( self.clients ) do
coxpcall( function()
if clientData.invalidateTimer ~= nil then
if os.time() >= clientData.invalidateTimer then
clientData.invalidateTimer = nil
assert( clientId == self.activeClient )
self:invalidateState_( true )
end
end
if clientData.config.dirty and os.time() >= (clientData.config.lastConfigSave or 0) + 10 then
self:saveConfig_( clientData.config.name )
end
if clientData.dirty then
self.window:setActive()
clientData.dirty = false
local client = self.engine.getClient( clientId )
if client == nil then
self.threadsDirty = true
elseif clientId == self.activeClient then
if client:status() == "break" then
client:setactivethread( clientData.activeThread )
self.threadsDirty = true
local callstack = client:callstack()
if type( callstack ) ~= "table" then
-- if we can not get the callstack, we try to switch to the current thread
clientData.activeThread = "current"
client:setactivethread( clientData.activeThread )
callstack = client:callstack()
end
self:refreshCallstack_( callstack )
self:refreshSourceFocus_( callstack, clientData.activeLevel )
end
self:refreshBreakPoints_()
end
elseif clientData.lastUpdate == nil or os.time() > clientData.lastUpdate + 2 then
clientData.lastUpdate = os.time()
self.engine.getClient( clientId ):checkConnection()
end
end, function( msg ) print( "Error refreshing client "..clientId ) print( msg ) print( debug.traceback() ) end )
end
if self.threadsDirty then
coxpcall( function()
self.threadsDirty = false
self:refreshThreads_()
end, function( msg ) print( "Error refreshing threads" ) print( msg ) print( debug.traceback() ) end )
end
self:sleep_()
end
end
function meta.__index:evaluateExpression_( expr )
local clientId = self.activeClient
local client = self.engine.getClient( clientId )
if client == nil then return { { name = "<no such client>" } } end
if client:status() == "running" then return { { name = "<can't evaluate expression while client is running>" } } end
local clientData = assert( self.clients[clientId] )
local results = client:evaluate( expr, clientData.activeLevel )
complexValueManagerMeta.init( results, self.engine, clientId )
return results
end
function meta.__index:onCallstackClicked_( level )
local clientId = self.activeClient
local clientData = self.clients[clientId]
if clientData == nil then return end
clientData.activeLevel = level
clientData.dirty = true
end
function meta.__index:refreshSourcePageFocus_( remoteSource, line )
local clientId = self.activeClient
local clientData = assert( self.clients[clientId] )
local sourceType = string.sub( remoteSource, 1, 1 )
if sourceType == "@" then
print( "Setting focus to "..remoteSource.."("..line..")" )
remoteSource = grldc.utilities.normalizePath( string.sub( remoteSource, 2 ) )
local source, remotePath, remoteFile = self:getLocalSource_( clientId, remoteSource )
if source == nil then
print( "Prompting mount path..." )
local mount, path = self.window:promptMountPath( remotePath, nil, remoteFile )
print( mount, path )
if mount ~= nil then
mount = grldc.utilities.normalizePath( mount )
path = grldc.utilities.normalizePath( path, lfs.currentdir() )
print( mount, path )
local mountEnd = string.sub( mount, -1 )
if mountEnd ~= "/" and mountEnd ~= "\\" then
mount = mount.."/"
end
print( mount, path )
clientData.config.mappings[mount] = path
clientData.config.dirty = true
source = self:getLocalSource_( clientId, remoteSource )
assert( source ~= nil )
end
end
if source ~= nil then
print( source )
source = grldc.utilities.normalizePath( source )
self:setSourceFocus_( "@"..source, line )
end
--print( source )
return source
end
end
function meta.__index:refreshSourceFocus_( callstack, level )
local clientId = self.activeClient
local clientData = assert( self.clients[clientId] )
if type( callstack ) == "table" and callstack[level] ~= nil then
local remoteSource = callstack[level].source
local line = callstack[level].line
local source = self:refreshSourcePageFocus_( remoteSource, line )
self:setPointers_( level, source, line )
self:refreshPointers_()
self:refreshWatches_( level )
end
end
function meta.__index:setPointers_( level, source, line )
self.pointer = { level = level, source = source, line = line }
end
function meta.__index:refreshPointers_()
self.window:clearMarkers()
if self.pointer ~= nil then
local source = self.pointer.source
local level = self.pointer.level
local line = self.pointer.line
if source ~= nil then
if level == 1 then
self.window:setCurrentLine( "@"..source, line )
else
self.window:getSourcePage( "@"..source ):addOtherLine( line )
end
end
end
end
function meta.__index:refreshWatches_( level )
local clientId = self.activeClient
local client = self.engine.getClient( clientId )
if client == nil then return end
local autoVariables = {}
local locals = client:locals( level )
if type( locals ) == "string" then
self.window.auto:setData( { { name = "<error evaluating local variables>", value = locals } } )
else
for _, entry in ipairs( locals ) do
table.insert( autoVariables, { name = "[local] "..entry.name, value = entry.value } )
end
end
local upvalues = client:upvalues( level )
if type( upvalues ) == "string" then
self.window.auto:setData( { { name = "<error evaluating upvalues>", value = locals } } )
else
for _, entry in ipairs( upvalues ) do
table.insert( autoVariables, { name = "[upvalue] "..entry.name, value = entry.value } )
end
end
complexValueManagerMeta.init( autoVariables, self.engine, clientId )
self.window.auto:setData( autoVariables )
self.window.watch:refresh()
end
function meta.__index:onToggleBreakpoint_()
local source, line = self.window:findSourcePageFocus()
self:onBreakPointChanged_( source, line )
end
function meta.__index:onBreakPointChanged_( source, line )
local clientId = self.activeClient
local config = nil
if clientId == nil or self.clients[clientId] == nil then
config = self.configs.global
else
local clientData = self.clients[clientId]
if clientData == nil then return end
config = clientData.config
end
if config.breakpoints[source] == nil then
config.breakpoints[source] = {}
end
config.breakpoints[source][line] = not config.breakpoints[source][line]
newValue = config.breakpoints[source][line]
if not newValue then
config.breakpoints[source][line] = nil
end
print( "Setting breakpoint at "..source.."("..line..") to "..tostring(newValue) )
assert( string.sub( source, 1, 1 ) == "@" )
source = string.sub( source, 2 )
for clientId, clientData in pairs( self.clients ) do
if clientData.config == config then
local client = self.engine.getClient( clientId )
if client == nil then return end
local remoteSource, dir = self:getRemoteSource_( clientId, source )
self:queueRequest_( function()
if remoteSource == nil then
print( "Can't find remote source corresponding to "..source )
print( "Prompting mount path..." )
local mount, path = self.window:promptMountPath( nil, dir )
print( mount, path )
if mount ~= nil then
mount = grldc.utilities.normalizePath( mount )
path = grldc.utilities.normalizePath( path, lfs.currentdir() )
print( mount, path )
local mountEnd = string.sub( mount, -1 )
if mountEnd ~= "/" and mountEnd ~= "\\" then
mount = mount.."/"
end
print( mount, path )
clientData.config.mappings[mount] = path
remoteSource, dir = self:getRemoteSource_( clientId, source )
assert( remoteSource ~= nil )
end
end
if remoteSource ~= nil then
client:setbreakpoint( "@"..remoteSource, line, newValue )
clientData.config.dirty = true
end
self:refreshBreakPoints_()
end )
end
end
self:refreshBreakPoints_()
end
function meta.__index:onApplicationExiting_()
for id, clientData in pairs( self.clients ) do
if clientData.config.dirty then
self:saveConfig_( clientData.config.name )
end
end
self.window.threads:setData( nil )
end
function meta.__index:refreshBreakPoints_()
local clientId = self.activeClient
local config = nil
local client = nil
if self.activeClient == nil or self.clients[clientId] == nil then
config = self.configs.global
else
config = self.clients[clientId].config
client = self.engine.getClient( clientId )
end
local remoteBreakPoints = {}
if client ~= nil then
remoteBreakPoints = client:breakpoints()
end
self.window:clearBreakPoints()
local goodBreakpoints = {}
for remoteSource, lines in pairs( remoteBreakPoints ) do
if next( lines ) ~= nil then
local source = self:getLocalSource_( clientId, string.sub( remoteSource, 2 ) )
if source ~= nil then
local page = self.window:findSourcePage( "@"..source )
if page ~= nil then
if goodBreakpoints["@"..source] == nil then
goodBreakpoints["@"..source] = {}
end
for line, value in pairs( lines ) do
if value then
page:addBreakPoint( line )
goodBreakpoints["@"..source][line] = true
end
end
else
print( "Can't find source page for breakpoint in file "..source )
end
else
print( "Can't find source corresponding to remote source "..remoteSource )
end
end
end
for source, lines in pairs( config.breakpoints ) do
local page = self.window:findSourcePage( source )
if page ~= nil then
for line, value in pairs( lines ) do
if value then
if goodBreakpoints[source] == nil or not goodBreakpoints[source][line] then
page:addBreakPoint( line, true )
end
end
end
end
end
end
function meta.__index:onFileOpen_( path )
print( "onFileOpen: "..path )
source = "@"..grldc.utilities.normalizePath( path )
print( "normalized path: "..source )
self:setSourceFocus_( source, 1 )
self:refreshPointers_()
self:refreshBreakPoints_()
end
function meta.__index:onFileClosed_( source )
for id, clientData in pairs( self.clients ) do
clientData.config.dirty = true
end
end
function meta.__index:onThreadClicked_( clientId, threadId )
print( "Thread clicked: client="..clientId..", thread="..threadId )
local clientData = self.clients[clientId]
if clientData == nil then return end
clientData.activeThread = threadId
clientData.activeLevel = 1
self:setActiveClient_( clientId )
end
function meta.__index:onBreakOnConnectionChanged_( clientId, newValue )
local clientData = self.clients[clientId]
if clientData == nil then return end
clientData.config.breakOnConnection = newValue
clientData.config.dirty = true
end
function meta.__index:onDebugCommand_( command, neededState, targetClientId )
if targetClientId == nil then targetClientId = self.activeClient end
if targetClientId == nil then return end
local client = self.engine.getClient( targetClientId )
if client == nil then
print( "No client "..targetClientId )
return
end
if neededState ~= nil and client:status() ~= neededState then return end
self:invalidateState_( false )
local clientData = assert( self.clients[targetClientId] )
local ok, msg = xpcall( function() client[command]( client ) end, debug.traceback )
if not ok then
print( msg )
end
clientData.dirty = true
end
function meta.__index:invalidateState_( immediate )
local clientData = self.clients[self.activeClient]
if not clientData or immediate then
if clientData ~= nil then
clientData.invalidateTimer = nil
end
self.threadsDirty = true
self.pointer = nil
self.window:clearMarkers()
self.window.callstack:setData( nil )
self:refreshBreakPoints_()
local client = self.engine.getClient( self.activeClient )
if client == nil then
self.window.auto:clear()
self.window.watch:refresh()
else
self.window.auto:setData( nil )
self.window.watch:refresh()
end
else
clientData.invalidateTimer = os.time() + 1
end
end
function meta.__index:getLocalSource_( clientId, source )
--print( source )
local _, _, dir, file = string.find( source, "(.*[/\\])(.*)" )
assert( dir ~= nil and file ~= nil )
local clientData = assert( self.clients[clientId] )
for mount, path in pairs( clientData.config.mappings ) do
if string.sub( dir, 1, #mount ) == mount then
local s = string.sub( dir, #mount, #mount )
assert( s == "/" or s == "\\" )
local r = string.sub( dir, #mount + 1 )
if r ~= "" then r = r.."/" end
local localPath = grldc.utilities.normalizePath( path.."/"..r..file, lfs.currentdir() )
--print( localPath )
if lfs.attributes( localPath, "mode" ) == "file" then
return localPath, dir, file
end
end
end
return nil, dir, file
end
function meta.__index:getRemoteSource_( clientId, localSource )
print( "Searching remote source corresponding to local source "..localSource )
local _, _, dir, file = string.find( localSource, "(.*[/\\])(.*)" )
assert( dir ~= nil and file ~= nil )
local clientData = assert( self.clients[clientId] )
local bestScore = -1
local bestPath = nil
for mount, path in pairs( clientData.config.mappings ) do
if string.sub( dir, 1, #path ) == path then
local s = string.sub( dir, #path+1, #path+1 )
if s == "/" or s == "\\" then
local r = string.sub( dir, #path + 2 )
if r ~= "" then r = r.."/" end
local remotePath = grldc.utilities.normalizePath( mount..r..file )
local score = 0
string.gsub( mount, "[/\\]", function() score = score + 1 end )
print( "Candidate (score="..score..") : "..remotePath )
if score > bestScore then
bestScore = score
bestPath = remotePath
end
end
end
end
return bestPath, dir
end
function meta.__index:setSourceFocus_( source, line )
local exist = (self.window:findSourcePage( source ) ~= nil)
local page = self.window:getSourcePage( source )
page:setFocus( line )
self.window:setSourcePageFocus( source )
if not exist then
for id, clientData in pairs( self.clients ) do
clientData.config.dirty = true
end
end
end
function meta.__index:refreshCallstack_( callstack )
if type( callstack ) == "string" then
self.window.callstack:setData( { { name = callstack, type = "", source = "", line = "" } } )
elseif callstack[1] == nil then
self.window.callstack:setData( { { name = "empty callstack", type = "", source = "", line = "" } } )
else
local callstackData = {}
for level, data in ipairs( callstack ) do
local entry = {}
if data.namewhat ~= "" then
assert( data.name ~= nil )
entry.name = "["..data.namewhat.."] "..data.name
else
entry.name = "???"
end
entry.type = data.what
entry.source = data.source
if data.line < 0 then
entry.line = ""
else
entry.line = tostring( data.line )
end
callstackData[level] = entry
end
self.window.callstack:setData( callstackData )
end
end
function meta.__index:refreshThreads_()
local data = {}
for clientId, clientData in pairs( self.clients ) do
local client = self.engine.getClient( clientId )
if client == nil then
print( "Client does not exist anymore: "..clientId )
if self.activeClient == clientId then
self.activeClient = nil
self:invalidateState_( true )
end
self.clients[clientId] = nil
else
local cdata = {}
cdata.name = client:name()
cdata.ip = client:ip()
cdata.clientId = client.clientId
cdata.coroutines = {}
cdata.status = client:status()
cdata.active = (clientId == self.activeClient)
cdata.breakOnConnection = clientData.config.breakOnConnection
if cdata.status == "break" then
local current = client:getcurrentthread()
local active = client:getactivethread()
if active == "current" then
active = current
end
table.insert( cdata.coroutines, { id = "main", current = (current == "main"), active = (active=="main" and cdata.clientId == self.activeClient and client:getactivethread() ~= "current") } )
local coroutines = client:coroutines()
--print( coroutines )
for _, data in ipairs( coroutines ) do
local codata = {}
codata.id = data.id
codata.current = (current == codata.id)
codata.active = (active == codata.id and cdata.clientId == self.activeClient and client:getactivethread() ~= "current")
table.insert( cdata.coroutines, codata )
end
end
table.insert( data, cdata )
end
end
self.window.threads:setData( data )
end
function meta.__index:setActiveClient_( clientId )
self:invalidateState_( true )
self.activeClient = clientId
self.clients[clientId].dirty = true
self.threadsDirty = true
local clientConfig = self.clients[clientId].config
for source, lines in pairs( self.configs.global.breakpoints ) do
for line, _ in pairs( lines ) do
if clientConfig.breakpoints[source] == nil or not clientConfig.breakpoints[source][line] then
self:onBreakPointChanged_( source, line )
end
lines[line] = nil
end
end
self:refreshBreakPoints_()
end
function meta.__index:onNewClient_( clientId )
local client = self.engine.getClient( clientId )
local name = client:name()
if self.configs[name] == nil then
self.configs[name] = { name = name, mappings = {}, breakpoints = {} }
self:loadConfig_( name )
end
self.clients[clientId] = { dirty = true, activeThread = "current", activeLevel = 1, config = self.configs[name] }
for source, lines in pairs( self.configs[name].breakpoints ) do
assert( string.sub( source, 1, 1 ) == "@" )
source = string.sub( source, 2 )
local remoteSource, dir = self:getRemoteSource_( clientId, source )
if remoteSource ~= nil then
for line, value in pairs( lines ) do
if value then
client:setbreakpoint( "@"..remoteSource, line, true )
end
end
end
end
self.threadsDirty = true
if self.activeClient == nil then
self:setActiveClient_( clientId )
end
if not self.configs[name].breakOnConnection then
self.clients[clientId].ignoreNextBreak = true
end
end
function meta.__index:onClientBreak_( clientId )
local clientData = assert( self.clients[clientId] )
clientData.invalidateTimer = nil
clientData.dirty = true
clientData.activeLevel = 1
self.threadsDirty = true
if clientData.ignoreNextBreak then
clientData.ignoreNextBreak = false
self:onDebugCommand_( "run", "break", clientId )
end
end
function meta.__index:onClientLost_( clientId )
local clientData = assert( self.clients[clientId] )
if clientData.config.dirty then
self:saveConfig_( clientData.config.name )
end
self.threadsDirty = true
end
function meta.__index:saveConfig_( name )
local clientConfig = assert( self.configs[name] )
clientConfig.dirty = false
local name = clientConfig.name
local openFiles = {}
for source, page in pairs( self.window:getSourcePages() ) do
openFiles[page.pageIdx+1] = source
end
local breakpoints = clientConfig.breakpoints
local path = "clients/"..name.."/config.lua"
lfs.mkdir( "clients" )
lfs.mkdir( "clients/"..name )
local file = assert( io.open( path, "w" ) )
file:write( grldc.net.serialize( { mappings = clientConfig.mappings, openFiles = openFiles, breakpoints = breakpoints, breakOnConnection = clientConfig.breakOnConnection } ) )
file:close()
print( "Saved config \""..name.."\"" )
clientConfig.lastConfigSave = os.time()
end
function meta.__index:loadConfig_( name )
local clientConfig = self.configs[name]
local path = "clients/"..name.."/config.lua"
local file = io.open( path, "r" )
if file ~= nil then
local config = grldc.net.deserialize( file:read( "*a" ) )
file:close()
clientConfig.mappings = config.mappings
clientConfig.breakOnConnection = config.breakOnConnection
for _, file in ipairs( config.openFiles ) do
self.window:getSourcePage( file )
end
if config.breakpoints ~= nil then
for source, bp in pairs( config.breakpoints ) do
if clientConfig.breakpoints[source] == nil then
clientConfig.breakpoints[source] = {}
end
for line, _ in pairs( bp ) do
clientConfig.breakpoints[source][line] = true
end
end
end
end
if clientConfig.breakOnConnection == nil then
clientConfig.breakOnConnection = true
end
clientConfig.dirty = false
end
function complexValueManagerMeta.init( variables, engine, clientId )
local manager = nil
for _, entry in pairs( variables ) do
if type( entry.value ) == "table" and entry.value.id ~= nil then
if manager == nil then
manager = { engine = engine, clientId = clientId }
end
assert( entry.value.manager == nil )
entry.value.manager = manager
setmetatable( entry.value, complexValueManagerMeta )
end
end
end
function complexValueManagerMeta.__index:release()
local client = self.manager.engine.getClient( self.manager.clientId )
if client == nil then return end
client:releaseValue( self.id )
end
function complexValueManagerMeta.__index:get()
local client = self.manager.engine.getClient( self.manager.clientId )
if client == nil then return { ERROR = "connection with client lost" } end
local value = client:getValue( self.id )
complexValueManagerMeta.init( value, self.manager.engine, self.manager.clientId )
return value
end

219
shared/grldc/net.lua

@ -0,0 +1,219 @@
-- see copyright notice in grldc.h
local socket = require( "grldc.socket" )
local assert = assert
local setmetatable = setmetatable
local print = print
local error = error
local type = type
local tonumber = tonumber
local tostring = tostring
local loadstring = loadstring
local string = string
local table = table
local pairs = pairs
local globals = _G
module( "grldc.net" )
local listenerMeta = { __index = {} }
local connectionMeta = { __index = {} }
local function debugPrint( ... )
--print( ... )
end
function serialize( value )
local t = type( value )
if t == "number" then
local res = tostring( value )
if string.find( value, "[^%.,%-0-9]" ) ~= nil then
res = "function() return 0/0 end"
end
return res
elseif t == "boolean" then
if value then return "true" end
return "false"
elseif t == "string" then
return string.format( "%q", value )
elseif t == "table" then
local res = "{ "
for k, v in pairs( value ) do
res = res.."["..serialize( k ).."] = "..serialize( v )..", "
end
res = res.." }"
return res
else
error( "Can't serialize a value of type "..t )
end
end
local function fixUp( value )
local t = type( value )
if t == "table" then
local res = {}
for k, v in pairs( value ) do
res[fixUp(k)] = fixUp(v)
end
return res
elseif t == "function" then
return value()
else
return value
end
end
function deserialize( str )
local f = loadstring( "return "..str )
if f then
local res = f()
return fixUp( res )
else
error( "Unable to parse serialized value: "..tostring(str) )
end
end
function bind( address, port )
local self = { listener = socket.bind( address, port ) }
setmetatable( self, listenerMeta )
return self
end
function listenerMeta.__index:accept()
local res = self.listener:accept()
if res ~= nil then
res = { connection = res }
setmetatable( res, connectionMeta )
res:init_()
end
return res
end
function connect( address, port )
local self = { connection = socket.connect( address, port ) }
print( "Connected to "..address..":"..port )
setmetatable( self, connectionMeta )
self:init_()
return self
end
function connectionMeta.__index:init_()
self.received_ = {}
end
function connectionMeta.__index:getpeername()
return self.connection:getpeername()
end
function connectionMeta.__index:send( data, channel )
channel = channel or "default"
debugPrint( "Sending "..tostring( data ).." on channel "..channel )
local sdata = serialize( data )
local packet = channel.."\n"..(#sdata).."\n"..sdata
local res, msg = self.connection:send( packet )
if res == nil then
error( msg, 0 )
else
return res
end
end
function connectionMeta.__index:waitData()
local needResumeHook = false
if globals.grldc.suspendHook ~= nil then
-- the grldc module is loaded, we need to avoid the debug hook to be called from the receive function (because the hook internally uses receive too)
globals.grldc.suspendHook()
needResumeHook = true
end
local hasData = false
for _, received in pairs( self.received_ ) do
if #received > 0 then
hasData = true
break
end
end
if hasData then
if needResumeHook then globals.grldc.resumeHook() end
return
end
debugPrint( "updating channels..." )
self:updateChannels_( nil )
if needResumeHook then globals.grldc.resumeHook() end
end
function connectionMeta.__index:receive( channel )
channel = channel or "default"
debugPrint( "Blocking receive on channel "..channel )
local data = self:popReceived_( channel )
while data == nil do
self:updateChannels_( nil )
data = self:popReceived_( channel )
end
debugPrint( "received "..tostring(data).." on channel "..channel )
return data
end
function connectionMeta.__index:tryReceive( channel )
channel = channel or "default"
local data = self:popReceived_( channel )
if data == nil then
self:updateChannels_( 0 )
data = self:popReceived_( channel )
end
if data ~= nil then
debugPrint( "received "..tostring(data).." on channel "..channel )
end
return data
end
function connectionMeta.__index:updateChannels_( timeout )
local needResumeHook = false
if globals.grldc.suspendHook ~= nil then
-- the grldc module is loaded, we need to avoid the debug hook to be called from the receive function (because the hook internally uses receive too)
globals.grldc.suspendHook()
needResumeHook = true
end
self.connection:settimeout( timeout )
local channel, msg = self.connection:receive()
self.connection:settimeout( nil )
if channel == nil and msg == "timeout" then
if needResumeHook then globals.grldc.resumeHook() end
return
end
local size
if channel ~= nil then
debugPrint( "receiving..." )
size, msg = self.connection:receive()
end
local data
if size ~= nil then
size = assert( tonumber( size ) )
data, msg = self.connection:receive( size )
end
if data == nil then
if needResumeHook then globals.grldc.resumeHook() end
error( msg, 0 )
end
if channel == "ka" then
-- special channel keepalive, we simply ignore data received on this channel
else
local received = self.received_[channel]
if received == nil then
received = {}
self.received_[channel] = received
end
table.insert( received, deserialize( data ) )
debugPrint( "queued "..tostring(data).." on channel "..channel )
end
if needResumeHook then globals.grldc.resumeHook() end
end
function connectionMeta.__index:popReceived_( channel )
local received = self.received_[channel]
if received == nil then return nil end
local res = received[1]
if res == nil then return nil end
table.remove( received, 1 )
return res
end

85
shared/grldc/socket.lua

@ -0,0 +1,85 @@
-- see copyright notice in grldc.h
-- This module follows approximately the same interface as the lua socket module, but implements only the subset needed by GRLD for easier port on platforms that lua socket does not support
local socket = require( "socket" )
local setmetatable = setmetatable
local ipairs = ipairs
local table = table
local assert = assert
local print = print
local error = error
local type = type
module( "grldc.socket" )
local listenerMeta = { __index = {} }
local connectionMeta = { __index = {} }
function sleep( time )
socket.sleep( time )
end
-- Wait until one of the sockets in the recvt list is receiving data, or the timeout has expired (if timeout is nil, wait forever)
function select( recvt, timeout )
local sockets = {}
for _, s in ipairs( recvt ) do
table.insert( sockets, s )
end
socket.select( sockets, nil, timeout )
end
-- Start listening for connections. See listener:accept
function bind( address, port )
local listener = assert( socket.bind( address, port ) )
listener:settimeout( 0 )
local self = { listener_ = listener }
setmetatable( self, listenerMeta )
return self
end
-- Connects to a listening server. Throws an error with message "connection refused" if the connection is refused by the server.
function connect( address, port )
print( "Connecting to "..address..":"..port.."..." )
local con, msg = socket.connect( address, port )
if not con and msg == "connection refused" then error( msg, 0 ) end
assert( con, msg )
con:setoption( "tcp-nodelay", true )
local res = { connection = con }
setmetatable( res, connectionMeta )
return res
end
-- If a client is connecting, returns a connection with it, otherwise returns nil (no waiting)
function listenerMeta.__index:accept()
local con, msg = self.listener_:accept()
if con == nil and msg ~= "timeout" then
error( msg )
end
if con == nil then return nil end
con:setoption( "tcp-nodelay", true )
--con:setoption( "keepalive", true )
local res = { connection = con }
setmetatable( res, connectionMeta )
return res
end
function connectionMeta.__index:getpeername()
return self.connection:getpeername()
end
function connectionMeta.__index:send( data )
return self.connection:send( data )
end
-- Receives a string until first "\n" character if what is nil, or the specified number of bytes if what is a number. The result is returned as a string. If the connection is closed, throws an error "closed"
function connectionMeta.__index:receive( what )
assert( what == nil or type( what ) == "number" )
return self.connection:receive( what )
end
-- Sets the timeout for the next receive operations
function connectionMeta.__index:settimeout( timeout )
self.connection:settimeout( timeout )
end

70
shared/grldc/utilities.lua

@ -0,0 +1,70 @@
-- see copyright notice in grldc.h
local string = string
local assert = assert
local print = print
module( "grldc.utilities" )
function normalizePath( path, base )
--print( "Normalizing "..path )
assert( string.sub( path, 1, 1 ) ~= "@" )
local n
path = string.gsub(path, "\\", "/")
path = string.lower( path )
--make sure the drive letter, if any, is upper case
if string.find(path, "^.:/") == 1 then
path = string.upper(string.sub(path, 1, 1))..string.sub(path, 2)
elseif string.sub( path, 1, 1 ) == "/" then
-- absolute linux-style path, nothing to do
elseif string.sub( path, 1, 2 ) == "./" then
-- explicit relative path, nothing to do
else
path = "./"..path
end
if string.sub( path, 1, 2 ) == "./" and base ~= nil then
-- if the lfs module is available, we convert relative path to absolute
path = base..string.sub( path, 2 )
path = string.gsub(path, "\\", "/")
end
--add end "/" if needed (simplifies pattern matchings below)
if string.sub(path, -1) ~= "/" then
path = path.."/"
end
--replace "//" by "/"
n = 1
while n > 0 do
path, n = string.gsub(path, "//", "/", 1)
end
--replace "/./" by "/"
n = 1
while n > 0 do
path, n = string.gsub(path, "/%./", "/", 1)
end
--replace "/something/../" by "/"
n = 1
while n > 0 do
n = 0
local s = 0, e
local something = ".."
while something == ".." do
s, e, something = string.find( path, "/([^/]*)/%.%./", s+1 )
end
if s ~= nil then
n = 1
path = string.sub( path, 1, s-1 ).."/"..string.sub( path, e+1 )
end
end
path = string.sub( path, 1, -2 ) -- remove end "/"
--print( path )
return path
end
Loading…
Cancel
Save