@ -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 |
@ -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] |
@ -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>. |
@ -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. |
@ -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. |
||||
|
||||
|
@ -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 |
@ -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 |
||||
|
||||
|
@ -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 |
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
@ -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 |
@ -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" |
||||
} |
@ -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 |
||||
|
@ -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 |
@ -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 |
@ -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" ) |
@ -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
|
||||
} |
@ -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_
|
@ -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 |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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 |
@ -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 |
@ -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 |
@ -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> |
@ -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> |
@ -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 |
@ -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> |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 124 KiB |
@ -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 |
@ -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" ) |
@ -0,0 +1,2 @@
|
||||
cd %~dp0 |
||||
..\bin\win_x86\lua5.1\lua51.exe wxLdb\wxLdb.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 |
@ -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é Carregal. The implementation is not derived from licensed software.</p> |
||||
|
||||
<p> |
||||
<!-- ===================================================================== --> |
||||
</p> |
||||
|
||||
<hr /> |
||||
<p>Copyright © 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> |
@ -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 |
||||
------------------------------------------------------------------------------- |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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() |
@ -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 |
@ -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 |
@ -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 |
@ -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 |