Initial import
commit 1 GPLv3 commit commit commit commit commit commit
This commit is contained in:
commit
6fb0158d39
|
@ -0,0 +1,8 @@
|
||||||
|
build/
|
||||||
|
.kdev4/
|
||||||
|
*.user
|
||||||
|
*-swp
|
||||||
|
*.kdev4
|
||||||
|
FreeKill
|
||||||
|
FreeKill.exe
|
||||||
|
freekill-wrap.cxx
|
|
@ -0,0 +1,28 @@
|
||||||
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
|
project(FreeKill VERSION 0.0.1)
|
||||||
|
|
||||||
|
find_package(Qt5 REQUIRED COMPONENTS
|
||||||
|
Gui
|
||||||
|
Qml
|
||||||
|
Network
|
||||||
|
Multimedia
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Lua)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
set(REQUIRED_QT_VERSION "5.15.2")
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/)
|
||||||
|
include_directories(include/lua)
|
||||||
|
include_directories(src)
|
||||||
|
include_directories(src/client)
|
||||||
|
include_directories(src/core)
|
||||||
|
include_directories(src/network)
|
||||||
|
include_directories(src/server)
|
||||||
|
include_directories(src/ui)
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
|
@ -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,49 @@
|
||||||
|
/*
|
||||||
|
** $Id: lapi.h $
|
||||||
|
** Auxiliary functions from Lua API
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lapi_h
|
||||||
|
#define lapi_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "llimits.h"
|
||||||
|
#include "lstate.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Increments 'L->top', checking for stack overflows */
|
||||||
|
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||||
|
"stack overflow");}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If a call returns too many multiple returns, the callee may not have
|
||||||
|
** stack space to accommodate all results. In this case, this macro
|
||||||
|
** increases its stack space ('L->ci->top').
|
||||||
|
*/
|
||||||
|
#define adjustresults(L,nres) \
|
||||||
|
{ if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Ensure the stack has at least 'n' elements */
|
||||||
|
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||||
|
"not enough elements in the stack")
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** To reduce the overhead of returning from C functions, the presence of
|
||||||
|
** to-be-closed variables in these functions is coded in the CallInfo's
|
||||||
|
** field 'nresults', in a way that functions with no to-be-closed variables
|
||||||
|
** with zero, one, or "all" wanted results have no overhead. Functions
|
||||||
|
** with other number of wanted results, as well as functions with
|
||||||
|
** variables to be closed, have an extra check.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define hastocloseCfunc(n) ((n) < LUA_MULTRET)
|
||||||
|
|
||||||
|
/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */
|
||||||
|
#define codeNresults(n) (-(n) - 3)
|
||||||
|
#define decodeNresults(n) (-(n) - 3)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
** $Id: lauxlib.h $
|
||||||
|
** 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 "luaconf.h"
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* global table */
|
||||||
|
#define LUA_GNAME "_G"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct luaL_Buffer luaL_Buffer;
|
||||||
|
|
||||||
|
|
||||||
|
/* extra error code for 'luaL_loadfilex' */
|
||||||
|
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||||
|
|
||||||
|
|
||||||
|
/* key, in the registry, for table of loaded modules */
|
||||||
|
#define LUA_LOADED_TABLE "_LOADED"
|
||||||
|
|
||||||
|
|
||||||
|
/* key, in the registry, for table of preloaded loaders */
|
||||||
|
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct luaL_Reg {
|
||||||
|
const char *name;
|
||||||
|
lua_CFunction func;
|
||||||
|
} luaL_Reg;
|
||||||
|
|
||||||
|
|
||||||
|
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
|
||||||
|
|
||||||
|
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
|
||||||
|
#define luaL_checkversion(L) \
|
||||||
|
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
|
||||||
|
|
||||||
|
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 arg, const char *extramsg);
|
||||||
|
LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
|
||||||
|
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
|
||||||
|
size_t *l);
|
||||||
|
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
|
||||||
|
const char *def, size_t *l);
|
||||||
|
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
|
||||||
|
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
|
||||||
|
|
||||||
|
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
|
||||||
|
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
|
||||||
|
lua_Integer def);
|
||||||
|
|
||||||
|
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||||
|
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
|
||||||
|
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
|
||||||
|
|
||||||
|
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 arg, 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);
|
||||||
|
|
||||||
|
|
||||||
|
/* predefined 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 lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||||
|
|
||||||
|
LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
|
||||||
|
const char *p, const char *r);
|
||||||
|
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_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||||
|
|
||||||
|
#define luaL_argcheck(L, cond,arg,extramsg) \
|
||||||
|
((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
|
||||||
|
|
||||||
|
#define luaL_argexpected(L,cond,arg,tname) \
|
||||||
|
((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname))))
|
||||||
|
|
||||||
|
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||||
|
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Perform arithmetic operations on lua_Integer values with wrap-around
|
||||||
|
** semantics, as the Lua core does.
|
||||||
|
*/
|
||||||
|
#define luaL_intop(op,v1,v2) \
|
||||||
|
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
|
||||||
|
|
||||||
|
|
||||||
|
/* push the value used to represent failure/error */
|
||||||
|
#define luaL_pushfail(L) lua_pushnil(L)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Internal assertions for in-house debugging
|
||||||
|
*/
|
||||||
|
#if !defined(lua_assert)
|
||||||
|
|
||||||
|
#if defined LUAI_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#define lua_assert(c) assert(c)
|
||||||
|
#else
|
||||||
|
#define lua_assert(c) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {======================================================
|
||||||
|
** Generic Buffer manipulation
|
||||||
|
** =======================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct luaL_Buffer {
|
||||||
|
char *b; /* buffer address */
|
||||||
|
size_t size; /* buffer size */
|
||||||
|
size_t n; /* number of characters in buffer */
|
||||||
|
lua_State *L;
|
||||||
|
union {
|
||||||
|
LUAI_MAXALIGN; /* ensure maximum alignment for buffer */
|
||||||
|
char b[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||||
|
} init;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define luaL_bufflen(bf) ((bf)->n)
|
||||||
|
#define luaL_buffaddr(bf) ((bf)->b)
|
||||||
|
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#define luaL_buffsub(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;
|
||||||
|
|
||||||
|
/* }====================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** "Abstraction Layer" for basic report of messages and errors
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* print a string */
|
||||||
|
#if !defined(lua_writestring)
|
||||||
|
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* print a newline and flush the output */
|
||||||
|
#if !defined(lua_writeline)
|
||||||
|
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* print an error message */
|
||||||
|
#if !defined(lua_writestringerror)
|
||||||
|
#define lua_writestringerror(s,p) \
|
||||||
|
(fprintf(stderr, (s), (p)), fflush(stderr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {============================================================
|
||||||
|
** Compatibility with deprecated conversions
|
||||||
|
** =============================================================
|
||||||
|
*/
|
||||||
|
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||||
|
|
||||||
|
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||||
|
#define luaL_optunsigned(L,a,d) \
|
||||||
|
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||||
|
|
||||||
|
#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)))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* }============================================================ */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
** $Id: lcode.h $
|
||||||
|
** Code generator for Lua
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lcode_h
|
||||||
|
#define lcode_h
|
||||||
|
|
||||||
|
#include "llex.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lopcodes.h"
|
||||||
|
#include "lparser.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Marks the end of a patch list. It is an invalid value both as an absolute
|
||||||
|
** address, and as a list link (would link an element to itself).
|
||||||
|
*/
|
||||||
|
#define NO_JUMP (-1)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** grep "ORDER OPR" if you change these enums (ORDER OP)
|
||||||
|
*/
|
||||||
|
typedef enum BinOpr {
|
||||||
|
/* arithmetic operators */
|
||||||
|
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
|
||||||
|
OPR_DIV, OPR_IDIV,
|
||||||
|
/* bitwise operators */
|
||||||
|
OPR_BAND, OPR_BOR, OPR_BXOR,
|
||||||
|
OPR_SHL, OPR_SHR,
|
||||||
|
/* string operator */
|
||||||
|
OPR_CONCAT,
|
||||||
|
/* comparison operators */
|
||||||
|
OPR_EQ, OPR_LT, OPR_LE,
|
||||||
|
OPR_NE, OPR_GT, OPR_GE,
|
||||||
|
/* logical operators */
|
||||||
|
OPR_AND, OPR_OR,
|
||||||
|
OPR_NOBINOPR
|
||||||
|
} BinOpr;
|
||||||
|
|
||||||
|
|
||||||
|
/* true if operation is foldable (that is, it is arithmetic or bitwise) */
|
||||||
|
#define foldbinop(op) ((op) <= OPR_SHR)
|
||||||
|
|
||||||
|
|
||||||
|
#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0)
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||||
|
|
||||||
|
|
||||||
|
/* get (pointer to) instruction of given 'expdesc' */
|
||||||
|
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
|
||||||
|
|
||||||
|
|
||||||
|
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
|
||||||
|
|
||||||
|
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
|
||||||
|
|
||||||
|
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
|
||||||
|
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||||
|
LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
|
||||||
|
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
|
||||||
|
int B, int C, int k);
|
||||||
|
LUAI_FUNC int luaK_isKint (expdesc *e);
|
||||||
|
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
|
||||||
|
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
||||||
|
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
||||||
|
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
|
||||||
|
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
|
||||||
|
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
|
||||||
|
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
||||||
|
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
||||||
|
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||||
|
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||||
|
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||||
|
LUAI_FUNC int luaK_jump (FuncState *fs);
|
||||||
|
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
|
||||||
|
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
||||||
|
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
||||||
|
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||||
|
LUAI_FUNC int luaK_getlabel (FuncState *fs);
|
||||||
|
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
|
||||||
|
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
|
||||||
|
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
|
||||||
|
expdesc *v2, int line);
|
||||||
|
LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc,
|
||||||
|
int ra, int asize, int hsize);
|
||||||
|
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
|
||||||
|
LUAI_FUNC void luaK_finish (FuncState *fs);
|
||||||
|
LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
** $Id: lctype.h $
|
||||||
|
** 'ctype' functions for Lua
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lctype_h
|
||||||
|
#define lctype_h
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** WARNING: the functions defined here do not necessarily correspond
|
||||||
|
** to the similar functions in the standard C ctype.h. They are
|
||||||
|
** optimized for the specific needs of Lua.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(LUA_USE_CTYPE)
|
||||||
|
|
||||||
|
#if 'A' == 65 && '0' == 48
|
||||||
|
/* ASCII case: can use its own tables; faster and fixed */
|
||||||
|
#define LUA_USE_CTYPE 0
|
||||||
|
#else
|
||||||
|
/* must use standard C ctype */
|
||||||
|
#define LUA_USE_CTYPE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !LUA_USE_CTYPE /* { */
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "llimits.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ALPHABIT 0
|
||||||
|
#define DIGITBIT 1
|
||||||
|
#define PRINTBIT 2
|
||||||
|
#define SPACEBIT 3
|
||||||
|
#define XDIGITBIT 4
|
||||||
|
|
||||||
|
|
||||||
|
#define MASK(B) (1 << (B))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** add 1 to char to allow index -1 (EOZ)
|
||||||
|
*/
|
||||||
|
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
|
||||||
|
*/
|
||||||
|
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
|
||||||
|
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
|
||||||
|
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
|
||||||
|
#define lisspace(c) testprop(c, MASK(SPACEBIT))
|
||||||
|
#define lisprint(c) testprop(c, MASK(PRINTBIT))
|
||||||
|
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** In ASCII, this 'ltolower' is correct for alphabetic characters and
|
||||||
|
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
|
||||||
|
** the character either is an upper-case letter or is unchanged by
|
||||||
|
** the transformation, which holds for lower-case letters and '.'.)
|
||||||
|
*/
|
||||||
|
#define ltolower(c) \
|
||||||
|
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \
|
||||||
|
(c) | ('A' ^ 'a'))
|
||||||
|
|
||||||
|
|
||||||
|
/* one entry for each character and for -1 (EOZ) */
|
||||||
|
LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
|
||||||
|
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** use standard C ctypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define lislalpha(c) (isalpha(c) || (c) == '_')
|
||||||
|
#define lislalnum(c) (isalnum(c) || (c) == '_')
|
||||||
|
#define lisdigit(c) (isdigit(c))
|
||||||
|
#define lisspace(c) (isspace(c))
|
||||||
|
#define lisprint(c) (isprint(c))
|
||||||
|
#define lisxdigit(c) (isxdigit(c))
|
||||||
|
|
||||||
|
#define ltolower(c) (tolower(c))
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
** $Id: ldebug.h $
|
||||||
|
** Auxiliary functions from Debug Interface module
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ldebug_h
|
||||||
|
#define ldebug_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "lstate.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
|
||||||
|
|
||||||
|
|
||||||
|
/* Active Lua function (given call info) */
|
||||||
|
#define ci_func(ci) (clLvalue(s2v((ci)->func)))
|
||||||
|
|
||||||
|
|
||||||
|
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** mark for entries in 'lineinfo' array that has absolute information in
|
||||||
|
** 'abslineinfo' array
|
||||||
|
*/
|
||||||
|
#define ABSLINEINFO (-0x80)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** MAXimum number of successive Instructions WiTHout ABSolute line
|
||||||
|
** information. (A power of two allows fast divisions.)
|
||||||
|
*/
|
||||||
|
#if !defined(MAXIWTHABS)
|
||||||
|
#define MAXIWTHABS 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
|
||||||
|
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
|
||||||
|
StkId *pos);
|
||||||
|
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
||||||
|
const char *opname);
|
||||||
|
LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o);
|
||||||
|
LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
|
||||||
|
const char *what);
|
||||||
|
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2);
|
||||||
|
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2,
|
||||||
|
const char *msg);
|
||||||
|
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2);
|
||||||
|
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2);
|
||||||
|
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||||
|
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
||||||
|
TString *src, int line);
|
||||||
|
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||||
|
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
** $Id: ldo.h $
|
||||||
|
** Stack and Call structure of Lua
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ldo_h
|
||||||
|
#define ldo_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lstate.h"
|
||||||
|
#include "lzio.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Macro to check stack size and grow stack if needed. Parameters
|
||||||
|
** 'pre'/'pos' allow the macro to preserve a pointer into the
|
||||||
|
** stack across reallocations, doing the work only when needed.
|
||||||
|
** It also allows the running of one GC step when the stack is
|
||||||
|
** reallocated.
|
||||||
|
** 'condmovestack' is used in heavy tests to force a stack reallocation
|
||||||
|
** at every check.
|
||||||
|
*/
|
||||||
|
#define luaD_checkstackaux(L,n,pre,pos) \
|
||||||
|
if (l_unlikely(L->stack_last - L->top <= (n))) \
|
||||||
|
{ pre; luaD_growstack(L, n, 1); pos; } \
|
||||||
|
else { condmovestack(L,pre,pos); }
|
||||||
|
|
||||||
|
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
||||||
|
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
|
||||||
|
#define restorestack(L,n) ((StkId)((char *)L->stack + (n)))
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to check stack size, preserving 'p' */
|
||||||
|
#define checkstackGCp(L,n,p) \
|
||||||
|
luaD_checkstackaux(L, n, \
|
||||||
|
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||||
|
luaC_checkGC(L), /* stack grow uses memory */ \
|
||||||
|
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to check stack size and GC */
|
||||||
|
#define checkstackGC(L,fsize) \
|
||||||
|
luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
|
||||||
|
|
||||||
|
|
||||||
|
/* type of protected functions, to be ran by 'runprotected' */
|
||||||
|
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||||
|
|
||||||
|
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
|
||||||
|
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
|
const char *mode);
|
||||||
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
|
int fTransfer, int nTransfer);
|
||||||
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
|
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta);
|
||||||
|
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
|
LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
|
||||||
|
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
|
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||||
|
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
|
||||||
|
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
|
||||||
|
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
|
||||||
|
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||||
|
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||||
|
|
||||||
|
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
|
||||||
|
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
** $Id: lfunc.h $
|
||||||
|
** Auxiliary functions to manipulate prototypes and closures
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lfunc_h
|
||||||
|
#define lfunc_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "lobject.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \
|
||||||
|
cast_int(sizeof(TValue)) * (n))
|
||||||
|
|
||||||
|
#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \
|
||||||
|
cast_int(sizeof(TValue *)) * (n))
|
||||||
|
|
||||||
|
|
||||||
|
/* test whether thread is in 'twups' list */
|
||||||
|
#define isintwups(L) (L->twups != L)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** maximum number of upvalues in a closure (both C and Lua). (Value
|
||||||
|
** must fit in a VM register.)
|
||||||
|
*/
|
||||||
|
#define MAXUPVAL 255
|
||||||
|
|
||||||
|
|
||||||
|
#define upisopen(up) ((up)->v != &(up)->u.value)
|
||||||
|
|
||||||
|
|
||||||
|
#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** maximum number of misses before giving up the cache of closures
|
||||||
|
** in prototypes
|
||||||
|
*/
|
||||||
|
#define MAXMISS 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* special status to close upvalues preserving the top of the stack */
|
||||||
|
#define CLOSEKTOP (-1)
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
|
||||||
|
LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals);
|
||||||
|
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals);
|
||||||
|
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
|
||||||
|
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
|
||||||
|
LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
|
||||||
|
LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level);
|
||||||
|
LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy);
|
||||||
|
LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
|
||||||
|
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
|
||||||
|
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
|
||||||
|
int pc);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
** $Id: lgc.h $
|
||||||
|
** Garbage Collector
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lgc_h
|
||||||
|
#define lgc_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lstate.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Collectable objects may have one of three colors: white, which means
|
||||||
|
** the object is not marked; gray, which means the object is marked, but
|
||||||
|
** its references may be not marked; and black, which means that the
|
||||||
|
** object and all its references are marked. The main invariant of the
|
||||||
|
** garbage collector, while marking objects, is that a black object can
|
||||||
|
** never point to a white one. Moreover, any gray object must be in a
|
||||||
|
** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it
|
||||||
|
** can be visited again before finishing the collection cycle. (Open
|
||||||
|
** upvalues are an exception to this rule.) These lists have no meaning
|
||||||
|
** when the invariant is not being enforced (e.g., sweep phase).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Possible states of the Garbage Collector
|
||||||
|
*/
|
||||||
|
#define GCSpropagate 0
|
||||||
|
#define GCSenteratomic 1
|
||||||
|
#define GCSatomic 2
|
||||||
|
#define GCSswpallgc 3
|
||||||
|
#define GCSswpfinobj 4
|
||||||
|
#define GCSswptobefnz 5
|
||||||
|
#define GCSswpend 6
|
||||||
|
#define GCScallfin 7
|
||||||
|
#define GCSpause 8
|
||||||
|
|
||||||
|
|
||||||
|
#define issweepphase(g) \
|
||||||
|
(GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro to tell when main invariant (white objects cannot point to black
|
||||||
|
** ones) must be kept. During a collection, the sweep
|
||||||
|
** phase may break the invariant, as objects turned white may point to
|
||||||
|
** still-black objects. The invariant is restored when sweep ends and
|
||||||
|
** all objects are white again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** some useful bit tricks
|
||||||
|
*/
|
||||||
|
#define resetbits(x,m) ((x) &= cast_byte(~(m)))
|
||||||
|
#define setbits(x,m) ((x) |= (m))
|
||||||
|
#define testbits(x,m) ((x) & (m))
|
||||||
|
#define bitmask(b) (1<<(b))
|
||||||
|
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
|
||||||
|
#define l_setbit(x,b) setbits(x, bitmask(b))
|
||||||
|
#define resetbit(x,b) resetbits(x, bitmask(b))
|
||||||
|
#define testbit(x,b) testbits(x, bitmask(b))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Layout for bit use in 'marked' field. First three bits are
|
||||||
|
** used for object "age" in generational mode. Last bit is used
|
||||||
|
** by tests.
|
||||||
|
*/
|
||||||
|
#define WHITE0BIT 3 /* object is white (type 0) */
|
||||||
|
#define WHITE1BIT 4 /* object is white (type 1) */
|
||||||
|
#define BLACKBIT 5 /* object is black */
|
||||||
|
#define FINALIZEDBIT 6 /* object has been marked for finalization */
|
||||||
|
|
||||||
|
#define TESTBIT 7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
|
||||||
|
|
||||||
|
|
||||||
|
#define iswhite(x) testbits((x)->marked, WHITEBITS)
|
||||||
|
#define isblack(x) testbit((x)->marked, BLACKBIT)
|
||||||
|
#define isgray(x) /* neither white nor black */ \
|
||||||
|
(!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
|
||||||
|
|
||||||
|
#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT)
|
||||||
|
|
||||||
|
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
|
||||||
|
#define isdeadm(ow,m) ((m) & (ow))
|
||||||
|
#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
|
||||||
|
|
||||||
|
#define changewhite(x) ((x)->marked ^= WHITEBITS)
|
||||||
|
#define nw2black(x) \
|
||||||
|
check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT))
|
||||||
|
|
||||||
|
#define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS)
|
||||||
|
|
||||||
|
|
||||||
|
/* object age in generational mode */
|
||||||
|
#define G_NEW 0 /* created in current cycle */
|
||||||
|
#define G_SURVIVAL 1 /* created in previous cycle */
|
||||||
|
#define G_OLD0 2 /* marked old by frw. barrier in this cycle */
|
||||||
|
#define G_OLD1 3 /* first full cycle as old */
|
||||||
|
#define G_OLD 4 /* really old object (not to be visited) */
|
||||||
|
#define G_TOUCHED1 5 /* old object touched this cycle */
|
||||||
|
#define G_TOUCHED2 6 /* old object touched in previous cycle */
|
||||||
|
|
||||||
|
#define AGEBITS 7 /* all age bits (111) */
|
||||||
|
|
||||||
|
#define getage(o) ((o)->marked & AGEBITS)
|
||||||
|
#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a))
|
||||||
|
#define isold(o) (getage(o) > G_SURVIVAL)
|
||||||
|
|
||||||
|
#define changeage(o,f,t) \
|
||||||
|
check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t)))
|
||||||
|
|
||||||
|
|
||||||
|
/* Default Values for GC parameters */
|
||||||
|
#define LUAI_GENMAJORMUL 100
|
||||||
|
#define LUAI_GENMINORMUL 20
|
||||||
|
|
||||||
|
/* wait memory to double before starting new cycle */
|
||||||
|
#define LUAI_GCPAUSE 200
|
||||||
|
|
||||||
|
/*
|
||||||
|
** some gc parameters are stored divided by 4 to allow a maximum value
|
||||||
|
** up to 1023 in a 'lu_byte'.
|
||||||
|
*/
|
||||||
|
#define getgcparam(p) ((p) * 4)
|
||||||
|
#define setgcparam(p,v) ((p) = (v) / 4)
|
||||||
|
|
||||||
|
#define LUAI_GCMUL 100
|
||||||
|
|
||||||
|
/* how much to allocate before next GC step (log2) */
|
||||||
|
#define LUAI_GCSTEPSIZE 13 /* 8 KB */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether the declared GC mode is generational. While in
|
||||||
|
** generational mode, the collector can go temporarily to incremental
|
||||||
|
** mode to improve performance. This is signaled by 'g->lastatomic != 0'.
|
||||||
|
*/
|
||||||
|
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Control when GC is running:
|
||||||
|
*/
|
||||||
|
#define GCSTPUSR 1 /* bit true when GC stopped by user */
|
||||||
|
#define GCSTPGC 2 /* bit true when GC stopped by itself */
|
||||||
|
#define GCSTPCLS 4 /* bit true when closing Lua state */
|
||||||
|
#define gcrunning(g) ((g)->gcstp == 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Does one step of collection when debt becomes positive. 'pre'/'pos'
|
||||||
|
** allows some adjustments to be done only when needed. macro
|
||||||
|
** 'condchangemem' is used only for heavy tests (forcing a full
|
||||||
|
** GC cycle on every opportunity)
|
||||||
|
*/
|
||||||
|
#define luaC_condGC(L,pre,pos) \
|
||||||
|
{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
|
||||||
|
condchangemem(L,pre,pos); }
|
||||||
|
|
||||||
|
/* more often than not, 'pre'/'pos' are empty */
|
||||||
|
#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
|
||||||
|
|
||||||
|
|
||||||
|
#define luaC_barrier(L,p,v) ( \
|
||||||
|
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
|
||||||
|
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
|
||||||
|
|
||||||
|
#define luaC_barrierback(L,p,v) ( \
|
||||||
|
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
|
||||||
|
luaC_barrierback_(L,p) : cast_void(0))
|
||||||
|
|
||||||
|
#define luaC_objbarrier(L,p,o) ( \
|
||||||
|
(isblack(p) && iswhite(o)) ? \
|
||||||
|
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
|
||||||
|
|
||||||
|
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
|
||||||
|
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
|
||||||
|
LUAI_FUNC void luaC_step (lua_State *L);
|
||||||
|
LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
|
||||||
|
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
|
||||||
|
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
|
||||||
|
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
|
||||||
|
LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
|
||||||
|
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
|
||||||
|
LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
** $Id: ljumptab.h $
|
||||||
|
** Jump Table for the Lua interpreter
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#undef vmdispatch
|
||||||
|
#undef vmcase
|
||||||
|
#undef vmbreak
|
||||||
|
|
||||||
|
#define vmdispatch(x) goto *disptab[x];
|
||||||
|
|
||||||
|
#define vmcase(l) L_##l:
|
||||||
|
|
||||||
|
#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i));
|
||||||
|
|
||||||
|
|
||||||
|
static const void *const disptab[NUM_OPCODES] = {
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
** you can update the following list with this command:
|
||||||
|
**
|
||||||
|
** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h
|
||||||
|
**
|
||||||
|
#endif
|
||||||
|
|
||||||
|
&&L_OP_MOVE,
|
||||||
|
&&L_OP_LOADI,
|
||||||
|
&&L_OP_LOADF,
|
||||||
|
&&L_OP_LOADK,
|
||||||
|
&&L_OP_LOADKX,
|
||||||
|
&&L_OP_LOADFALSE,
|
||||||
|
&&L_OP_LFALSESKIP,
|
||||||
|
&&L_OP_LOADTRUE,
|
||||||
|
&&L_OP_LOADNIL,
|
||||||
|
&&L_OP_GETUPVAL,
|
||||||
|
&&L_OP_SETUPVAL,
|
||||||
|
&&L_OP_GETTABUP,
|
||||||
|
&&L_OP_GETTABLE,
|
||||||
|
&&L_OP_GETI,
|
||||||
|
&&L_OP_GETFIELD,
|
||||||
|
&&L_OP_SETTABUP,
|
||||||
|
&&L_OP_SETTABLE,
|
||||||
|
&&L_OP_SETI,
|
||||||
|
&&L_OP_SETFIELD,
|
||||||
|
&&L_OP_NEWTABLE,
|
||||||
|
&&L_OP_SELF,
|
||||||
|
&&L_OP_ADDI,
|
||||||
|
&&L_OP_ADDK,
|
||||||
|
&&L_OP_SUBK,
|
||||||
|
&&L_OP_MULK,
|
||||||
|
&&L_OP_MODK,
|
||||||
|
&&L_OP_POWK,
|
||||||
|
&&L_OP_DIVK,
|
||||||
|
&&L_OP_IDIVK,
|
||||||
|
&&L_OP_BANDK,
|
||||||
|
&&L_OP_BORK,
|
||||||
|
&&L_OP_BXORK,
|
||||||
|
&&L_OP_SHRI,
|
||||||
|
&&L_OP_SHLI,
|
||||||
|
&&L_OP_ADD,
|
||||||
|
&&L_OP_SUB,
|
||||||
|
&&L_OP_MUL,
|
||||||
|
&&L_OP_MOD,
|
||||||
|
&&L_OP_POW,
|
||||||
|
&&L_OP_DIV,
|
||||||
|
&&L_OP_IDIV,
|
||||||
|
&&L_OP_BAND,
|
||||||
|
&&L_OP_BOR,
|
||||||
|
&&L_OP_BXOR,
|
||||||
|
&&L_OP_SHL,
|
||||||
|
&&L_OP_SHR,
|
||||||
|
&&L_OP_MMBIN,
|
||||||
|
&&L_OP_MMBINI,
|
||||||
|
&&L_OP_MMBINK,
|
||||||
|
&&L_OP_UNM,
|
||||||
|
&&L_OP_BNOT,
|
||||||
|
&&L_OP_NOT,
|
||||||
|
&&L_OP_LEN,
|
||||||
|
&&L_OP_CONCAT,
|
||||||
|
&&L_OP_CLOSE,
|
||||||
|
&&L_OP_TBC,
|
||||||
|
&&L_OP_JMP,
|
||||||
|
&&L_OP_EQ,
|
||||||
|
&&L_OP_LT,
|
||||||
|
&&L_OP_LE,
|
||||||
|
&&L_OP_EQK,
|
||||||
|
&&L_OP_EQI,
|
||||||
|
&&L_OP_LTI,
|
||||||
|
&&L_OP_LEI,
|
||||||
|
&&L_OP_GTI,
|
||||||
|
&&L_OP_GEI,
|
||||||
|
&&L_OP_TEST,
|
||||||
|
&&L_OP_TESTSET,
|
||||||
|
&&L_OP_CALL,
|
||||||
|
&&L_OP_TAILCALL,
|
||||||
|
&&L_OP_RETURN,
|
||||||
|
&&L_OP_RETURN0,
|
||||||
|
&&L_OP_RETURN1,
|
||||||
|
&&L_OP_FORLOOP,
|
||||||
|
&&L_OP_FORPREP,
|
||||||
|
&&L_OP_TFORPREP,
|
||||||
|
&&L_OP_TFORCALL,
|
||||||
|
&&L_OP_TFORLOOP,
|
||||||
|
&&L_OP_SETLIST,
|
||||||
|
&&L_OP_CLOSURE,
|
||||||
|
&&L_OP_VARARG,
|
||||||
|
&&L_OP_VARARGPREP,
|
||||||
|
&&L_OP_EXTRAARG
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
** $Id: llex.h $
|
||||||
|
** Lexical Analyzer
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef llex_h
|
||||||
|
#define llex_h
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lzio.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Single-char tokens (terminal symbols) are represented by their own
|
||||||
|
** numeric code. Other tokens start at the following value.
|
||||||
|
*/
|
||||||
|
#define FIRST_RESERVED (UCHAR_MAX + 1)
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(LUA_ENV)
|
||||||
|
#define LUA_ENV "_ENV"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING: if you change the order of this enumeration,
|
||||||
|
* grep "ORDER RESERVED"
|
||||||
|
*/
|
||||||
|
enum RESERVED {
|
||||||
|
/* terminal symbols denoted by reserved words */
|
||||||
|
TK_AND = FIRST_RESERVED, TK_BREAK,
|
||||||
|
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
||||||
|
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||||
|
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
||||||
|
/* other terminal symbols */
|
||||||
|
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
|
||||||
|
TK_SHL, TK_SHR,
|
||||||
|
TK_DBCOLON, TK_EOS,
|
||||||
|
TK_FLT, TK_INT, TK_NAME, TK_STRING
|
||||||
|
};
|
||||||
|
|
||||||
|
/* number of reserved words */
|
||||||
|
#define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1))
|
||||||
|
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
lua_Number r;
|
||||||
|
lua_Integer i;
|
||||||
|
TString *ts;
|
||||||
|
} SemInfo; /* semantics information */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct Token {
|
||||||
|
int token;
|
||||||
|
SemInfo seminfo;
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
|
||||||
|
/* state of the lexer plus state of the parser when shared by all
|
||||||
|
functions */
|
||||||
|
typedef struct LexState {
|
||||||
|
int current; /* current character (charint) */
|
||||||
|
int linenumber; /* input line counter */
|
||||||
|
int lastline; /* line of last token 'consumed' */
|
||||||
|
Token t; /* current token */
|
||||||
|
Token lookahead; /* look ahead token */
|
||||||
|
struct FuncState *fs; /* current function (parser) */
|
||||||
|
struct lua_State *L;
|
||||||
|
ZIO *z; /* input stream */
|
||||||
|
Mbuffer *buff; /* buffer for tokens */
|
||||||
|
Table *h; /* to avoid collection/reuse strings */
|
||||||
|
struct Dyndata *dyd; /* dynamic structures used by the parser */
|
||||||
|
TString *source; /* current source name */
|
||||||
|
TString *envn; /* environment variable name */
|
||||||
|
} LexState;
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC void luaX_init (lua_State *L);
|
||||||
|
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
|
||||||
|
TString *source, int firstchar);
|
||||||
|
LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
|
||||||
|
LUAI_FUNC void luaX_next (LexState *ls);
|
||||||
|
LUAI_FUNC int luaX_lookahead (LexState *ls);
|
||||||
|
LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
|
||||||
|
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
** $Id: llimits.h $
|
||||||
|
** 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"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count
|
||||||
|
** the total memory used by Lua (in bytes). Usually, 'size_t' and
|
||||||
|
** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
|
||||||
|
*/
|
||||||
|
#if defined(LUAI_MEM) /* { external definitions? */
|
||||||
|
typedef LUAI_UMEM lu_mem;
|
||||||
|
typedef LUAI_MEM l_mem;
|
||||||
|
#elif LUAI_IS32INT /* }{ */
|
||||||
|
typedef size_t lu_mem;
|
||||||
|
typedef ptrdiff_t l_mem;
|
||||||
|
#else /* 16-bit ints */ /* }{ */
|
||||||
|
typedef unsigned long lu_mem;
|
||||||
|
typedef long l_mem;
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
/* chars used as small naturals (so that 'char' is reserved for characters) */
|
||||||
|
typedef unsigned char lu_byte;
|
||||||
|
typedef signed char ls_byte;
|
||||||
|
|
||||||
|
|
||||||
|
/* maximum value for size_t */
|
||||||
|
#define MAX_SIZET ((size_t)(~(size_t)0))
|
||||||
|
|
||||||
|
/* maximum size visible for Lua (must be representable in a lua_Integer) */
|
||||||
|
#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
|
||||||
|
: (size_t)(LUA_MAXINTEGER))
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_LUMEM ((lu_mem)(~(lu_mem)0))
|
||||||
|
|
||||||
|
#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1))
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_INT INT_MAX /* maximum value of an int */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** floor of the log2 of the maximum signed value for integral type 't'.
|
||||||
|
** (That is, maximum 'n' such that '2^n' fits in the given signed type.)
|
||||||
|
*/
|
||||||
|
#define log2maxs(t) (sizeof(t) * 8 - 2)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** test whether an unsigned value is a power of 2 (or zero)
|
||||||
|
*/
|
||||||
|
#define ispow2(x) (((x) & ((x) - 1)) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
/* number of chars of a literal string without the ending \0 */
|
||||||
|
#define LL(x) (sizeof(x)/sizeof(char) - 1)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** conversion of pointer to unsigned integer:
|
||||||
|
** this is for hashing only; there is no problem if the integer
|
||||||
|
** cannot hold the whole pointer value
|
||||||
|
*/
|
||||||
|
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* types of 'usual argument conversions' for lua_Number and lua_Integer */
|
||||||
|
typedef LUAI_UACNUMBER l_uacNumber;
|
||||||
|
typedef LUAI_UACINT l_uacInt;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Internal assertions for in-house debugging
|
||||||
|
*/
|
||||||
|
#if defined LUAI_ASSERT
|
||||||
|
#undef NDEBUG
|
||||||
|
#include <assert.h>
|
||||||
|
#define lua_assert(c) assert(c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(lua_assert)
|
||||||
|
#define check_exp(c,e) (lua_assert(c), (e))
|
||||||
|
/* to avoid problems with conditions too long */
|
||||||
|
#define lua_longassert(c) ((c) ? (void)0 : 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)
|
||||||
|
#define luai_apicheck(l,e) ((void)l, lua_assert(e))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to avoid warnings about unused variables */
|
||||||
|
#if !defined(UNUSED)
|
||||||
|
#define UNUSED(x) ((void)(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* type casts (a macro highlights casts in the code) */
|
||||||
|
#define cast(t, exp) ((t)(exp))
|
||||||
|
|
||||||
|
#define cast_void(i) cast(void, (i))
|
||||||
|
#define cast_voidp(i) cast(void *, (i))
|
||||||
|
#define cast_num(i) cast(lua_Number, (i))
|
||||||
|
#define cast_int(i) cast(int, (i))
|
||||||
|
#define cast_uint(i) cast(unsigned int, (i))
|
||||||
|
#define cast_byte(i) cast(lu_byte, (i))
|
||||||
|
#define cast_uchar(i) cast(unsigned char, (i))
|
||||||
|
#define cast_char(i) cast(char, (i))
|
||||||
|
#define cast_charp(i) cast(char *, (i))
|
||||||
|
#define cast_sizet(i) cast(size_t, (i))
|
||||||
|
|
||||||
|
|
||||||
|
/* cast a signed lua_Integer to lua_Unsigned */
|
||||||
|
#if !defined(l_castS2U)
|
||||||
|
#define l_castS2U(i) ((lua_Unsigned)(i))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** cast a lua_Unsigned to a signed lua_Integer; this cast is
|
||||||
|
** not strict ISO C, but two-complement architectures should
|
||||||
|
** work fine.
|
||||||
|
*/
|
||||||
|
#if !defined(l_castU2S)
|
||||||
|
#define l_castU2S(i) ((lua_Integer)(i))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** non-return type
|
||||||
|
*/
|
||||||
|
#if !defined(l_noret)
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define l_noret void __attribute__((noreturn))
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||||
|
#define l_noret void __declspec(noreturn)
|
||||||
|
#else
|
||||||
|
#define l_noret void
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Inline functions
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
#define l_inline inline
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define l_inline __inline__
|
||||||
|
#else
|
||||||
|
#define l_inline /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define l_sinline static l_inline
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** type for virtual-machine instructions;
|
||||||
|
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
|
||||||
|
*/
|
||||||
|
#if LUAI_IS32INT
|
||||||
|
typedef unsigned int l_uint32;
|
||||||
|
#else
|
||||||
|
typedef unsigned long l_uint32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef l_uint32 Instruction;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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.)
|
||||||
|
*/
|
||||||
|
#if !defined(LUAI_MAXSHORTLEN)
|
||||||
|
#define LUAI_MAXSHORTLEN 40
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Initial size for the string table (must be power of 2).
|
||||||
|
** The Lua core alone registers ~50 strings (reserved words +
|
||||||
|
** metaevent keys + a few others). Libraries would typically add
|
||||||
|
** a few dozens more.
|
||||||
|
*/
|
||||||
|
#if !defined(MINSTRTABSIZE)
|
||||||
|
#define MINSTRTABSIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Size of cache for strings in the API. 'N' is the number of
|
||||||
|
** sets (better be a prime) and "M" is the size of each set (M == 1
|
||||||
|
** makes a direct cache.)
|
||||||
|
*/
|
||||||
|
#if !defined(STRCACHE_N)
|
||||||
|
#define STRCACHE_N 53
|
||||||
|
#define STRCACHE_M 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* minimum size for string buffer */
|
||||||
|
#if !defined(LUA_MINBUFFER)
|
||||||
|
#define LUA_MINBUFFER 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Maximum depth for nested C calls, syntactical nested non-terminals,
|
||||||
|
** and other features implemented through recursion in C. (Value must
|
||||||
|
** fit in a 16-bit unsigned integer. It must also be compatible with
|
||||||
|
** the size of the C stack.)
|
||||||
|
*/
|
||||||
|
#if !defined(LUAI_MAXCCALLS)
|
||||||
|
#define LUAI_MAXCCALLS 200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macros that are executed whenever program enters the Lua core
|
||||||
|
** ('lua_lock') and leaves the core ('lua_unlock')
|
||||||
|
*/
|
||||||
|
#if !defined(lua_lock)
|
||||||
|
#define lua_lock(L) ((void) 0)
|
||||||
|
#define lua_unlock(L) ((void) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro executed during Lua functions at points where the
|
||||||
|
** function can yield.
|
||||||
|
*/
|
||||||
|
#if !defined(luai_threadyield)
|
||||||
|
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these macros allow user-specific actions 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The luai_num* macros define the primitive operations over numbers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* floor division (defined as 'floor(a/b)') */
|
||||||
|
#if !defined(luai_numidiv)
|
||||||
|
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* float division */
|
||||||
|
#if !defined(luai_numdiv)
|
||||||
|
#define luai_numdiv(L,a,b) ((a)/(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** modulo: defined as 'a - floor(a/b)*b'; the direct computation
|
||||||
|
** using this definition has several problems with rounding errors,
|
||||||
|
** so it is better to use 'fmod'. 'fmod' gives the result of
|
||||||
|
** 'a - trunc(a/b)*b', and therefore must be corrected when
|
||||||
|
** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
|
||||||
|
** non-integer negative result: non-integer result is equivalent to
|
||||||
|
** a non-zero remainder 'm'; negative result is equivalent to 'a' and
|
||||||
|
** 'b' with different signs, or 'm' and 'b' with different signs
|
||||||
|
** (as the result 'm' of 'fmod' has the same sign of 'a').
|
||||||
|
*/
|
||||||
|
#if !defined(luai_nummod)
|
||||||
|
#define luai_nummod(L,a,b,m) \
|
||||||
|
{ (void)L; (m) = l_mathop(fmod)(a,b); \
|
||||||
|
if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* exponentiation */
|
||||||
|
#if !defined(luai_numpow)
|
||||||
|
#define luai_numpow(L,a,b) \
|
||||||
|
((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the others are quite standard operations */
|
||||||
|
#if !defined(luai_numadd)
|
||||||
|
#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_numunm(L,a) (-(a))
|
||||||
|
#define luai_numeq(a,b) ((a)==(b))
|
||||||
|
#define luai_numlt(a,b) ((a)<(b))
|
||||||
|
#define luai_numle(a,b) ((a)<=(b))
|
||||||
|
#define luai_numgt(a,b) ((a)>(b))
|
||||||
|
#define luai_numge(a,b) ((a)>=(b))
|
||||||
|
#define luai_numisnan(a) (!luai_numeq((a), (a)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro to control inclusion of some hard tests on stack reallocation
|
||||||
|
*/
|
||||||
|
#if !defined(HARDSTACKTESTS)
|
||||||
|
#define condmovestack(L,pre,pos) ((void)0)
|
||||||
|
#else
|
||||||
|
/* realloc stack keeping its size */
|
||||||
|
#define condmovestack(L,pre,pos) \
|
||||||
|
{ int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HARDMEMTESTS)
|
||||||
|
#define condchangemem(L,pre,pos) ((void)0)
|
||||||
|
#else
|
||||||
|
#define condchangemem(L,pre,pos) \
|
||||||
|
{ if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
** $Id: lmem.h $
|
||||||
|
** 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"
|
||||||
|
|
||||||
|
|
||||||
|
#define luaM_error(L) luaD_throw(L, LUA_ERRMEM)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This macro tests whether it is safe to multiply 'n' by the size of
|
||||||
|
** type 't' without overflows. Because 'e' is always constant, it avoids
|
||||||
|
** the runtime division MAX_SIZET/(e).
|
||||||
|
** (The macro is somewhat complex to avoid warnings: The 'sizeof'
|
||||||
|
** comparison avoids a runtime comparison when overflow cannot occur.
|
||||||
|
** The compiler should be able to optimize the real test by itself, but
|
||||||
|
** when it does it, it may give a warning about "comparison is always
|
||||||
|
** false due to limited range of data type"; the +1 tricks the compiler,
|
||||||
|
** avoiding this warning but also this optimization.)
|
||||||
|
*/
|
||||||
|
#define luaM_testsize(n,e) \
|
||||||
|
(sizeof(n) >= sizeof(size_t) && cast_sizet((n)) + 1 > MAX_SIZET/(e))
|
||||||
|
|
||||||
|
#define luaM_checksize(L,n,e) \
|
||||||
|
(luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that
|
||||||
|
** the result is not larger than 'n' and cannot overflow a 'size_t'
|
||||||
|
** when multiplied by the size of type 't'. (Assumes that 'n' is an
|
||||||
|
** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.)
|
||||||
|
*/
|
||||||
|
#define luaM_limitN(n,t) \
|
||||||
|
((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \
|
||||||
|
cast_uint((MAX_SIZET/sizeof(t))))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Arrays of chars do not need any test
|
||||||
|
*/
|
||||||
|
#define luaM_reallocvchar(L,b,on,n) \
|
||||||
|
cast_charp(luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
|
||||||
|
|
||||||
|
#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s))
|
||||||
|
#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b)))
|
||||||
|
#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b)))
|
||||||
|
|
||||||
|
#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0))
|
||||||
|
#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0))
|
||||||
|
#define luaM_newvectorchecked(L,n,t) \
|
||||||
|
(luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t))
|
||||||
|
|
||||||
|
#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag)
|
||||||
|
|
||||||
|
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
|
||||||
|
((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \
|
||||||
|
luaM_limitN(limit,t),e)))
|
||||||
|
|
||||||
|
#define luaM_reallocvector(L, v,oldn,n,t) \
|
||||||
|
(cast(t *, luaM_realloc_(L, v, cast_sizet(oldn) * sizeof(t), \
|
||||||
|
cast_sizet(n) * sizeof(t))))
|
||||||
|
|
||||||
|
#define luaM_shrinkvector(L,v,size,fs,t) \
|
||||||
|
((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, 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_saferealloc_ (lua_State *L, void *block, size_t oldsize,
|
||||||
|
size_t size);
|
||||||
|
LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize);
|
||||||
|
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems,
|
||||||
|
int *size, int size_elem, int limit,
|
||||||
|
const char *what);
|
||||||
|
LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem,
|
||||||
|
int final_n, int size_elem);
|
||||||
|
LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,800 @@
|
||||||
|
/*
|
||||||
|
** $Id: lobject.h $
|
||||||
|
** 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 types for collectable non-values
|
||||||
|
*/
|
||||||
|
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
|
||||||
|
#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */
|
||||||
|
#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** number of all possible types (including LUA_TNONE but excluding DEADKEY)
|
||||||
|
*/
|
||||||
|
#define LUA_TOTALTYPES (LUA_TPROTO + 2)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** tags for Tagged Values have the following use of bits:
|
||||||
|
** bits 0-3: actual tag (a LUA_T* constant)
|
||||||
|
** bits 4-5: variant bits
|
||||||
|
** bit 6: whether value is collectable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* add variant bits to a type */
|
||||||
|
#define makevariant(t,v) ((t) | ((v) << 4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Union of all Lua values
|
||||||
|
*/
|
||||||
|
typedef union Value {
|
||||||
|
struct GCObject *gc; /* collectable objects */
|
||||||
|
void *p; /* light userdata */
|
||||||
|
lua_CFunction f; /* light C functions */
|
||||||
|
lua_Integer i; /* integer numbers */
|
||||||
|
lua_Number n; /* float numbers */
|
||||||
|
} Value;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Tagged Values. This is the basic representation of values in Lua:
|
||||||
|
** an actual value plus a tag with its type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TValuefields Value value_; lu_byte tt_
|
||||||
|
|
||||||
|
typedef struct TValue {
|
||||||
|
TValuefields;
|
||||||
|
} TValue;
|
||||||
|
|
||||||
|
|
||||||
|
#define val_(o) ((o)->value_)
|
||||||
|
#define valraw(o) (val_(o))
|
||||||
|
|
||||||
|
|
||||||
|
/* raw type tag of a TValue */
|
||||||
|
#define rawtt(o) ((o)->tt_)
|
||||||
|
|
||||||
|
/* tag with no variants (bits 0-3) */
|
||||||
|
#define novariant(t) ((t) & 0x0F)
|
||||||
|
|
||||||
|
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
|
||||||
|
#define withvariant(t) ((t) & 0x3F)
|
||||||
|
#define ttypetag(o) withvariant(rawtt(o))
|
||||||
|
|
||||||
|
/* type of a TValue */
|
||||||
|
#define ttype(o) (novariant(rawtt(o)))
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros to test type */
|
||||||
|
#define checktag(o,t) (rawtt(o) == (t))
|
||||||
|
#define checktype(o,t) (ttype(o) == (t))
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros for internal tests */
|
||||||
|
|
||||||
|
/* collectable object has the same tag as the original value */
|
||||||
|
#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Any value being manipulated by the program either is non
|
||||||
|
** collectable, or the collectable object has the right tag
|
||||||
|
** and it is not dead. The option 'L == NULL' allows other
|
||||||
|
** macros using this one to be used where L is not available.
|
||||||
|
*/
|
||||||
|
#define checkliveness(L,obj) \
|
||||||
|
((void)L, lua_longassert(!iscollectable(obj) || \
|
||||||
|
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))))
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros to set values */
|
||||||
|
|
||||||
|
/* set a value's tag */
|
||||||
|
#define settt_(o,t) ((o)->tt_=(t))
|
||||||
|
|
||||||
|
|
||||||
|
/* main macro to copy values (from 'obj2' to 'obj1') */
|
||||||
|
#define setobj(L,obj1,obj2) \
|
||||||
|
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
||||||
|
io1->value_ = io2->value_; settt_(io1, io2->tt_); \
|
||||||
|
checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Different types of assignments, according to source and destination.
|
||||||
|
** (They are mostly equal now, but may be different in the future.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* from stack to stack */
|
||||||
|
#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2))
|
||||||
|
/* to stack (not from same stack) */
|
||||||
|
#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2)
|
||||||
|
/* from table to same table */
|
||||||
|
#define setobjt2t setobj
|
||||||
|
/* to new object */
|
||||||
|
#define setobj2n setobj
|
||||||
|
/* to table */
|
||||||
|
#define setobj2t setobj
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Entries in a Lua stack. Field 'tbclist' forms a list of all
|
||||||
|
** to-be-closed variables active in this stack. Dummy entries are
|
||||||
|
** used when the distance between two tbc variables does not fit
|
||||||
|
** in an unsigned short. They are represented by delta==0, and
|
||||||
|
** their real delta is always the maximum value that fits in
|
||||||
|
** that field.
|
||||||
|
*/
|
||||||
|
typedef union StackValue {
|
||||||
|
TValue val;
|
||||||
|
struct {
|
||||||
|
TValuefields;
|
||||||
|
unsigned short delta;
|
||||||
|
} tbclist;
|
||||||
|
} StackValue;
|
||||||
|
|
||||||
|
|
||||||
|
/* index to stack elements */
|
||||||
|
typedef StackValue *StkId;
|
||||||
|
|
||||||
|
/* convert a 'StackValue' to a 'TValue' */
|
||||||
|
#define s2v(o) (&(o)->val)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Nil
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard nil */
|
||||||
|
#define LUA_VNIL makevariant(LUA_TNIL, 0)
|
||||||
|
|
||||||
|
/* Empty slot (which might be different from a slot containing nil) */
|
||||||
|
#define LUA_VEMPTY makevariant(LUA_TNIL, 1)
|
||||||
|
|
||||||
|
/* Value returned for a key not found in a table (absent key) */
|
||||||
|
#define LUA_VABSTKEY makevariant(LUA_TNIL, 2)
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to test for (any kind of) nil */
|
||||||
|
#define ttisnil(v) checktype((v), LUA_TNIL)
|
||||||
|
|
||||||
|
|
||||||
|
/* macro to test for a standard nil */
|
||||||
|
#define ttisstrictnil(o) checktag((o), LUA_VNIL)
|
||||||
|
|
||||||
|
|
||||||
|
#define setnilvalue(obj) settt_(obj, LUA_VNIL)
|
||||||
|
|
||||||
|
|
||||||
|
#define isabstkey(v) checktag((v), LUA_VABSTKEY)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro to detect non-standard nils (used only in assertions)
|
||||||
|
*/
|
||||||
|
#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** By default, entries with any kind of nil are considered empty.
|
||||||
|
** (In any definition, values associated with absent keys must also
|
||||||
|
** be accepted as empty.)
|
||||||
|
*/
|
||||||
|
#define isempty(v) ttisnil(v)
|
||||||
|
|
||||||
|
|
||||||
|
/* macro defining a value corresponding to an absent key */
|
||||||
|
#define ABSTKEYCONSTANT {NULL}, LUA_VABSTKEY
|
||||||
|
|
||||||
|
|
||||||
|
/* mark an entry as empty */
|
||||||
|
#define setempty(v) settt_(v, LUA_VEMPTY)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Booleans
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define LUA_VFALSE makevariant(LUA_TBOOLEAN, 0)
|
||||||
|
#define LUA_VTRUE makevariant(LUA_TBOOLEAN, 1)
|
||||||
|
|
||||||
|
#define ttisboolean(o) checktype((o), LUA_TBOOLEAN)
|
||||||
|
#define ttisfalse(o) checktag((o), LUA_VFALSE)
|
||||||
|
#define ttistrue(o) checktag((o), LUA_VTRUE)
|
||||||
|
|
||||||
|
|
||||||
|
#define l_isfalse(o) (ttisfalse(o) || ttisnil(o))
|
||||||
|
|
||||||
|
|
||||||
|
#define setbfvalue(obj) settt_(obj, LUA_VFALSE)
|
||||||
|
#define setbtvalue(obj) settt_(obj, LUA_VTRUE)
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Threads
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LUA_VTHREAD makevariant(LUA_TTHREAD, 0)
|
||||||
|
|
||||||
|
#define ttisthread(o) checktag((o), ctb(LUA_VTHREAD))
|
||||||
|
|
||||||
|
#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
|
||||||
|
|
||||||
|
#define setthvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); lua_State *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTHREAD)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t)
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Collectable Objects
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Common Header for all collectable objects (in macro form, to be
|
||||||
|
** included in other objects)
|
||||||
|
*/
|
||||||
|
#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked
|
||||||
|
|
||||||
|
|
||||||
|
/* Common type for all collectable objects */
|
||||||
|
typedef struct GCObject {
|
||||||
|
CommonHeader;
|
||||||
|
} GCObject;
|
||||||
|
|
||||||
|
|
||||||
|
/* Bit mark for collectable types */
|
||||||
|
#define BIT_ISCOLLECTABLE (1 << 6)
|
||||||
|
|
||||||
|
#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE)
|
||||||
|
|
||||||
|
/* mark a tag as collectable */
|
||||||
|
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
|
||||||
|
|
||||||
|
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
|
||||||
|
|
||||||
|
#define gcvalueraw(v) ((v).gc)
|
||||||
|
|
||||||
|
#define setgcovalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); GCObject *i_g=(x); \
|
||||||
|
val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Numbers
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Variant tags for numbers */
|
||||||
|
#define LUA_VNUMINT makevariant(LUA_TNUMBER, 0) /* integer numbers */
|
||||||
|
#define LUA_VNUMFLT makevariant(LUA_TNUMBER, 1) /* float numbers */
|
||||||
|
|
||||||
|
#define ttisnumber(o) checktype((o), LUA_TNUMBER)
|
||||||
|
#define ttisfloat(o) checktag((o), LUA_VNUMFLT)
|
||||||
|
#define ttisinteger(o) checktag((o), LUA_VNUMINT)
|
||||||
|
|
||||||
|
#define nvalue(o) check_exp(ttisnumber(o), \
|
||||||
|
(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
|
||||||
|
#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
|
||||||
|
#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
|
||||||
|
|
||||||
|
#define fltvalueraw(v) ((v).n)
|
||||||
|
#define ivalueraw(v) ((v).i)
|
||||||
|
|
||||||
|
#define setfltvalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_VNUMFLT); }
|
||||||
|
|
||||||
|
#define chgfltvalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
|
||||||
|
|
||||||
|
#define setivalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_VNUMINT); }
|
||||||
|
|
||||||
|
#define chgivalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Strings
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Variant tags for strings */
|
||||||
|
#define LUA_VSHRSTR makevariant(LUA_TSTRING, 0) /* short strings */
|
||||||
|
#define LUA_VLNGSTR makevariant(LUA_TSTRING, 1) /* long strings */
|
||||||
|
|
||||||
|
#define ttisstring(o) checktype((o), LUA_TSTRING)
|
||||||
|
#define ttisshrstring(o) checktag((o), ctb(LUA_VSHRSTR))
|
||||||
|
#define ttislngstring(o) checktag((o), ctb(LUA_VLNGSTR))
|
||||||
|
|
||||||
|
#define tsvalueraw(v) (gco2ts((v).gc))
|
||||||
|
|
||||||
|
#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
|
||||||
|
|
||||||
|
#define setsvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); TString *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
/* set a string to the stack */
|
||||||
|
#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s)
|
||||||
|
|
||||||
|
/* set a string to a new object */
|
||||||
|
#define setsvalue2n setsvalue
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Header for a string value.
|
||||||
|
*/
|
||||||
|
typedef struct TString {
|
||||||
|
CommonHeader;
|
||||||
|
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
||||||
|
lu_byte shrlen; /* length for short strings */
|
||||||
|
unsigned int hash;
|
||||||
|
union {
|
||||||
|
size_t lnglen; /* length for long strings */
|
||||||
|
struct TString *hnext; /* linked list for hash table */
|
||||||
|
} u;
|
||||||
|
char contents[1];
|
||||||
|
} TString;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Get the actual string (array of bytes) from a 'TString'.
|
||||||
|
*/
|
||||||
|
#define getstr(ts) ((ts)->contents)
|
||||||
|
|
||||||
|
|
||||||
|
/* get the actual string (array of bytes) from a Lua value */
|
||||||
|
#define svalue(o) getstr(tsvalue(o))
|
||||||
|
|
||||||
|
/* get string length from 'TString *s' */
|
||||||
|
#define tsslen(s) ((s)->tt == LUA_VSHRSTR ? (s)->shrlen : (s)->u.lnglen)
|
||||||
|
|
||||||
|
/* get string length from 'TValue *o' */
|
||||||
|
#define vslen(o) tsslen(tsvalue(o))
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Userdata
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Light userdata should be a variant of userdata, but for compatibility
|
||||||
|
** reasons they are also different types.
|
||||||
|
*/
|
||||||
|
#define LUA_VLIGHTUSERDATA makevariant(LUA_TLIGHTUSERDATA, 0)
|
||||||
|
|
||||||
|
#define LUA_VUSERDATA makevariant(LUA_TUSERDATA, 0)
|
||||||
|
|
||||||
|
#define ttislightuserdata(o) checktag((o), LUA_VLIGHTUSERDATA)
|
||||||
|
#define ttisfulluserdata(o) checktag((o), ctb(LUA_VUSERDATA))
|
||||||
|
|
||||||
|
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
|
||||||
|
#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
|
||||||
|
|
||||||
|
#define pvalueraw(v) ((v).p)
|
||||||
|
|
||||||
|
#define setpvalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_VLIGHTUSERDATA); }
|
||||||
|
|
||||||
|
#define setuvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); Udata *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VUSERDATA)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
|
||||||
|
/* Ensures that addresses after this type are always fully aligned. */
|
||||||
|
typedef union UValue {
|
||||||
|
TValue uv;
|
||||||
|
LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */
|
||||||
|
} UValue;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Header for userdata with user values;
|
||||||
|
** memory area follows the end of this structure.
|
||||||
|
*/
|
||||||
|
typedef struct Udata {
|
||||||
|
CommonHeader;
|
||||||
|
unsigned short nuvalue; /* number of user values */
|
||||||
|
size_t len; /* number of bytes */
|
||||||
|
struct Table *metatable;
|
||||||
|
GCObject *gclist;
|
||||||
|
UValue uv[1]; /* user values */
|
||||||
|
} Udata;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Header for userdata with no user values. These userdata do not need
|
||||||
|
** to be gray during GC, and therefore do not need a 'gclist' field.
|
||||||
|
** To simplify, the code always use 'Udata' for both kinds of userdata,
|
||||||
|
** making sure it never accesses 'gclist' on userdata with no user values.
|
||||||
|
** This structure here is used only to compute the correct size for
|
||||||
|
** this representation. (The 'bindata' field in its end ensures correct
|
||||||
|
** alignment for binary data following this header.)
|
||||||
|
*/
|
||||||
|
typedef struct Udata0 {
|
||||||
|
CommonHeader;
|
||||||
|
unsigned short nuvalue; /* number of user values */
|
||||||
|
size_t len; /* number of bytes */
|
||||||
|
struct Table *metatable;
|
||||||
|
union {LUAI_MAXALIGN;} bindata;
|
||||||
|
} Udata0;
|
||||||
|
|
||||||
|
|
||||||
|
/* compute the offset of the memory area of a userdata */
|
||||||
|
#define udatamemoffset(nuv) \
|
||||||
|
((nuv) == 0 ? offsetof(Udata0, bindata) \
|
||||||
|
: offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
|
||||||
|
|
||||||
|
/* get the address of the memory block inside 'Udata' */
|
||||||
|
#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))
|
||||||
|
|
||||||
|
/* compute the size of a userdata */
|
||||||
|
#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb))
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Prototypes
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LUA_VPROTO makevariant(LUA_TPROTO, 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 (register) */
|
||||||
|
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
|
||||||
|
lu_byte kind; /* kind of corresponding variable */
|
||||||
|
} 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;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Associates the absolute line source for a given instruction ('pc').
|
||||||
|
** The array 'lineinfo' gives, for each instruction, the difference in
|
||||||
|
** lines from the previous instruction. When that difference does not
|
||||||
|
** fit into a byte, Lua saves the absolute line for that instruction.
|
||||||
|
** (Lua also saves the absolute line periodically, to speed up the
|
||||||
|
** computation of a line number: we can use binary search in the
|
||||||
|
** absolute-line array, but we must traverse the 'lineinfo' array
|
||||||
|
** linearly to compute a line.)
|
||||||
|
*/
|
||||||
|
typedef struct AbsLineInfo {
|
||||||
|
int pc;
|
||||||
|
int line;
|
||||||
|
} AbsLineInfo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Function Prototypes
|
||||||
|
*/
|
||||||
|
typedef struct Proto {
|
||||||
|
CommonHeader;
|
||||||
|
lu_byte numparams; /* number of fixed (named) parameters */
|
||||||
|
lu_byte is_vararg;
|
||||||
|
lu_byte maxstacksize; /* number of registers needed by this function */
|
||||||
|
int sizeupvalues; /* size of 'upvalues' */
|
||||||
|
int sizek; /* size of 'k' */
|
||||||
|
int sizecode;
|
||||||
|
int sizelineinfo;
|
||||||
|
int sizep; /* size of 'p' */
|
||||||
|
int sizelocvars;
|
||||||
|
int sizeabslineinfo; /* size of 'abslineinfo' */
|
||||||
|
int linedefined; /* debug information */
|
||||||
|
int lastlinedefined; /* debug information */
|
||||||
|
TValue *k; /* constants used by the function */
|
||||||
|
Instruction *code; /* opcodes */
|
||||||
|
struct Proto **p; /* functions defined inside the function */
|
||||||
|
Upvaldesc *upvalues; /* upvalue information */
|
||||||
|
ls_byte *lineinfo; /* information about source lines (debug information) */
|
||||||
|
AbsLineInfo *abslineinfo; /* idem */
|
||||||
|
LocVar *locvars; /* information about local variables (debug information) */
|
||||||
|
TString *source; /* used for debug information */
|
||||||
|
GCObject *gclist;
|
||||||
|
} Proto;
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Functions
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LUA_VUPVAL makevariant(LUA_TUPVAL, 0)
|
||||||
|
|
||||||
|
|
||||||
|
/* Variant tags for functions */
|
||||||
|
#define LUA_VLCL makevariant(LUA_TFUNCTION, 0) /* Lua closure */
|
||||||
|
#define LUA_VLCF makevariant(LUA_TFUNCTION, 1) /* light C function */
|
||||||
|
#define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */
|
||||||
|
|
||||||
|
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
|
||||||
|
#define ttisLclosure(o) checktag((o), ctb(LUA_VLCL))
|
||||||
|
#define ttislcf(o) checktag((o), LUA_VLCF)
|
||||||
|
#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL))
|
||||||
|
#define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o))
|
||||||
|
|
||||||
|
|
||||||
|
#define isLfunction(o) ttisLclosure(o)
|
||||||
|
|
||||||
|
#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
|
||||||
|
#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
|
||||||
|
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
|
||||||
|
#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
|
||||||
|
|
||||||
|
#define fvalueraw(v) ((v).f)
|
||||||
|
|
||||||
|
#define setclLvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); LClosure *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VLCL)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl)
|
||||||
|
|
||||||
|
#define setfvalue(obj,x) \
|
||||||
|
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_VLCF); }
|
||||||
|
|
||||||
|
#define setclCvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); CClosure *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Upvalues for Lua closures
|
||||||
|
*/
|
||||||
|
typedef struct UpVal {
|
||||||
|
CommonHeader;
|
||||||
|
lu_byte tbc; /* true if it represents a to-be-closed variable */
|
||||||
|
TValue *v; /* points to stack or to its own value */
|
||||||
|
union {
|
||||||
|
struct { /* (when open) */
|
||||||
|
struct UpVal *next; /* linked list */
|
||||||
|
struct UpVal **previous;
|
||||||
|
} open;
|
||||||
|
TValue value; /* the value (when closed) */
|
||||||
|
} u;
|
||||||
|
} UpVal;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#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 getproto(o) (clLvalue(o)->p)
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Tables
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LUA_VTABLE makevariant(LUA_TTABLE, 0)
|
||||||
|
|
||||||
|
#define ttistable(o) checktag((o), ctb(LUA_VTABLE))
|
||||||
|
|
||||||
|
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
|
||||||
|
|
||||||
|
#define sethvalue(L,obj,x) \
|
||||||
|
{ TValue *io = (obj); Table *x_ = (x); \
|
||||||
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTABLE)); \
|
||||||
|
checkliveness(L,io); }
|
||||||
|
|
||||||
|
#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Nodes for Hash tables: A pack of two TValue's (key-value pairs)
|
||||||
|
** plus a 'next' field to link colliding entries. The distribution
|
||||||
|
** of the key's fields ('key_tt' and 'key_val') not forming a proper
|
||||||
|
** 'TValue' allows for a smaller size for 'Node' both in 4-byte
|
||||||
|
** and 8-byte alignments.
|
||||||
|
*/
|
||||||
|
typedef union Node {
|
||||||
|
struct NodeKey {
|
||||||
|
TValuefields; /* fields for value */
|
||||||
|
lu_byte key_tt; /* key type */
|
||||||
|
int next; /* for chaining */
|
||||||
|
Value key_val; /* key value */
|
||||||
|
} u;
|
||||||
|
TValue i_val; /* direct access to node's value as a proper 'TValue' */
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
|
||||||
|
/* copy a value into a key */
|
||||||
|
#define setnodekey(L,node,obj) \
|
||||||
|
{ Node *n_=(node); const TValue *io_=(obj); \
|
||||||
|
n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
|
||||||
|
checkliveness(L,io_); }
|
||||||
|
|
||||||
|
|
||||||
|
/* copy a value from a key */
|
||||||
|
#define getnodekey(L,obj,node) \
|
||||||
|
{ TValue *io_=(obj); const Node *n_=(node); \
|
||||||
|
io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
|
||||||
|
checkliveness(L,io_); }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
|
||||||
|
** real size of 'array'. Otherwise, the real size of 'array' is the
|
||||||
|
** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
|
||||||
|
** is zero); 'alimit' is then used as a hint for #t.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BITRAS (1 << 7)
|
||||||
|
#define isrealasize(t) (!((t)->flags & BITRAS))
|
||||||
|
#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS))
|
||||||
|
#define setnorealasize(t) ((t)->flags |= BITRAS)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct Table {
|
||||||
|
CommonHeader;
|
||||||
|
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||||
|
lu_byte lsizenode; /* log2 of size of 'node' array */
|
||||||
|
unsigned int alimit; /* "limit" of 'array' array */
|
||||||
|
TValue *array; /* array part */
|
||||||
|
Node *node;
|
||||||
|
Node *lastfree; /* any free position is before this position */
|
||||||
|
struct Table *metatable;
|
||||||
|
GCObject *gclist;
|
||||||
|
} Table;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Macros to manipulate keys inserted in nodes
|
||||||
|
*/
|
||||||
|
#define keytt(node) ((node)->u.key_tt)
|
||||||
|
#define keyval(node) ((node)->u.key_val)
|
||||||
|
|
||||||
|
#define keyisnil(node) (keytt(node) == LUA_TNIL)
|
||||||
|
#define keyisinteger(node) (keytt(node) == LUA_VNUMINT)
|
||||||
|
#define keyival(node) (keyval(node).i)
|
||||||
|
#define keyisshrstr(node) (keytt(node) == ctb(LUA_VSHRSTR))
|
||||||
|
#define keystrval(node) (gco2ts(keyval(node).gc))
|
||||||
|
|
||||||
|
#define setnilkey(node) (keytt(node) = LUA_TNIL)
|
||||||
|
|
||||||
|
#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
|
||||||
|
|
||||||
|
#define gckey(n) (keyval(n).gc)
|
||||||
|
#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Dead keys in tables have the tag DEADKEY but keep their original
|
||||||
|
** gcvalue. This distinguishes them from regular keys but allows them to
|
||||||
|
** be found when searched in a special way. ('next' needs that to find
|
||||||
|
** keys removed from a table during a traversal.)
|
||||||
|
*/
|
||||||
|
#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
|
||||||
|
#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** '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))
|
||||||
|
|
||||||
|
|
||||||
|
/* size of buffer for 'luaO_utf8esc' function */
|
||||||
|
#define UTF8BUFFSZ 8
|
||||||
|
|
||||||
|
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
|
||||||
|
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
|
||||||
|
LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
|
||||||
|
const TValue *p2, TValue *res);
|
||||||
|
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
|
||||||
|
const TValue *p2, StkId res);
|
||||||
|
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
|
||||||
|
LUAI_FUNC int luaO_hexavalue (int c);
|
||||||
|
LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
|
||||||
|
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 srclen);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
/*
|
||||||
|
** $Id: lopcodes.h $
|
||||||
|
** Opcodes for Lua virtual machine
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lopcodes_h
|
||||||
|
#define lopcodes_h
|
||||||
|
|
||||||
|
#include "llimits.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
We assume that instructions are unsigned 32-bit integers.
|
||||||
|
All instructions have an opcode in the first 7 bits.
|
||||||
|
Instructions can have the following formats:
|
||||||
|
|
||||||
|
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
|
||||||
|
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
iABC C(8) | B(8) |k| A(8) | Op(7) |
|
||||||
|
iABx Bx(17) | A(8) | Op(7) |
|
||||||
|
iAsBx sBx (signed)(17) | A(8) | Op(7) |
|
||||||
|
iAx Ax(25) | Op(7) |
|
||||||
|
isJ sJ(25) | Op(7) |
|
||||||
|
|
||||||
|
A signed argument is represented in excess K: the represented value is
|
||||||
|
the written unsigned value minus K, where K is half the maximum for the
|
||||||
|
corresponding unsigned argument.
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** size and position of opcode arguments.
|
||||||
|
*/
|
||||||
|
#define SIZE_C 8
|
||||||
|
#define SIZE_B 8
|
||||||
|
#define SIZE_Bx (SIZE_C + SIZE_B + 1)
|
||||||
|
#define SIZE_A 8
|
||||||
|
#define SIZE_Ax (SIZE_Bx + SIZE_A)
|
||||||
|
#define SIZE_sJ (SIZE_Bx + SIZE_A)
|
||||||
|
|
||||||
|
#define SIZE_OP 7
|
||||||
|
|
||||||
|
#define POS_OP 0
|
||||||
|
|
||||||
|
#define POS_A (POS_OP + SIZE_OP)
|
||||||
|
#define POS_k (POS_A + SIZE_A)
|
||||||
|
#define POS_B (POS_k + 1)
|
||||||
|
#define POS_C (POS_B + SIZE_B)
|
||||||
|
|
||||||
|
#define POS_Bx POS_k
|
||||||
|
|
||||||
|
#define POS_Ax POS_A
|
||||||
|
|
||||||
|
#define POS_sJ POS_A
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** limits for opcode arguments.
|
||||||
|
** we use (signed) 'int' to manipulate most arguments,
|
||||||
|
** so they must fit in ints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check whether type 'int' has at least 'b' bits ('b' < 32) */
|
||||||
|
#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1)
|
||||||
|
|
||||||
|
|
||||||
|
#if L_INTHASBITS(SIZE_Bx)
|
||||||
|
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
|
||||||
|
#else
|
||||||
|
#define MAXARG_Bx MAX_INT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OFFSET_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
|
||||||
|
|
||||||
|
|
||||||
|
#if L_INTHASBITS(SIZE_Ax)
|
||||||
|
#define MAXARG_Ax ((1<<SIZE_Ax)-1)
|
||||||
|
#else
|
||||||
|
#define MAXARG_Ax MAX_INT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if L_INTHASBITS(SIZE_sJ)
|
||||||
|
#define MAXARG_sJ ((1 << SIZE_sJ) - 1)
|
||||||
|
#else
|
||||||
|
#define MAXARG_sJ MAX_INT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OFFSET_sJ (MAXARG_sJ >> 1)
|
||||||
|
|
||||||
|
|
||||||
|
#define MAXARG_A ((1<<SIZE_A)-1)
|
||||||
|
#define MAXARG_B ((1<<SIZE_B)-1)
|
||||||
|
#define MAXARG_C ((1<<SIZE_C)-1)
|
||||||
|
#define OFFSET_sC (MAXARG_C >> 1)
|
||||||
|
|
||||||
|
#define int2sC(i) ((i) + OFFSET_sC)
|
||||||
|
#define sC2int(i) ((i) - OFFSET_sC)
|
||||||
|
|
||||||
|
|
||||||
|
/* creates a mask with 'n' 1 bits at position 'p' */
|
||||||
|
#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p))
|
||||||
|
|
||||||
|
/* creates a mask with 'n' 0 bits at position 'p' */
|
||||||
|
#define MASK0(n,p) (~MASK1(n,p))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** the following macros help to manipulate instructions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
|
||||||
|
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
|
||||||
|
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
|
||||||
|
|
||||||
|
#define checkopm(i,m) (getOpMode(GET_OPCODE(i)) == m)
|
||||||
|
|
||||||
|
|
||||||
|
#define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0)))
|
||||||
|
#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
|
||||||
|
((cast(Instruction, v)<<pos)&MASK1(size,pos))))
|
||||||
|
|
||||||
|
#define GETARG_A(i) getarg(i, POS_A, SIZE_A)
|
||||||
|
#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
|
||||||
|
|
||||||
|
#define GETARG_B(i) check_exp(checkopm(i, iABC), getarg(i, POS_B, SIZE_B))
|
||||||
|
#define GETARG_sB(i) sC2int(GETARG_B(i))
|
||||||
|
#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
|
||||||
|
|
||||||
|
#define GETARG_C(i) check_exp(checkopm(i, iABC), getarg(i, POS_C, SIZE_C))
|
||||||
|
#define GETARG_sC(i) sC2int(GETARG_C(i))
|
||||||
|
#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
|
||||||
|
|
||||||
|
#define TESTARG_k(i) check_exp(checkopm(i, iABC), (cast_int(((i) & (1u << POS_k)))))
|
||||||
|
#define GETARG_k(i) check_exp(checkopm(i, iABC), getarg(i, POS_k, 1))
|
||||||
|
#define SETARG_k(i,v) setarg(i, v, POS_k, 1)
|
||||||
|
|
||||||
|
#define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx))
|
||||||
|
#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
|
||||||
|
|
||||||
|
#define GETARG_Ax(i) check_exp(checkopm(i, iAx), getarg(i, POS_Ax, SIZE_Ax))
|
||||||
|
#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
|
||||||
|
|
||||||
|
#define GETARG_sBx(i) \
|
||||||
|
check_exp(checkopm(i, iAsBx), getarg(i, POS_Bx, SIZE_Bx) - OFFSET_sBx)
|
||||||
|
#define SETARG_sBx(i,b) SETARG_Bx((i),cast_uint((b)+OFFSET_sBx))
|
||||||
|
|
||||||
|
#define GETARG_sJ(i) \
|
||||||
|
check_exp(checkopm(i, isJ), getarg(i, POS_sJ, SIZE_sJ) - OFFSET_sJ)
|
||||||
|
#define SETARG_sJ(i,j) \
|
||||||
|
setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ)
|
||||||
|
|
||||||
|
|
||||||
|
#define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \
|
||||||
|
| (cast(Instruction, a)<<POS_A) \
|
||||||
|
| (cast(Instruction, b)<<POS_B) \
|
||||||
|
| (cast(Instruction, c)<<POS_C) \
|
||||||
|
| (cast(Instruction, k)<<POS_k))
|
||||||
|
|
||||||
|
#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
|
||||||
|
| (cast(Instruction, a)<<POS_A) \
|
||||||
|
| (cast(Instruction, bc)<<POS_Bx))
|
||||||
|
|
||||||
|
#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \
|
||||||
|
| (cast(Instruction, a)<<POS_Ax))
|
||||||
|
|
||||||
|
#define CREATE_sJ(o,j,k) ((cast(Instruction, o) << POS_OP) \
|
||||||
|
| (cast(Instruction, j) << POS_sJ) \
|
||||||
|
| (cast(Instruction, k) << POS_k))
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(MAXINDEXRK) /* (for debugging only) */
|
||||||
|
#define MAXINDEXRK MAXARG_B
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** invalid register that fits in 8 bits
|
||||||
|
*/
|
||||||
|
#define NO_REG MAXARG_A
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** R[x] - register
|
||||||
|
** K[x] - constant (in constant table)
|
||||||
|
** RK(x) == if k(i) then K[x] else R[x]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*)
|
||||||
|
** has extra descriptions in the notes after the enumeration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
name args description
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
OP_MOVE,/* A B R[A] := R[B] */
|
||||||
|
OP_LOADI,/* A sBx R[A] := sBx */
|
||||||
|
OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */
|
||||||
|
OP_LOADK,/* A Bx R[A] := K[Bx] */
|
||||||
|
OP_LOADKX,/* A R[A] := K[extra arg] */
|
||||||
|
OP_LOADFALSE,/* A R[A] := false */
|
||||||
|
OP_LFALSESKIP,/*A R[A] := false; pc++ (*) */
|
||||||
|
OP_LOADTRUE,/* A R[A] := true */
|
||||||
|
OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
|
||||||
|
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
|
||||||
|
OP_SETUPVAL,/* A B UpValue[B] := R[A] */
|
||||||
|
|
||||||
|
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:string] */
|
||||||
|
OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */
|
||||||
|
OP_GETI,/* A B C R[A] := R[B][C] */
|
||||||
|
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:string] */
|
||||||
|
|
||||||
|
OP_SETTABUP,/* A B C UpValue[A][K[B]:string] := RK(C) */
|
||||||
|
OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */
|
||||||
|
OP_SETI,/* A B C R[A][B] := RK(C) */
|
||||||
|
OP_SETFIELD,/* A B C R[A][K[B]:string] := RK(C) */
|
||||||
|
|
||||||
|
OP_NEWTABLE,/* A B C k R[A] := {} */
|
||||||
|
|
||||||
|
OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][RK(C):string] */
|
||||||
|
|
||||||
|
OP_ADDI,/* A B sC R[A] := R[B] + sC */
|
||||||
|
|
||||||
|
OP_ADDK,/* A B C R[A] := R[B] + K[C]:number */
|
||||||
|
OP_SUBK,/* A B C R[A] := R[B] - K[C]:number */
|
||||||
|
OP_MULK,/* A B C R[A] := R[B] * K[C]:number */
|
||||||
|
OP_MODK,/* A B C R[A] := R[B] % K[C]:number */
|
||||||
|
OP_POWK,/* A B C R[A] := R[B] ^ K[C]:number */
|
||||||
|
OP_DIVK,/* A B C R[A] := R[B] / K[C]:number */
|
||||||
|
OP_IDIVK,/* A B C R[A] := R[B] // K[C]:number */
|
||||||
|
|
||||||
|
OP_BANDK,/* A B C R[A] := R[B] & K[C]:integer */
|
||||||
|
OP_BORK,/* A B C R[A] := R[B] | K[C]:integer */
|
||||||
|
OP_BXORK,/* A B C R[A] := R[B] ~ K[C]:integer */
|
||||||
|
|
||||||
|
OP_SHRI,/* A B sC R[A] := R[B] >> sC */
|
||||||
|
OP_SHLI,/* A B sC R[A] := sC << R[B] */
|
||||||
|
|
||||||
|
OP_ADD,/* A B C R[A] := R[B] + R[C] */
|
||||||
|
OP_SUB,/* A B C R[A] := R[B] - R[C] */
|
||||||
|
OP_MUL,/* A B C R[A] := R[B] * R[C] */
|
||||||
|
OP_MOD,/* A B C R[A] := R[B] % R[C] */
|
||||||
|
OP_POW,/* A B C R[A] := R[B] ^ R[C] */
|
||||||
|
OP_DIV,/* A B C R[A] := R[B] / R[C] */
|
||||||
|
OP_IDIV,/* A B C R[A] := R[B] // R[C] */
|
||||||
|
|
||||||
|
OP_BAND,/* A B C R[A] := R[B] & R[C] */
|
||||||
|
OP_BOR,/* A B C R[A] := R[B] | R[C] */
|
||||||
|
OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */
|
||||||
|
OP_SHL,/* A B C R[A] := R[B] << R[C] */
|
||||||
|
OP_SHR,/* A B C R[A] := R[B] >> R[C] */
|
||||||
|
|
||||||
|
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */
|
||||||
|
OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
|
||||||
|
OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
|
||||||
|
|
||||||
|
OP_UNM,/* A B R[A] := -R[B] */
|
||||||
|
OP_BNOT,/* A B R[A] := ~R[B] */
|
||||||
|
OP_NOT,/* A B R[A] := not R[B] */
|
||||||
|
OP_LEN,/* A B R[A] := #R[B] (length operator) */
|
||||||
|
|
||||||
|
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
|
||||||
|
|
||||||
|
OP_CLOSE,/* A close all upvalues >= R[A] */
|
||||||
|
OP_TBC,/* A mark variable A "to be closed" */
|
||||||
|
OP_JMP,/* sJ pc += sJ */
|
||||||
|
OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */
|
||||||
|
OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */
|
||||||
|
OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */
|
||||||
|
|
||||||
|
OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */
|
||||||
|
OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */
|
||||||
|
OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */
|
||||||
|
OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */
|
||||||
|
OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */
|
||||||
|
OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
|
||||||
|
|
||||||
|
OP_TEST,/* A k if (not R[A] == k) then pc++ */
|
||||||
|
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */
|
||||||
|
|
||||||
|
OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */
|
||||||
|
OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */
|
||||||
|
|
||||||
|
OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */
|
||||||
|
OP_RETURN0,/* return */
|
||||||
|
OP_RETURN1,/* A return R[A] */
|
||||||
|
|
||||||
|
OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */
|
||||||
|
OP_FORPREP,/* A Bx <check values and prepare counters>;
|
||||||
|
if not to run then pc+=Bx+1; */
|
||||||
|
|
||||||
|
OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
|
||||||
|
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
|
||||||
|
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
|
||||||
|
|
||||||
|
OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
|
||||||
|
|
||||||
|
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
||||||
|
|
||||||
|
OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
|
||||||
|
|
||||||
|
OP_VARARGPREP,/*A (adjust vararg parameters) */
|
||||||
|
|
||||||
|
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||||
|
} OpCode;
|
||||||
|
|
||||||
|
|
||||||
|
#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
(*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean
|
||||||
|
value, in a code equivalent to (not cond ? false : true). (It
|
||||||
|
produces false and skips the next instruction producing true.)
|
||||||
|
|
||||||
|
(*) Opcodes OP_MMBIN and variants follow each arithmetic and
|
||||||
|
bitwise opcode. If the operation succeeds, it skips this next
|
||||||
|
opcode. Otherwise, this opcode calls the corresponding metamethod.
|
||||||
|
|
||||||
|
(*) Opcode OP_TESTSET is used in short-circuit expressions that need
|
||||||
|
both to jump and to produce a value, such as (a = b or c).
|
||||||
|
|
||||||
|
(*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
|
||||||
|
'top' is set to last_result+1, so next open instruction (OP_CALL,
|
||||||
|
OP_RETURN*, OP_SETLIST) may use 'top'.
|
||||||
|
|
||||||
|
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
|
||||||
|
set top (like in OP_CALL with C == 0).
|
||||||
|
|
||||||
|
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
|
||||||
|
|
||||||
|
(*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always
|
||||||
|
OP_EXTRAARG.
|
||||||
|
|
||||||
|
(*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then
|
||||||
|
real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the
|
||||||
|
bits of C).
|
||||||
|
|
||||||
|
(*) In OP_NEWTABLE, B is log2 of the hash size (which is always a
|
||||||
|
power of 2) plus 1, or zero for size zero. If not k, the array size
|
||||||
|
is C. Otherwise, the array size is EXTRAARG _ C.
|
||||||
|
|
||||||
|
(*) For comparisons, k specifies what condition the test should accept
|
||||||
|
(true or false).
|
||||||
|
|
||||||
|
(*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped
|
||||||
|
(the constant is the first operand).
|
||||||
|
|
||||||
|
(*) All 'skips' (pc++) assume that next instruction is a jump.
|
||||||
|
|
||||||
|
(*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
|
||||||
|
function builds upvalues, which may need to be closed. C > 0 means
|
||||||
|
the function is vararg, so that its 'func' must be corrected before
|
||||||
|
returning; in this case, (C - 1) is its number of fixed parameters.
|
||||||
|
|
||||||
|
(*) In comparisons with an immediate operand, C signals whether the
|
||||||
|
original operand was a float. (It must be corrected in case of
|
||||||
|
metamethods.)
|
||||||
|
|
||||||
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** masks for instruction properties. The format is:
|
||||||
|
** bits 0-2: op mode
|
||||||
|
** bit 3: instruction set register A
|
||||||
|
** bit 4: operator is a test (next instruction must be a jump)
|
||||||
|
** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0)
|
||||||
|
** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
|
||||||
|
** bit 7: instruction is an MM instruction (call a metamethod)
|
||||||
|
*/
|
||||||
|
|
||||||
|
LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
|
||||||
|
|
||||||
|
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7))
|
||||||
|
#define testAMode(m) (luaP_opmodes[m] & (1 << 3))
|
||||||
|
#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
|
||||||
|
#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
|
||||||
|
#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
|
||||||
|
#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
|
||||||
|
|
||||||
|
/* "out top" (set top for next instruction) */
|
||||||
|
#define isOT(i) \
|
||||||
|
((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \
|
||||||
|
GET_OPCODE(i) == OP_TAILCALL)
|
||||||
|
|
||||||
|
/* "in top" (uses top from previous instruction) */
|
||||||
|
#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
|
||||||
|
|
||||||
|
#define opmode(mm,ot,it,t,a,m) \
|
||||||
|
(((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m))
|
||||||
|
|
||||||
|
|
||||||
|
/* number of list items to accumulate before a SETLIST instruction */
|
||||||
|
#define LFIELDS_PER_FLUSH 50
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
** $Id: lopnames.h $
|
||||||
|
** Opcode names
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(lopnames_h)
|
||||||
|
#define lopnames_h
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* ORDER OP */
|
||||||
|
|
||||||
|
static const char *const opnames[] = {
|
||||||
|
"MOVE",
|
||||||
|
"LOADI",
|
||||||
|
"LOADF",
|
||||||
|
"LOADK",
|
||||||
|
"LOADKX",
|
||||||
|
"LOADFALSE",
|
||||||
|
"LFALSESKIP",
|
||||||
|
"LOADTRUE",
|
||||||
|
"LOADNIL",
|
||||||
|
"GETUPVAL",
|
||||||
|
"SETUPVAL",
|
||||||
|
"GETTABUP",
|
||||||
|
"GETTABLE",
|
||||||
|
"GETI",
|
||||||
|
"GETFIELD",
|
||||||
|
"SETTABUP",
|
||||||
|
"SETTABLE",
|
||||||
|
"SETI",
|
||||||
|
"SETFIELD",
|
||||||
|
"NEWTABLE",
|
||||||
|
"SELF",
|
||||||
|
"ADDI",
|
||||||
|
"ADDK",
|
||||||
|
"SUBK",
|
||||||
|
"MULK",
|
||||||
|
"MODK",
|
||||||
|
"POWK",
|
||||||
|
"DIVK",
|
||||||
|
"IDIVK",
|
||||||
|
"BANDK",
|
||||||
|
"BORK",
|
||||||
|
"BXORK",
|
||||||
|
"SHRI",
|
||||||
|
"SHLI",
|
||||||
|
"ADD",
|
||||||
|
"SUB",
|
||||||
|
"MUL",
|
||||||
|
"MOD",
|
||||||
|
"POW",
|
||||||
|
"DIV",
|
||||||
|
"IDIV",
|
||||||
|
"BAND",
|
||||||
|
"BOR",
|
||||||
|
"BXOR",
|
||||||
|
"SHL",
|
||||||
|
"SHR",
|
||||||
|
"MMBIN",
|
||||||
|
"MMBINI",
|
||||||
|
"MMBINK",
|
||||||
|
"UNM",
|
||||||
|
"BNOT",
|
||||||
|
"NOT",
|
||||||
|
"LEN",
|
||||||
|
"CONCAT",
|
||||||
|
"CLOSE",
|
||||||
|
"TBC",
|
||||||
|
"JMP",
|
||||||
|
"EQ",
|
||||||
|
"LT",
|
||||||
|
"LE",
|
||||||
|
"EQK",
|
||||||
|
"EQI",
|
||||||
|
"LTI",
|
||||||
|
"LEI",
|
||||||
|
"GTI",
|
||||||
|
"GEI",
|
||||||
|
"TEST",
|
||||||
|
"TESTSET",
|
||||||
|
"CALL",
|
||||||
|
"TAILCALL",
|
||||||
|
"RETURN",
|
||||||
|
"RETURN0",
|
||||||
|
"RETURN1",
|
||||||
|
"FORLOOP",
|
||||||
|
"FORPREP",
|
||||||
|
"TFORPREP",
|
||||||
|
"TFORCALL",
|
||||||
|
"TFORLOOP",
|
||||||
|
"SETLIST",
|
||||||
|
"CLOSURE",
|
||||||
|
"VARARG",
|
||||||
|
"VARARGPREP",
|
||||||
|
"EXTRAARG",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
** $Id: lparser.h $
|
||||||
|
** Lua Parser
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lparser_h
|
||||||
|
#define lparser_h
|
||||||
|
|
||||||
|
#include "llimits.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lzio.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Expression and variable descriptor.
|
||||||
|
** Code generation for variables and expressions can be delayed to allow
|
||||||
|
** optimizations; An 'expdesc' structure describes a potentially-delayed
|
||||||
|
** variable/expression. It has a description of its "main" value plus a
|
||||||
|
** list of conditional jumps that can also produce its value (generated
|
||||||
|
** by short-circuit operators 'and'/'or').
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* kinds of variables/expressions */
|
||||||
|
typedef enum {
|
||||||
|
VVOID, /* when 'expdesc' describes the last expression of a list,
|
||||||
|
this kind means an empty list (so, no expression) */
|
||||||
|
VNIL, /* constant nil */
|
||||||
|
VTRUE, /* constant true */
|
||||||
|
VFALSE, /* constant false */
|
||||||
|
VK, /* constant in 'k'; info = index of constant in 'k' */
|
||||||
|
VKFLT, /* floating constant; nval = numerical float value */
|
||||||
|
VKINT, /* integer constant; ival = numerical integer value */
|
||||||
|
VKSTR, /* string constant; strval = TString address;
|
||||||
|
(string is fixed by the lexer) */
|
||||||
|
VNONRELOC, /* expression has its value in a fixed register;
|
||||||
|
info = result register */
|
||||||
|
VLOCAL, /* local variable; var.ridx = register index;
|
||||||
|
var.vidx = relative index in 'actvar.arr' */
|
||||||
|
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
||||||
|
VCONST, /* compile-time <const> variable;
|
||||||
|
info = absolute index in 'actvar.arr' */
|
||||||
|
VINDEXED, /* indexed variable;
|
||||||
|
ind.t = table register;
|
||||||
|
ind.idx = key's R index */
|
||||||
|
VINDEXUP, /* indexed upvalue;
|
||||||
|
ind.t = table upvalue;
|
||||||
|
ind.idx = key's K index */
|
||||||
|
VINDEXI, /* indexed variable with constant integer;
|
||||||
|
ind.t = table register;
|
||||||
|
ind.idx = key's value */
|
||||||
|
VINDEXSTR, /* indexed variable with literal string;
|
||||||
|
ind.t = table register;
|
||||||
|
ind.idx = key's K index */
|
||||||
|
VJMP, /* expression is a test/comparison;
|
||||||
|
info = pc of corresponding jump instruction */
|
||||||
|
VRELOC, /* expression can put result in any register;
|
||||||
|
info = instruction pc */
|
||||||
|
VCALL, /* expression is a function call; info = instruction pc */
|
||||||
|
VVARARG /* vararg expression; info = instruction pc */
|
||||||
|
} expkind;
|
||||||
|
|
||||||
|
|
||||||
|
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
|
||||||
|
#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct expdesc {
|
||||||
|
expkind k;
|
||||||
|
union {
|
||||||
|
lua_Integer ival; /* for VKINT */
|
||||||
|
lua_Number nval; /* for VKFLT */
|
||||||
|
TString *strval; /* for VKSTR */
|
||||||
|
int info; /* for generic use */
|
||||||
|
struct { /* for indexed variables */
|
||||||
|
short idx; /* index (R or "long" K) */
|
||||||
|
lu_byte t; /* table (register or upvalue) */
|
||||||
|
} ind;
|
||||||
|
struct { /* for local variables */
|
||||||
|
lu_byte ridx; /* register holding the variable */
|
||||||
|
unsigned short vidx; /* compiler index (in 'actvar.arr') */
|
||||||
|
} var;
|
||||||
|
} u;
|
||||||
|
int t; /* patch list of 'exit when true' */
|
||||||
|
int f; /* patch list of 'exit when false' */
|
||||||
|
} expdesc;
|
||||||
|
|
||||||
|
|
||||||
|
/* kinds of variables */
|
||||||
|
#define VDKREG 0 /* regular */
|
||||||
|
#define RDKCONST 1 /* constant */
|
||||||
|
#define RDKTOCLOSE 2 /* to-be-closed */
|
||||||
|
#define RDKCTC 3 /* compile-time constant */
|
||||||
|
|
||||||
|
/* description of an active local variable */
|
||||||
|
typedef union Vardesc {
|
||||||
|
struct {
|
||||||
|
TValuefields; /* constant value (if it is a compile-time constant) */
|
||||||
|
lu_byte kind;
|
||||||
|
lu_byte ridx; /* register holding the variable */
|
||||||
|
short pidx; /* index of the variable in the Proto's 'locvars' array */
|
||||||
|
TString *name; /* variable name */
|
||||||
|
} vd;
|
||||||
|
TValue k; /* constant value (if any) */
|
||||||
|
} Vardesc;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* description of pending goto statements and label statements */
|
||||||
|
typedef struct Labeldesc {
|
||||||
|
TString *name; /* label identifier */
|
||||||
|
int pc; /* position in code */
|
||||||
|
int line; /* line where it appeared */
|
||||||
|
lu_byte nactvar; /* number of active variables in that position */
|
||||||
|
lu_byte close; /* goto that escapes upvalues */
|
||||||
|
} Labeldesc;
|
||||||
|
|
||||||
|
|
||||||
|
/* list of labels or gotos */
|
||||||
|
typedef struct Labellist {
|
||||||
|
Labeldesc *arr; /* array */
|
||||||
|
int n; /* number of entries in use */
|
||||||
|
int size; /* array size */
|
||||||
|
} Labellist;
|
||||||
|
|
||||||
|
|
||||||
|
/* dynamic structures used by the parser */
|
||||||
|
typedef struct Dyndata {
|
||||||
|
struct { /* list of all active local variables */
|
||||||
|
Vardesc *arr;
|
||||||
|
int n;
|
||||||
|
int size;
|
||||||
|
} actvar;
|
||||||
|
Labellist gt; /* list of pending gotos */
|
||||||
|
Labellist label; /* list of active labels */
|
||||||
|
} Dyndata;
|
||||||
|
|
||||||
|
|
||||||
|
/* control of blocks */
|
||||||
|
struct BlockCnt; /* defined in lparser.c */
|
||||||
|
|
||||||
|
|
||||||
|
/* state needed to generate code for a given function */
|
||||||
|
typedef struct FuncState {
|
||||||
|
Proto *f; /* current function header */
|
||||||
|
struct FuncState *prev; /* enclosing function */
|
||||||
|
struct LexState *ls; /* lexical state */
|
||||||
|
struct BlockCnt *bl; /* chain of current blocks */
|
||||||
|
int pc; /* next position to code (equivalent to 'ncode') */
|
||||||
|
int lasttarget; /* 'label' of last 'jump label' */
|
||||||
|
int previousline; /* last line that was saved in 'lineinfo' */
|
||||||
|
int nk; /* number of elements in 'k' */
|
||||||
|
int np; /* number of elements in 'p' */
|
||||||
|
int nabslineinfo; /* number of elements in 'abslineinfo' */
|
||||||
|
int firstlocal; /* index of first local var (in Dyndata array) */
|
||||||
|
int firstlabel; /* index of first label (in 'dyd->label->arr') */
|
||||||
|
short ndebugvars; /* number of elements in 'f->locvars' */
|
||||||
|
lu_byte nactvar; /* number of active local variables */
|
||||||
|
lu_byte nups; /* number of upvalues */
|
||||||
|
lu_byte freereg; /* first free register */
|
||||||
|
lu_byte iwthabs; /* instructions issued since last absolute line info */
|
||||||
|
lu_byte needclose; /* function needs to close upvalues when returning */
|
||||||
|
} FuncState;
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC int luaY_nvarstack (FuncState *fs);
|
||||||
|
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
||||||
|
Dyndata *dyd, const char *name, int firstchar);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
** $Id: lprefix.h $
|
||||||
|
** Definitions for Lua code that must come before any other header file
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lprefix_h
|
||||||
|
#define lprefix_h
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allows POSIX/XSI stuff
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89) /* { */
|
||||||
|
|
||||||
|
#if !defined(_XOPEN_SOURCE)
|
||||||
|
#define _XOPEN_SOURCE 600
|
||||||
|
#elif _XOPEN_SOURCE == 0
|
||||||
|
#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allows manipulation of large files in gcc and some other compilers
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
|
||||||
|
#define _LARGEFILE_SOURCE 1
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Windows stuff
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) /* { */
|
||||||
|
|
||||||
|
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,404 @@
|
||||||
|
/*
|
||||||
|
** $Id: lstate.h $
|
||||||
|
** 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, so all objects always
|
||||||
|
** belong to one (and only one) of these lists, using field 'next' of
|
||||||
|
** the 'CommonHeader' for the link:
|
||||||
|
**
|
||||||
|
** 'allgc': all objects not marked for finalization;
|
||||||
|
** 'finobj': all objects marked for finalization;
|
||||||
|
** 'tobefnz': all objects ready to be finalized;
|
||||||
|
** 'fixedgc': all objects that are not to be collected (currently
|
||||||
|
** only small strings, such as reserved words).
|
||||||
|
**
|
||||||
|
** For the generational collector, some of these lists have marks for
|
||||||
|
** generations. Each mark points to the first element in the list for
|
||||||
|
** that particular generation; that generation goes until the next mark.
|
||||||
|
**
|
||||||
|
** 'allgc' -> 'survival': new objects;
|
||||||
|
** 'survival' -> 'old': objects that survived one collection;
|
||||||
|
** 'old1' -> 'reallyold': objects that became old in last collection;
|
||||||
|
** 'reallyold' -> NULL: objects old for more than one cycle.
|
||||||
|
**
|
||||||
|
** 'finobj' -> 'finobjsur': new objects marked for finalization;
|
||||||
|
** 'finobjsur' -> 'finobjold1': survived """";
|
||||||
|
** 'finobjold1' -> 'finobjrold': just old """";
|
||||||
|
** 'finobjrold' -> NULL: really old """".
|
||||||
|
**
|
||||||
|
** All lists can contain elements older than their main ages, due
|
||||||
|
** to 'luaC_checkfinalizer' and 'udata2finalize', which move
|
||||||
|
** objects between the normal lists and the "marked for finalization"
|
||||||
|
** lists. Moreover, barriers can age young objects in young lists as
|
||||||
|
** OLD0, which then become OLD1. However, a list never contains
|
||||||
|
** elements younger than their main ages.
|
||||||
|
**
|
||||||
|
** The generational collector also uses a pointer 'firstold1', which
|
||||||
|
** points to the first OLD1 object in the list. It is used to optimize
|
||||||
|
** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc'
|
||||||
|
** and 'reallyold', but often the list has no OLD1 objects or they are
|
||||||
|
** after 'old1'.) Note the difference between it and 'old1':
|
||||||
|
** 'firstold1': no OLD1 objects before this point; there can be all
|
||||||
|
** ages after it.
|
||||||
|
** 'old1': no objects younger than OLD1 after this point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Moreover, there is another set of lists that control gray objects.
|
||||||
|
** These lists are linked by fields 'gclist'. (All objects that
|
||||||
|
** can become gray have such a field. The field is not the same
|
||||||
|
** in all objects, but it always has this name.) Any gray object
|
||||||
|
** must belong to one of these lists, and all objects in these lists
|
||||||
|
** must be gray (with two exceptions explained below):
|
||||||
|
**
|
||||||
|
** 'gray': regular gray objects, still waiting to be visited.
|
||||||
|
** 'grayagain': objects that must be revisited at the atomic phase.
|
||||||
|
** That includes
|
||||||
|
** - black objects got in a write barrier;
|
||||||
|
** - all kinds of weak tables during propagation phase;
|
||||||
|
** - all threads.
|
||||||
|
** 'weak': tables with weak values to be cleared;
|
||||||
|
** 'ephemeron': ephemeron tables with white->white entries;
|
||||||
|
** 'allweak': tables with weak keys and/or weak values to be cleared.
|
||||||
|
**
|
||||||
|
** The exceptions to that "gray rule" are:
|
||||||
|
** - TOUCHED2 objects in generational mode stay in a gray list (because
|
||||||
|
** they must be visited again at the end of the cycle), but they are
|
||||||
|
** marked black because assignments to them must activate barriers (to
|
||||||
|
** move them back to TOUCHED1).
|
||||||
|
** - Open upvales are kept gray to avoid barriers, but they stay out
|
||||||
|
** of gray lists. (They don't even have a 'gclist' field.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** About 'nCcalls': This count has two parts: the lower 16 bits counts
|
||||||
|
** the number of recursive invocations in the C stack; the higher
|
||||||
|
** 16 bits counts the number of non-yieldable calls in the stack.
|
||||||
|
** (They are together so that we can change and save both with one
|
||||||
|
** instruction.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* true if this thread does not have non-yieldable calls in the stack */
|
||||||
|
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
|
||||||
|
|
||||||
|
/* real number of C calls */
|
||||||
|
#define getCcalls(L) ((L)->nCcalls & 0xffff)
|
||||||
|
|
||||||
|
|
||||||
|
/* Increment the number of non-yieldable calls */
|
||||||
|
#define incnny(L) ((L)->nCcalls += 0x10000)
|
||||||
|
|
||||||
|
/* Decrement the number of non-yieldable calls */
|
||||||
|
#define decnny(L) ((L)->nCcalls -= 0x10000)
|
||||||
|
|
||||||
|
/* Non-yieldable call increment */
|
||||||
|
#define nyci (0x10000 | 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct lua_longjmp; /* defined in ldo.c */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
|
||||||
|
** is thread safe
|
||||||
|
*/
|
||||||
|
#if !defined(l_signalT)
|
||||||
|
#include <signal.h>
|
||||||
|
#define l_signalT sig_atomic_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Extra stack space to handle TM calls and some other extras. This
|
||||||
|
** space is not included in 'stack_last'. It is used only to avoid stack
|
||||||
|
** checks, either because the element will be promptly popped or because
|
||||||
|
** there will be a stack check soon after the push. Function frames
|
||||||
|
** never use this extra space, so it does not need to be kept clean.
|
||||||
|
*/
|
||||||
|
#define EXTRA_STACK 5
|
||||||
|
|
||||||
|
|
||||||
|
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
|
||||||
|
|
||||||
|
#define stacksize(th) cast_int((th)->stack_last - (th)->stack)
|
||||||
|
|
||||||
|
|
||||||
|
/* kinds of Garbage Collection */
|
||||||
|
#define KGC_INC 0 /* incremental gc */
|
||||||
|
#define KGC_GEN 1 /* generational gc */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct stringtable {
|
||||||
|
TString **hash;
|
||||||
|
int nuse; /* number of elements */
|
||||||
|
int size;
|
||||||
|
} stringtable;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Information about a call.
|
||||||
|
** About union 'u':
|
||||||
|
** - field 'l' is used only for Lua functions;
|
||||||
|
** - field 'c' is used only for C functions.
|
||||||
|
** About union 'u2':
|
||||||
|
** - field 'funcidx' is used only by C functions while doing a
|
||||||
|
** protected call;
|
||||||
|
** - field 'nyield' is used only while a function is "doing" an
|
||||||
|
** yield (from the yield until the next resume);
|
||||||
|
** - field 'nres' is used only while closing tbc variables when
|
||||||
|
** returning from a function;
|
||||||
|
** - field 'transferinfo' is used only during call/returnhooks,
|
||||||
|
** before the function starts or after it ends.
|
||||||
|
*/
|
||||||
|
typedef struct CallInfo {
|
||||||
|
StkId func; /* function index in the stack */
|
||||||
|
StkId top; /* top for this function */
|
||||||
|
struct CallInfo *previous, *next; /* dynamic call link */
|
||||||
|
union {
|
||||||
|
struct { /* only for Lua functions */
|
||||||
|
const Instruction *savedpc;
|
||||||
|
volatile l_signalT trap;
|
||||||
|
int nextraargs; /* # of extra arguments in vararg functions */
|
||||||
|
} l;
|
||||||
|
struct { /* only for C functions */
|
||||||
|
lua_KFunction k; /* continuation in case of yields */
|
||||||
|
ptrdiff_t old_errfunc;
|
||||||
|
lua_KContext ctx; /* context info. in case of yields */
|
||||||
|
} c;
|
||||||
|
} u;
|
||||||
|
union {
|
||||||
|
int funcidx; /* called-function index */
|
||||||
|
int nyield; /* number of values yielded */
|
||||||
|
int nres; /* number of values returned */
|
||||||
|
struct { /* info about transferred values (for call/return hooks) */
|
||||||
|
unsigned short ftransfer; /* offset of first value transferred */
|
||||||
|
unsigned short ntransfer; /* number of values transferred */
|
||||||
|
} transferinfo;
|
||||||
|
} u2;
|
||||||
|
short nresults; /* expected number of results from this function */
|
||||||
|
unsigned short callstatus;
|
||||||
|
} CallInfo;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Bits in CallInfo status
|
||||||
|
*/
|
||||||
|
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
|
||||||
|
#define CIST_C (1<<1) /* call is running a C function */
|
||||||
|
#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
|
||||||
|
#define CIST_HOOKED (1<<3) /* call is running a debug hook */
|
||||||
|
#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
|
||||||
|
#define CIST_TAIL (1<<5) /* call was tail called */
|
||||||
|
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
||||||
|
#define CIST_FIN (1<<7) /* function "called" a finalizer */
|
||||||
|
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
|
||||||
|
#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
|
||||||
|
/* Bits 10-12 are used for CIST_RECST (see below) */
|
||||||
|
#define CIST_RECST 10
|
||||||
|
#if defined(LUA_COMPAT_LT_LE)
|
||||||
|
#define CIST_LEQ (1<<13) /* using __lt for __le */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Field CIST_RECST stores the "recover status", used to keep the error
|
||||||
|
** status while closing to-be-closed variables in coroutines, so that
|
||||||
|
** Lua can correctly resume after an yield from a __close method called
|
||||||
|
** because of an error. (Three bits are enough for error status.)
|
||||||
|
*/
|
||||||
|
#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7)
|
||||||
|
#define setcistrecst(ci,st) \
|
||||||
|
check_exp(((st) & 7) == (st), /* status must fit in three bits */ \
|
||||||
|
((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \
|
||||||
|
| ((st) << CIST_RECST)))
|
||||||
|
|
||||||
|
|
||||||
|
/* active function is a Lua function */
|
||||||
|
#define isLua(ci) (!((ci)->callstatus & CIST_C))
|
||||||
|
|
||||||
|
/* call is running Lua code (not a hook) */
|
||||||
|
#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED)))
|
||||||
|
|
||||||
|
/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
|
||||||
|
#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v))
|
||||||
|
#define getoah(st) ((st) & CIST_OAH)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** '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' */
|
||||||
|
l_mem totalbytes; /* number of bytes currently allocated - GCdebt */
|
||||||
|
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
|
||||||
|
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
|
||||||
|
lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */
|
||||||
|
stringtable strt; /* hash table for strings */
|
||||||
|
TValue l_registry;
|
||||||
|
TValue nilvalue; /* a nil value */
|
||||||
|
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 gcstopem; /* stops emergency collections */
|
||||||
|
lu_byte genminormul; /* control for minor generational collections */
|
||||||
|
lu_byte genmajormul; /* control for major generational collections */
|
||||||
|
lu_byte gcstp; /* control whether GC is running */
|
||||||
|
lu_byte gcemergency; /* true if this is an emergency collection */
|
||||||
|
lu_byte gcpause; /* size of pause between successive GCs */
|
||||||
|
lu_byte gcstepmul; /* GC "speed" */
|
||||||
|
lu_byte gcstepsize; /* (log2 of) GC granularity */
|
||||||
|
GCObject *allgc; /* list of all collectable objects */
|
||||||
|
GCObject **sweepgc; /* current position of sweep in list */
|
||||||
|
GCObject *finobj; /* list of collectable objects with finalizers */
|
||||||
|
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 */
|
||||||
|
GCObject *fixedgc; /* list of objects not to be collected */
|
||||||
|
/* fields for generational collector */
|
||||||
|
GCObject *survival; /* start of objects that survived one GC cycle */
|
||||||
|
GCObject *old1; /* start of old1 objects */
|
||||||
|
GCObject *reallyold; /* objects more than one cycle old ("really old") */
|
||||||
|
GCObject *firstold1; /* first OLD1 object in the list (if any) */
|
||||||
|
GCObject *finobjsur; /* list of survival objects with finalizers */
|
||||||
|
GCObject *finobjold1; /* list of old1 objects with finalizers */
|
||||||
|
GCObject *finobjrold; /* list of really old objects with finalizers */
|
||||||
|
struct lua_State *twups; /* list of threads with open upvalues */
|
||||||
|
lua_CFunction panic; /* to be called in unprotected errors */
|
||||||
|
struct lua_State *mainthread;
|
||||||
|
TString *memerrmsg; /* message for memory-allocation errors */
|
||||||
|
TString *tmname[TM_N]; /* array with tag-method names */
|
||||||
|
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
|
||||||
|
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
|
||||||
|
lua_WarnFunction warnf; /* warning function */
|
||||||
|
void *ud_warn; /* auxiliary data to 'warnf' */
|
||||||
|
} global_State;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'per thread' state
|
||||||
|
*/
|
||||||
|
struct lua_State {
|
||||||
|
CommonHeader;
|
||||||
|
lu_byte status;
|
||||||
|
lu_byte allowhook;
|
||||||
|
unsigned short nci; /* number of items in 'ci' list */
|
||||||
|
StkId top; /* first free slot in the stack */
|
||||||
|
global_State *l_G;
|
||||||
|
CallInfo *ci; /* call info for current function */
|
||||||
|
StkId stack_last; /* end of stack (last element + 1) */
|
||||||
|
StkId stack; /* stack base */
|
||||||
|
UpVal *openupval; /* list of open upvalues in this stack */
|
||||||
|
StkId tbclist; /* list of to-be-closed variables */
|
||||||
|
GCObject *gclist;
|
||||||
|
struct lua_State *twups; /* list of threads with open upvalues */
|
||||||
|
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||||
|
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
|
||||||
|
volatile lua_Hook hook;
|
||||||
|
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
||||||
|
l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */
|
||||||
|
int oldpc; /* last pc traced */
|
||||||
|
int basehookcount;
|
||||||
|
int hookcount;
|
||||||
|
volatile l_signalT hookmask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define G(L) (L->l_G)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'g->nilvalue' being a nil value flags that the state was completely
|
||||||
|
** build.
|
||||||
|
*/
|
||||||
|
#define completestate(g) ttisnil(&g->nilvalue)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Union of all collectable objects (only for conversions)
|
||||||
|
** ISO C99, 6.5.2.3 p.5:
|
||||||
|
** "if a union contains several structures that share a common initial
|
||||||
|
** sequence [...], and if the union object currently contains one
|
||||||
|
** of these structures, it is permitted to inspect the common initial
|
||||||
|
** part of any of them anywhere that a declaration of the complete type
|
||||||
|
** of the union is visible."
|
||||||
|
*/
|
||||||
|
union GCUnion {
|
||||||
|
GCObject gc; /* common header */
|
||||||
|
struct TString ts;
|
||||||
|
struct Udata u;
|
||||||
|
union Closure cl;
|
||||||
|
struct Table h;
|
||||||
|
struct Proto p;
|
||||||
|
struct lua_State th; /* thread */
|
||||||
|
struct UpVal upv;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** ISO C99, 6.7.2.1 p.14:
|
||||||
|
** "A pointer to a union object, suitably converted, points to each of
|
||||||
|
** its members [...], and vice versa."
|
||||||
|
*/
|
||||||
|
#define cast_u(o) cast(union GCUnion *, (o))
|
||||||
|
|
||||||
|
/* macros to convert a GCObject into a specific value */
|
||||||
|
#define gco2ts(o) \
|
||||||
|
check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
|
||||||
|
#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u))
|
||||||
|
#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l))
|
||||||
|
#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c))
|
||||||
|
#define gco2cl(o) \
|
||||||
|
check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
|
||||||
|
#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
|
||||||
|
#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
|
||||||
|
#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
|
||||||
|
#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro to convert a Lua object into a GCObject
|
||||||
|
** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.)
|
||||||
|
*/
|
||||||
|
#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc))
|
||||||
|
|
||||||
|
|
||||||
|
/* actual number of total bytes allocated */
|
||||||
|
#define gettotalbytes(g) cast(lu_mem, (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);
|
||||||
|
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
||||||
|
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
||||||
|
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
||||||
|
LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
|
||||||
|
LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
|
||||||
|
LUAI_FUNC int luaE_resetthread (lua_State *L, int status);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
** $Id: lstring.h $
|
||||||
|
** String table (keep all strings handled by Lua)
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lstring_h
|
||||||
|
#define lstring_h
|
||||||
|
|
||||||
|
#include "lgc.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lstate.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Memory-allocation error message must be preallocated (it cannot
|
||||||
|
** be created after memory is exhausted)
|
||||||
|
*/
|
||||||
|
#define MEMERRMSG "not enough memory"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Size of a TString: Size of the header plus space for the string
|
||||||
|
** itself (including final '\0').
|
||||||
|
*/
|
||||||
|
#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
|
||||||
|
|
||||||
|
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
||||||
|
(sizeof(s)/sizeof(char))-1))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** test whether a string is a reserved word
|
||||||
|
*/
|
||||||
|
#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** equality for short strings, which are always internalized
|
||||||
|
*/
|
||||||
|
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
|
||||||
|
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
|
||||||
|
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
|
||||||
|
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
||||||
|
LUAI_FUNC void luaS_clearcache (global_State *g);
|
||||||
|
LUAI_FUNC void luaS_init (lua_State *L);
|
||||||
|
LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
|
||||||
|
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue);
|
||||||
|
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
|
||||||
|
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
|
||||||
|
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
** $Id: ltable.h $
|
||||||
|
** Lua tables (hash)
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ltable_h
|
||||||
|
#define ltable_h
|
||||||
|
|
||||||
|
#include "lobject.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define gnode(t,i) (&(t)->node[i])
|
||||||
|
#define gval(n) (&(n)->i_val)
|
||||||
|
#define gnext(n) ((n)->u.next)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Clear all bits of fast-access metamethods, which means that the table
|
||||||
|
** may have any of these metamethods. (First access that fails after the
|
||||||
|
** clearing will set the bit again.)
|
||||||
|
*/
|
||||||
|
#define invalidateTMcache(t) ((t)->flags &= ~maskflags)
|
||||||
|
|
||||||
|
|
||||||
|
/* true when 't' is using 'dummynode' as its hash part */
|
||||||
|
#define isdummy(t) ((t)->lastfree == NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/* allocated size for hash nodes */
|
||||||
|
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
|
||||||
|
|
||||||
|
|
||||||
|
/* returns the Node, given the value of a table entry */
|
||||||
|
#define nodefromval(v) cast(Node *, (v))
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
|
||||||
|
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
|
||||||
|
TValue *value);
|
||||||
|
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
|
||||||
|
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
|
||||||
|
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
|
||||||
|
LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key,
|
||||||
|
TValue *value);
|
||||||
|
LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
|
||||||
|
TValue *value);
|
||||||
|
LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
||||||
|
const TValue *slot, TValue *value);
|
||||||
|
LUAI_FUNC Table *luaH_new (lua_State *L);
|
||||||
|
LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
||||||
|
unsigned int nhsize);
|
||||||
|
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
|
||||||
|
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
|
||||||
|
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
|
||||||
|
LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
|
||||||
|
LUAI_FUNC unsigned int luaH_realasize (const Table *t);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_DEBUG)
|
||||||
|
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
|
||||||
|
LUAI_FUNC int luaH_isdummy (const Table *t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
** $Id: ltm.h $
|
||||||
|
** 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" and "ORDER OP"
|
||||||
|
*/
|
||||||
|
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_MOD,
|
||||||
|
TM_POW,
|
||||||
|
TM_DIV,
|
||||||
|
TM_IDIV,
|
||||||
|
TM_BAND,
|
||||||
|
TM_BOR,
|
||||||
|
TM_BXOR,
|
||||||
|
TM_SHL,
|
||||||
|
TM_SHR,
|
||||||
|
TM_UNM,
|
||||||
|
TM_BNOT,
|
||||||
|
TM_LT,
|
||||||
|
TM_LE,
|
||||||
|
TM_CONCAT,
|
||||||
|
TM_CALL,
|
||||||
|
TM_CLOSE,
|
||||||
|
TM_N /* number of elements in the enum */
|
||||||
|
} TMS;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Mask with 1 in all fast-access methods. A 1 in any of these bits
|
||||||
|
** in the flag of a (meta)table means the metatable does not have the
|
||||||
|
** corresponding metamethod field. (Bit 7 of the flag is used for
|
||||||
|
** 'isrealasize'.)
|
||||||
|
*/
|
||||||
|
#define maskflags (~(~0u << (TM_EQ + 1)))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Test whether there is no tagmethod.
|
||||||
|
** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
|
||||||
|
*/
|
||||||
|
#define notm(tm) ttisnil(tm)
|
||||||
|
|
||||||
|
|
||||||
|
#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]
|
||||||
|
|
||||||
|
LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];)
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
|
||||||
|
const TValue *p2, const TValue *p3);
|
||||||
|
LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f,
|
||||||
|
const TValue *p1, const TValue *p2, StkId p3);
|
||||||
|
LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
|
||||||
|
StkId res, TMS event);
|
||||||
|
LUAI_FUNC void luaT_tryconcatTM (lua_State *L);
|
||||||
|
LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2, int inv, StkId res, TMS event);
|
||||||
|
LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
|
||||||
|
int inv, StkId res, TMS event);
|
||||||
|
LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
|
||||||
|
const TValue *p2, TMS event);
|
||||||
|
LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
|
||||||
|
int inv, int isfloat, TMS event);
|
||||||
|
|
||||||
|
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
|
||||||
|
struct CallInfo *ci, const Proto *p);
|
||||||
|
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
|
||||||
|
StkId where, int wanted);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,518 @@
|
||||||
|
/*
|
||||||
|
** $Id: lua.h $
|
||||||
|
** 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 "4"
|
||||||
|
#define LUA_VERSION_RELEASE "4"
|
||||||
|
|
||||||
|
#define LUA_VERSION_NUM 504
|
||||||
|
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 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-2022 Lua.org, PUC-Rio"
|
||||||
|
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
||||||
|
|
||||||
|
|
||||||
|
/* mark for precompiled code ('<esc>Lua') */
|
||||||
|
#define LUA_SIGNATURE "\x1bLua"
|
||||||
|
|
||||||
|
/* option for multiple returns in 'lua_pcall' and 'lua_call' */
|
||||||
|
#define LUA_MULTRET (-1)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Pseudo-indices
|
||||||
|
** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
|
||||||
|
** space after that to help overflow detection)
|
||||||
|
*/
|
||||||
|
#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
|
||||||
|
#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_ERRERR 5
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct lua_State lua_State;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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_NUMTYPES 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;
|
||||||
|
|
||||||
|
/* type for continuation-function contexts */
|
||||||
|
typedef LUA_KCONTEXT lua_KContext;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Type for C functions registered with Lua
|
||||||
|
*/
|
||||||
|
typedef int (*lua_CFunction) (lua_State *L);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Type for continuation functions
|
||||||
|
*/
|
||||||
|
typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Type for 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);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Type for memory-allocation functions
|
||||||
|
*/
|
||||||
|
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Type for warning functions
|
||||||
|
*/
|
||||||
|
typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 int (lua_resetthread) (lua_State *L);
|
||||||
|
|
||||||
|
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||||
|
|
||||||
|
|
||||||
|
LUA_API 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_rotate) (lua_State *L, int idx, int n);
|
||||||
|
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
|
||||||
|
LUA_API int (lua_checkstack) (lua_State *L, int n);
|
||||||
|
|
||||||
|
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_isinteger) (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 int (lua_toboolean) (lua_State *L, int idx);
|
||||||
|
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
|
||||||
|
LUA_API lua_Unsigned (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, ORDER OP */
|
||||||
|
#define LUA_OPSUB 1
|
||||||
|
#define LUA_OPMUL 2
|
||||||
|
#define LUA_OPMOD 3
|
||||||
|
#define LUA_OPPOW 4
|
||||||
|
#define LUA_OPDIV 5
|
||||||
|
#define LUA_OPIDIV 6
|
||||||
|
#define LUA_OPBAND 7
|
||||||
|
#define LUA_OPBOR 8
|
||||||
|
#define LUA_OPBXOR 9
|
||||||
|
#define LUA_OPSHL 10
|
||||||
|
#define LUA_OPSHR 11
|
||||||
|
#define LUA_OPUNM 12
|
||||||
|
#define LUA_OPBNOT 13
|
||||||
|
|
||||||
|
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 const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
|
||||||
|
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 int (lua_getglobal) (lua_State *L, const char *name);
|
||||||
|
LUA_API int (lua_gettable) (lua_State *L, int idx);
|
||||||
|
LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||||
|
LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
|
||||||
|
LUA_API int (lua_rawget) (lua_State *L, int idx);
|
||||||
|
LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
|
||||||
|
LUA_API int (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_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
|
||||||
|
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||||
|
LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** set functions (stack -> Lua)
|
||||||
|
*/
|
||||||
|
LUA_API void (lua_setglobal) (lua_State *L, const char *name);
|
||||||
|
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_seti) (lua_State *L, int idx, lua_Integer n);
|
||||||
|
LUA_API void (lua_rawset) (lua_State *L, int idx);
|
||||||
|
LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer 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 int (lua_setiuservalue) (lua_State *L, int idx, int n);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'load' and 'call' functions (load and run Lua code)
|
||||||
|
*/
|
||||||
|
LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults,
|
||||||
|
lua_KContext ctx, lua_KFunction k);
|
||||||
|
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
|
||||||
|
|
||||||
|
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
|
||||||
|
lua_KContext ctx, lua_KFunction 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, int strip);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** coroutine functions
|
||||||
|
*/
|
||||||
|
LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
|
||||||
|
lua_KFunction k);
|
||||||
|
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg,
|
||||||
|
int *nres);
|
||||||
|
LUA_API int (lua_status) (lua_State *L);
|
||||||
|
LUA_API int (lua_isyieldable) (lua_State *L);
|
||||||
|
|
||||||
|
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Warning-related functions
|
||||||
|
*/
|
||||||
|
LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
|
||||||
|
LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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_GCISRUNNING 9
|
||||||
|
#define LUA_GCGEN 10
|
||||||
|
#define LUA_GCINC 11
|
||||||
|
|
||||||
|
LUA_API int (lua_gc) (lua_State *L, int what, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 size_t (lua_stringtonumber) (lua_State *L, const char *s);
|
||||||
|
|
||||||
|
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
||||||
|
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
|
||||||
|
|
||||||
|
LUA_API void (lua_toclose) (lua_State *L, int idx);
|
||||||
|
LUA_API void (lua_closeslot) (lua_State *L, int idx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==============================================================
|
||||||
|
** some useful macros
|
||||||
|
** ===============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||||
|
|
||||||
|
#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL)
|
||||||
|
#define lua_tointeger(L,i) lua_tointegerx(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_pushstring(L, "" s)
|
||||||
|
|
||||||
|
#define lua_pushglobaltable(L) \
|
||||||
|
((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||||
|
|
||||||
|
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||||
|
|
||||||
|
|
||||||
|
#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
||||||
|
|
||||||
|
#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
||||||
|
|
||||||
|
#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
||||||
|
|
||||||
|
/* }============================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==============================================================
|
||||||
|
** compatibility macros
|
||||||
|
** ===============================================================
|
||||||
|
*/
|
||||||
|
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||||
|
|
||||||
|
#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
|
||||||
|
#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is))
|
||||||
|
#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
|
||||||
|
#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
|
||||||
|
#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1)
|
||||||
|
|
||||||
|
#define LUA_NUMTAGS LUA_NUMTYPES
|
||||||
|
|
||||||
|
/* }============================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {======================================================================
|
||||||
|
** 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 void (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);
|
||||||
|
|
||||||
|
LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit);
|
||||||
|
|
||||||
|
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) */
|
||||||
|
size_t srclen; /* (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) */
|
||||||
|
unsigned short ftransfer; /* (r) index of first value transferred */
|
||||||
|
unsigned short ntransfer; /* (r) number of transferred values */
|
||||||
|
char short_src[LUA_IDSIZE]; /* (S) */
|
||||||
|
/* private part */
|
||||||
|
struct CallInfo *i_ci; /* active function */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* }====================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 1994-2022 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,786 @@
|
||||||
|
/*
|
||||||
|
** $Id: luaconf.h $
|
||||||
|
** Configuration file for Lua
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef luaconf_h
|
||||||
|
#define luaconf_h
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** ===================================================================
|
||||||
|
** General Configuration File for Lua
|
||||||
|
**
|
||||||
|
** Some definitions here can be changed externally, through the compiler
|
||||||
|
** (e.g., with '-D' options): They are commented out or protected
|
||||||
|
** by '#if !defined' guards. However, several other definitions
|
||||||
|
** should be changed directly here, either because they affect the
|
||||||
|
** Lua ABI (by making the changes here, you ensure that all software
|
||||||
|
** connected to Lua, such as C libraries, will be compiled with the same
|
||||||
|
** configuration); or because they are seldom changed.
|
||||||
|
**
|
||||||
|
** Search for "@@" to find all configurable definitions.
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {====================================================================
|
||||||
|
** System Configuration: macros to adapt (if needed) Lua to some
|
||||||
|
** particular platform, for instance restricting it to C89.
|
||||||
|
** =====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
|
||||||
|
** Define it if you want Lua to avoid the use of a few C99 features
|
||||||
|
** or Windows-specific features on Windows.
|
||||||
|
*/
|
||||||
|
/* #define LUA_USE_C89 */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** By default, Lua on Windows use (some) specific Windows features
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
|
||||||
|
#define LUA_USE_WINDOWS /* enable goodies for regular Windows */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_USE_WINDOWS)
|
||||||
|
#define LUA_DL_DLL /* enable support for DLL */
|
||||||
|
#define LUA_USE_C89 /* broadly, Windows is C89 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_USE_LINUX)
|
||||||
|
#define LUA_USE_POSIX
|
||||||
|
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_USE_MACOSX)
|
||||||
|
#define LUA_USE_POSIX
|
||||||
|
#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
|
||||||
|
*/
|
||||||
|
#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Configuration for Number types. These options should not be
|
||||||
|
** set externally, because any other code connected to Lua must
|
||||||
|
** use the same configuration.
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_INT_TYPE defines the type for Lua integers.
|
||||||
|
@@ LUA_FLOAT_TYPE defines the type for Lua floats.
|
||||||
|
** Lua should work fine with any mix of these options supported
|
||||||
|
** by your C compiler. The usual configurations are 64-bit integers
|
||||||
|
** and 'double' (the default), 32-bit integers and 'float' (for
|
||||||
|
** restricted platforms), and 'long'/'double' (for C compilers not
|
||||||
|
** compliant with C99, which may not have support for 'long long').
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* predefined options for LUA_INT_TYPE */
|
||||||
|
#define LUA_INT_INT 1
|
||||||
|
#define LUA_INT_LONG 2
|
||||||
|
#define LUA_INT_LONGLONG 3
|
||||||
|
|
||||||
|
/* predefined options for LUA_FLOAT_TYPE */
|
||||||
|
#define LUA_FLOAT_FLOAT 1
|
||||||
|
#define LUA_FLOAT_DOUBLE 2
|
||||||
|
#define LUA_FLOAT_LONGDOUBLE 3
|
||||||
|
|
||||||
|
|
||||||
|
/* Default configuration ('long long' and 'double', for 64-bit Lua) */
|
||||||
|
#define LUA_INT_DEFAULT LUA_INT_LONGLONG
|
||||||
|
#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
|
||||||
|
*/
|
||||||
|
#define LUA_32BITS 0
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
|
||||||
|
** C89 ('long' and 'double'); Windows always has '__int64', so it does
|
||||||
|
** not need to use this case.
|
||||||
|
*/
|
||||||
|
#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
|
||||||
|
#define LUA_C89_NUMBERS 1
|
||||||
|
#else
|
||||||
|
#define LUA_C89_NUMBERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if LUA_32BITS /* { */
|
||||||
|
/*
|
||||||
|
** 32-bit integers and 'float'
|
||||||
|
*/
|
||||||
|
#if LUAI_IS32INT /* use 'int' if big enough */
|
||||||
|
#define LUA_INT_TYPE LUA_INT_INT
|
||||||
|
#else /* otherwise use 'long' */
|
||||||
|
#define LUA_INT_TYPE LUA_INT_LONG
|
||||||
|
#endif
|
||||||
|
#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
|
||||||
|
|
||||||
|
#elif LUA_C89_NUMBERS /* }{ */
|
||||||
|
/*
|
||||||
|
** largest types available for C89 ('long' and 'double')
|
||||||
|
*/
|
||||||
|
#define LUA_INT_TYPE LUA_INT_LONG
|
||||||
|
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
/* use defaults */
|
||||||
|
|
||||||
|
#define LUA_INT_TYPE LUA_INT_DEFAULT
|
||||||
|
#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Configuration for Paths.
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** LUA_PATH_SEP is the character that separates templates in a path.
|
||||||
|
** LUA_PATH_MARK is the string that marks the substitution points in a
|
||||||
|
** template.
|
||||||
|
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
|
||||||
|
** directory.
|
||||||
|
*/
|
||||||
|
#define LUA_PATH_SEP ";"
|
||||||
|
#define LUA_PATH_MARK "?"
|
||||||
|
#define LUA_EXEC_DIR "!"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||||
|
#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_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
|
||||||
|
|
||||||
|
#if !defined(LUA_PATH_DEFAULT)
|
||||||
|
#define LUA_PATH_DEFAULT \
|
||||||
|
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
|
||||||
|
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
|
||||||
|
LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
|
||||||
|
".\\?.lua;" ".\\?\\init.lua"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LUA_CPATH_DEFAULT)
|
||||||
|
#define LUA_CPATH_DEFAULT \
|
||||||
|
LUA_CDIR"?.dll;" \
|
||||||
|
LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
|
||||||
|
LUA_CDIR"loadall.dll;" ".\\?.dll"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
|
||||||
|
#define LUA_ROOT "/usr/local/"
|
||||||
|
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
|
||||||
|
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
|
||||||
|
|
||||||
|
#if !defined(LUA_PATH_DEFAULT)
|
||||||
|
#define LUA_PATH_DEFAULT \
|
||||||
|
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
|
||||||
|
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
|
||||||
|
"./?.lua;" "./?/init.lua"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LUA_CPATH_DEFAULT)
|
||||||
|
#define LUA_CPATH_DEFAULT \
|
||||||
|
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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(LUA_DIRSEP)
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define LUA_DIRSEP "\\"
|
||||||
|
#else
|
||||||
|
#define LUA_DIRSEP "/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Marks for exported symbols in the C code
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ 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 LUA_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,
|
||||||
|
** none of which 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("internal"))) extern
|
||||||
|
#else /* }{ */
|
||||||
|
#define LUAI_FUNC extern
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
#define LUAI_DDEC(dec) LUAI_FUNC dec
|
||||||
|
#define LUAI_DDEF /* empty */
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Compatibility with previous versions
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3.
|
||||||
|
** You can define it to get all options, or change specific options
|
||||||
|
** to fit your specific needs.
|
||||||
|
*/
|
||||||
|
#if defined(LUA_COMPAT_5_3) /* { */
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
|
||||||
|
** functions in the mathematical library.
|
||||||
|
** (These functions were already officially removed in 5.3;
|
||||||
|
** nevertheless they are still available here.)
|
||||||
|
*/
|
||||||
|
#define LUA_COMPAT_MATHLIB
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
|
||||||
|
** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
|
||||||
|
** luaL_checkint, luaL_checklong, etc.)
|
||||||
|
** (These macros were also officially removed in 5.3, but they are still
|
||||||
|
** available here.)
|
||||||
|
*/
|
||||||
|
#define LUA_COMPAT_APIINTCASTS
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
|
||||||
|
** using '__lt'.
|
||||||
|
*/
|
||||||
|
#define LUA_COMPAT_LT_LE
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ 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.
|
||||||
|
** (Once more, these macros were officially removed in 5.3, but they are
|
||||||
|
** still available here.)
|
||||||
|
*/
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Configuration for Numbers (low-level part).
|
||||||
|
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
|
||||||
|
** satisfy your needs.
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
|
||||||
|
@@ over a floating number.
|
||||||
|
@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
|
||||||
|
** by prefixing it with one of FLT/DBL/LDBL.
|
||||||
|
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
|
||||||
|
@@ LUA_NUMBER_FMT is the format for writing floats.
|
||||||
|
@@ lua_number2str converts a float to a string.
|
||||||
|
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
|
||||||
|
@@ l_floor takes the floor of a float.
|
||||||
|
@@ lua_str2number converts a decimal numeral to a number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* The following definitions are good for most cases here */
|
||||||
|
|
||||||
|
#define l_floor(x) (l_mathop(floor)(x))
|
||||||
|
|
||||||
|
#define lua_number2str(s,sz,n) \
|
||||||
|
l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_numbertointeger converts a float number with an integral value
|
||||||
|
** to an integer, or returns 0 if float is not within the range of
|
||||||
|
** a lua_Integer. (The range comparisons are tricky because of
|
||||||
|
** rounding. The tests here assume a two-complement representation,
|
||||||
|
** where MININTEGER always has an exact representation as a float;
|
||||||
|
** MAXINTEGER may not have one, and therefore its conversion to float
|
||||||
|
** may have an ill-defined value.)
|
||||||
|
*/
|
||||||
|
#define lua_numbertointeger(n,p) \
|
||||||
|
((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
|
||||||
|
(n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
|
||||||
|
(*(p) = (LUA_INTEGER)(n), 1))
|
||||||
|
|
||||||
|
|
||||||
|
/* now the variable definitions */
|
||||||
|
|
||||||
|
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
|
||||||
|
|
||||||
|
#define LUA_NUMBER float
|
||||||
|
|
||||||
|
#define l_floatatt(n) (FLT_##n)
|
||||||
|
|
||||||
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
|
#define LUA_NUMBER_FMT "%.7g"
|
||||||
|
|
||||||
|
#define l_mathop(op) op##f
|
||||||
|
|
||||||
|
#define lua_str2number(s,p) strtof((s), (p))
|
||||||
|
|
||||||
|
|
||||||
|
#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
|
||||||
|
|
||||||
|
#define LUA_NUMBER long double
|
||||||
|
|
||||||
|
#define l_floatatt(n) (LDBL_##n)
|
||||||
|
|
||||||
|
#define LUAI_UACNUMBER long double
|
||||||
|
|
||||||
|
#define LUA_NUMBER_FRMLEN "L"
|
||||||
|
#define LUA_NUMBER_FMT "%.19Lg"
|
||||||
|
|
||||||
|
#define l_mathop(op) op##l
|
||||||
|
|
||||||
|
#define lua_str2number(s,p) strtold((s), (p))
|
||||||
|
|
||||||
|
#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
|
||||||
|
|
||||||
|
#define LUA_NUMBER double
|
||||||
|
|
||||||
|
#define l_floatatt(n) (DBL_##n)
|
||||||
|
|
||||||
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
|
#define LUA_NUMBER_FMT "%.14g"
|
||||||
|
|
||||||
|
#define l_mathop(op) op
|
||||||
|
|
||||||
|
#define lua_str2number(s,p) strtod((s), (p))
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
|
||||||
|
#error "numeric float type not defined"
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
|
||||||
|
@@ LUAI_UACINT is the result of a 'default argument promotion'
|
||||||
|
@@ over a LUA_INTEGER.
|
||||||
|
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
|
||||||
|
@@ LUA_INTEGER_FMT is the format for writing integers.
|
||||||
|
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
|
||||||
|
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
|
||||||
|
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
|
||||||
|
@@ lua_integer2str converts an integer to a string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* The following definitions are good for most cases here */
|
||||||
|
|
||||||
|
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
|
||||||
|
|
||||||
|
#define LUAI_UACINT LUA_INTEGER
|
||||||
|
|
||||||
|
#define lua_integer2str(s,sz,n) \
|
||||||
|
l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n))
|
||||||
|
|
||||||
|
/*
|
||||||
|
** use LUAI_UACINT here to avoid problems with promotions (which
|
||||||
|
** can turn a comparison between unsigneds into a signed comparison)
|
||||||
|
*/
|
||||||
|
#define LUA_UNSIGNED unsigned LUAI_UACINT
|
||||||
|
|
||||||
|
|
||||||
|
/* now the variable definitions */
|
||||||
|
|
||||||
|
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
|
||||||
|
|
||||||
|
#define LUA_INTEGER int
|
||||||
|
#define LUA_INTEGER_FRMLEN ""
|
||||||
|
|
||||||
|
#define LUA_MAXINTEGER INT_MAX
|
||||||
|
#define LUA_MININTEGER INT_MIN
|
||||||
|
|
||||||
|
#define LUA_MAXUNSIGNED UINT_MAX
|
||||||
|
|
||||||
|
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
|
||||||
|
|
||||||
|
#define LUA_INTEGER long
|
||||||
|
#define LUA_INTEGER_FRMLEN "l"
|
||||||
|
|
||||||
|
#define LUA_MAXINTEGER LONG_MAX
|
||||||
|
#define LUA_MININTEGER LONG_MIN
|
||||||
|
|
||||||
|
#define LUA_MAXUNSIGNED ULONG_MAX
|
||||||
|
|
||||||
|
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
|
||||||
|
|
||||||
|
/* use presence of macro LLONG_MAX as proxy for C99 compliance */
|
||||||
|
#if defined(LLONG_MAX) /* { */
|
||||||
|
/* use ISO C99 stuff */
|
||||||
|
|
||||||
|
#define LUA_INTEGER long long
|
||||||
|
#define LUA_INTEGER_FRMLEN "ll"
|
||||||
|
|
||||||
|
#define LUA_MAXINTEGER LLONG_MAX
|
||||||
|
#define LUA_MININTEGER LLONG_MIN
|
||||||
|
|
||||||
|
#define LUA_MAXUNSIGNED ULLONG_MAX
|
||||||
|
|
||||||
|
#elif defined(LUA_USE_WINDOWS) /* }{ */
|
||||||
|
/* in Windows, can use specific Windows types */
|
||||||
|
|
||||||
|
#define LUA_INTEGER __int64
|
||||||
|
#define LUA_INTEGER_FRMLEN "I64"
|
||||||
|
|
||||||
|
#define LUA_MAXINTEGER _I64_MAX
|
||||||
|
#define LUA_MININTEGER _I64_MIN
|
||||||
|
|
||||||
|
#define LUA_MAXUNSIGNED _UI64_MAX
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
|
||||||
|
#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
|
||||||
|
or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
#else /* }{ */
|
||||||
|
|
||||||
|
#error "numeric integer type not defined"
|
||||||
|
|
||||||
|
#endif /* } */
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Dependencies with C99 and other C details
|
||||||
|
** ===================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
|
||||||
|
** (All uses in Lua have only one format item.)
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i)
|
||||||
|
#else
|
||||||
|
#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_strx2number converts a hexadecimal numeral to a number.
|
||||||
|
** In C99, 'strtod' does that conversion. Otherwise, you can
|
||||||
|
** leave 'lua_strx2number' undefined and Lua will provide its own
|
||||||
|
** implementation.
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
#define lua_strx2number(s,p) lua_str2number(s,p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_pointer2str converts a pointer to a readable string in a
|
||||||
|
** non-specified way.
|
||||||
|
*/
|
||||||
|
#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_number2strx converts a float to a hexadecimal numeral.
|
||||||
|
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
|
||||||
|
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
|
||||||
|
** provide its own implementation.
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
#define lua_number2strx(L,b,sz,f,n) \
|
||||||
|
((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 'strtof' and 'opf' variants for math functions are not valid in
|
||||||
|
** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
|
||||||
|
** availability of these variants. ('math.h' is already included in
|
||||||
|
** all files that use these macros.)
|
||||||
|
*/
|
||||||
|
#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
|
||||||
|
#undef l_mathop /* variants not available */
|
||||||
|
#undef lua_str2number
|
||||||
|
#define l_mathop(op) (lua_Number)op /* no variant */
|
||||||
|
#define lua_str2number(s,p) ((lua_Number)strtod((s), (p)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
|
||||||
|
** functions. It must be a numerical type; Lua will use 'intptr_t' if
|
||||||
|
** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
|
||||||
|
** 'intptr_t' in C89)
|
||||||
|
*/
|
||||||
|
#define LUA_KCONTEXT ptrdiff_t
|
||||||
|
|
||||||
|
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
|
||||||
|
__STDC_VERSION__ >= 199901L
|
||||||
|
#include <stdint.h>
|
||||||
|
#if defined(INTPTR_MAX) /* even in C99 this type is optional */
|
||||||
|
#undef LUA_KCONTEXT
|
||||||
|
#define LUA_KCONTEXT intptr_t
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
|
||||||
|
** Change that if you do not want to use C locales. (Code using this
|
||||||
|
** macro must include the header 'locale.h'.)
|
||||||
|
*/
|
||||||
|
#if !defined(lua_getlocaledecpoint)
|
||||||
|
#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macros to improve jump prediction, used mostly for error handling
|
||||||
|
** and debug facilities. (Some macros in the Lua API use these macros.
|
||||||
|
** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your
|
||||||
|
** code.)
|
||||||
|
*/
|
||||||
|
#if !defined(luai_likely)
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(LUA_NOBUILTIN)
|
||||||
|
#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
|
||||||
|
#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
||||||
|
#else
|
||||||
|
#define luai_likely(x) (x)
|
||||||
|
#define luai_unlikely(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_CORE) || defined(LUA_LIB)
|
||||||
|
/* shorter names for Lua's own use */
|
||||||
|
#define l_likely(x) luai_likely(x)
|
||||||
|
#define l_unlikely(x) luai_unlikely(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Language Variations
|
||||||
|
** =====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
|
||||||
|
** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
|
||||||
|
** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
|
||||||
|
** coercion from strings to numbers.
|
||||||
|
*/
|
||||||
|
/* #define LUA_NOCVTN2S */
|
||||||
|
/* #define LUA_NOCVTS2N */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
|
||||||
|
** Define it as a help when debugging C code.
|
||||||
|
*/
|
||||||
|
#if defined(LUA_USE_APICHECK)
|
||||||
|
#include <assert.h>
|
||||||
|
#define luai_apicheck(l,e) assert(e)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {==================================================================
|
||||||
|
** Macros that affect the API and must be stable (that is, must be the
|
||||||
|
** same when you compile Lua and when you compile code that links to
|
||||||
|
** Lua).
|
||||||
|
** =====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ 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).
|
||||||
|
** (It must fit into max(size_t)/32.)
|
||||||
|
*/
|
||||||
|
#if LUAI_IS32INT
|
||||||
|
#define LUAI_MAXSTACK 1000000
|
||||||
|
#else
|
||||||
|
#define LUAI_MAXSTACK 15000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
|
||||||
|
** a Lua state with very fast access.
|
||||||
|
** CHANGE it if you need a different size.
|
||||||
|
*/
|
||||||
|
#define LUA_EXTRASPACE (sizeof(void *))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ 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
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
|
||||||
|
*/
|
||||||
|
#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number)))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
|
||||||
|
** maximum alignment for the other items in that union.
|
||||||
|
*/
|
||||||
|
#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l
|
||||||
|
|
||||||
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* =================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Local configuration. You can use this space to add your redefinitions
|
||||||
|
** without modifying the main part of the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
** $Id: lualib.h $
|
||||||
|
** Lua standard libraries
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef lualib_h
|
||||||
|
#define lualib_h
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* version suffix for environment variable names */
|
||||||
|
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||||
|
|
||||||
|
|
||||||
|
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_UTF8LIBNAME "utf8"
|
||||||
|
LUAMOD_API int (luaopen_utf8) (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);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
** $Id: lundump.h $
|
||||||
|
** load precompiled Lua chunks
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lundump_h
|
||||||
|
#define lundump_h
|
||||||
|
|
||||||
|
#include "llimits.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lzio.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* data to catch conversion errors */
|
||||||
|
#define LUAC_DATA "\x19\x93\r\n\x1a\n"
|
||||||
|
|
||||||
|
#define LUAC_INT 0x5678
|
||||||
|
#define LUAC_NUM cast_num(370.5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Encode major-minor version in one byte, one nibble for each
|
||||||
|
*/
|
||||||
|
#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */
|
||||||
|
#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
|
||||||
|
|
||||||
|
#define LUAC_FORMAT 0 /* this is the official format */
|
||||||
|
|
||||||
|
/* load one chunk; from lundump.c */
|
||||||
|
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
|
||||||
|
|
||||||
|
/* dump one chunk; from ldump.c */
|
||||||
|
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
|
||||||
|
void* data, int strip);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
** $Id: lvm.h $
|
||||||
|
** Lua virtual machine
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lvm_h
|
||||||
|
#define lvm_h
|
||||||
|
|
||||||
|
|
||||||
|
#include "ldo.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "ltm.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(LUA_NOCVTN2S)
|
||||||
|
#define cvt2str(o) ttisnumber(o)
|
||||||
|
#else
|
||||||
|
#define cvt2str(o) 0 /* no conversion from numbers to strings */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(LUA_NOCVTS2N)
|
||||||
|
#define cvt2num(o) ttisstring(o)
|
||||||
|
#else
|
||||||
|
#define cvt2num(o) 0 /* no conversion from strings to numbers */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** You can define LUA_FLOORN2I if you want to convert floats to integers
|
||||||
|
** by flooring them (instead of raising an error if they are not
|
||||||
|
** integral values)
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_FLOORN2I)
|
||||||
|
#define LUA_FLOORN2I F2Ieq
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Rounding modes for float->integer coercion
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
F2Ieq, /* no rounding; accepts only integral values */
|
||||||
|
F2Ifloor, /* takes the floor of the number */
|
||||||
|
F2Iceil /* takes the ceil of the number */
|
||||||
|
} F2Imod;
|
||||||
|
|
||||||
|
|
||||||
|
/* convert an object to a float (including string coercion) */
|
||||||
|
#define tonumber(o,n) \
|
||||||
|
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
|
||||||
|
|
||||||
|
|
||||||
|
/* convert an object to a float (without string coercion) */
|
||||||
|
#define tonumberns(o,n) \
|
||||||
|
(ttisfloat(o) ? ((n) = fltvalue(o), 1) : \
|
||||||
|
(ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0))
|
||||||
|
|
||||||
|
|
||||||
|
/* convert an object to an integer (including string coercion) */
|
||||||
|
#define tointeger(o,i) \
|
||||||
|
(l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
|
||||||
|
: luaV_tointeger(o,i,LUA_FLOORN2I))
|
||||||
|
|
||||||
|
|
||||||
|
/* convert an object to an integer (without string coercion) */
|
||||||
|
#define tointegerns(o,i) \
|
||||||
|
(l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
|
||||||
|
: luaV_tointegerns(o,i,LUA_FLOORN2I))
|
||||||
|
|
||||||
|
|
||||||
|
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
|
||||||
|
|
||||||
|
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** fast track for 'gettable': if 't' is a table and 't[k]' is present,
|
||||||
|
** return 1 with 'slot' pointing to 't[k]' (position of final result).
|
||||||
|
** Otherwise, return 0 (meaning it will have to check metamethod)
|
||||||
|
** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL
|
||||||
|
** (otherwise). 'f' is the raw get function to use.
|
||||||
|
*/
|
||||||
|
#define luaV_fastget(L,t,k,slot,f) \
|
||||||
|
(!ttistable(t) \
|
||||||
|
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||||
|
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
||||||
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Special case of 'luaV_fastget' for integers, inlining the fast case
|
||||||
|
** of 'luaH_getint'.
|
||||||
|
*/
|
||||||
|
#define luaV_fastgeti(L,t,k,slot) \
|
||||||
|
(!ttistable(t) \
|
||||||
|
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||||
|
: (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \
|
||||||
|
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
||||||
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Finish a fast set operation (when fast get succeeds). In that case,
|
||||||
|
** 'slot' points to the place to put the value.
|
||||||
|
*/
|
||||||
|
#define luaV_finishfastset(L,t,slot,v) \
|
||||||
|
{ setobj2t(L, cast(TValue *,slot), v); \
|
||||||
|
luaC_barrierback(L, gcvalue(t), v); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
||||||
|
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
|
||||||
|
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
|
||||||
|
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
||||||
|
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode);
|
||||||
|
LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
|
||||||
|
F2Imod mode);
|
||||||
|
LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
|
||||||
|
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
|
||||||
|
StkId val, const TValue *slot);
|
||||||
|
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||||
|
TValue *val, const TValue *slot);
|
||||||
|
LUAI_FUNC void luaV_finishOp (lua_State *L);
|
||||||
|
LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
|
||||||
|
LUAI_FUNC void luaV_concat (lua_State *L, int total);
|
||||||
|
LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y);
|
||||||
|
LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
|
||||||
|
LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
|
||||||
|
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
|
||||||
|
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
** $Id: lzio.h $
|
||||||
|
** 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_buffremove(buff,i) ((buff)->n -= (i))
|
||||||
|
#define luaZ_resetbuffer(buff) ((buff)->n = 0)
|
||||||
|
|
||||||
|
|
||||||
|
#define luaZ_resizebuffer(L, buff, size) \
|
||||||
|
((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \
|
||||||
|
(buff)->buffsize, size), \
|
||||||
|
(buff)->buffsize = size)
|
||||||
|
|
||||||
|
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
Binary file not shown.
|
@ -0,0 +1,25 @@
|
||||||
|
local Client = class('Client')
|
||||||
|
|
||||||
|
freekill.client_callback = {}
|
||||||
|
|
||||||
|
function Client:initialize()
|
||||||
|
self.client = freekill.ClientInstance
|
||||||
|
self.notifyUI = function(self, command, json_data)
|
||||||
|
freekill.Backend:emitNotifyUI(command, json_data)
|
||||||
|
end
|
||||||
|
self.client.callback = function(_self, command, json_data)
|
||||||
|
local cb = freekill.client_callback[command]
|
||||||
|
if (type(cb) == "function") then
|
||||||
|
cb(json_data)
|
||||||
|
else
|
||||||
|
self:notifyUI("error_msg", "Unknown command " .. command);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
freekill.client_callback["enter_lobby"] = function(json_data)
|
||||||
|
ClientInstance:notifyUI("enter_lobby", json_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create ClientInstance (used by Lua)
|
||||||
|
ClientInstance = Client:new()
|
|
@ -0,0 +1,52 @@
|
||||||
|
-- class Card : public Object
|
||||||
|
local Card = class('Card')
|
||||||
|
|
||||||
|
-- public:
|
||||||
|
|
||||||
|
-- enum Suit
|
||||||
|
Card.Suit = {
|
||||||
|
Spade = 0,
|
||||||
|
Club = 1,
|
||||||
|
Heart = 2,
|
||||||
|
Diamond = 3,
|
||||||
|
NoSuitBlack = 4,
|
||||||
|
NoSuitRed = 5,
|
||||||
|
NoSuit = 6,
|
||||||
|
SuitToBeDecided = -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- enum Color
|
||||||
|
Card.Color = {
|
||||||
|
Red = 0,
|
||||||
|
Black = 1,
|
||||||
|
Colorless = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- enum HandlingMethod
|
||||||
|
Card.HandlingMethod = {
|
||||||
|
MethodNone = 0,
|
||||||
|
MethodUse = 1,
|
||||||
|
MethodResponse = 2,
|
||||||
|
MethodDiscard = 3,
|
||||||
|
MethodRecast = 4,
|
||||||
|
MethodPindian = 5,
|
||||||
|
}
|
||||||
|
function Card:initialize(suit, number)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- private:
|
||||||
|
local subcards = {} -- array of cards
|
||||||
|
local target_fixed
|
||||||
|
local mute
|
||||||
|
local will_throw
|
||||||
|
local has_preact
|
||||||
|
local can_recast
|
||||||
|
local m_suit
|
||||||
|
local m_number
|
||||||
|
local id
|
||||||
|
local skill_name
|
||||||
|
local handling_method
|
||||||
|
local flags = {}
|
||||||
|
|
||||||
|
return Card
|
|
@ -0,0 +1,16 @@
|
||||||
|
-- Fundemental script for FreeKill
|
||||||
|
-- Load mods, init the engine, etc.
|
||||||
|
|
||||||
|
package.path = package.path .. ';./lua/lib/?.lua'
|
||||||
|
|
||||||
|
-- load libraries
|
||||||
|
class = require 'middleclass'
|
||||||
|
json = require 'json'
|
||||||
|
|
||||||
|
function pt(t)
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
print(k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- load core classes
|
|
@ -0,0 +1,388 @@
|
||||||
|
--
|
||||||
|
-- json.lua
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2020 rxi
|
||||||
|
--
|
||||||
|
-- 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 json = { _version = "0.1.2" }
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Encode
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local encode
|
||||||
|
|
||||||
|
local escape_char_map = {
|
||||||
|
[ "\\" ] = "\\",
|
||||||
|
[ "\"" ] = "\"",
|
||||||
|
[ "\b" ] = "b",
|
||||||
|
[ "\f" ] = "f",
|
||||||
|
[ "\n" ] = "n",
|
||||||
|
[ "\r" ] = "r",
|
||||||
|
[ "\t" ] = "t",
|
||||||
|
}
|
||||||
|
|
||||||
|
local escape_char_map_inv = { [ "/" ] = "/" }
|
||||||
|
for k, v in pairs(escape_char_map) do
|
||||||
|
escape_char_map_inv[v] = k
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function escape_char(c)
|
||||||
|
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_nil(val)
|
||||||
|
return "null"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_table(val, stack)
|
||||||
|
local res = {}
|
||||||
|
stack = stack or {}
|
||||||
|
|
||||||
|
-- Circular reference?
|
||||||
|
if stack[val] then error("circular reference") end
|
||||||
|
|
||||||
|
stack[val] = true
|
||||||
|
|
||||||
|
if rawget(val, 1) ~= nil or next(val) == nil then
|
||||||
|
-- Treat as array -- check keys are valid and it is not sparse
|
||||||
|
local n = 0
|
||||||
|
for k in pairs(val) do
|
||||||
|
if type(k) ~= "number" then
|
||||||
|
error("invalid table: mixed or invalid key types")
|
||||||
|
end
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
if n ~= #val then
|
||||||
|
error("invalid table: sparse array")
|
||||||
|
end
|
||||||
|
-- Encode
|
||||||
|
for i, v in ipairs(val) do
|
||||||
|
table.insert(res, encode(v, stack))
|
||||||
|
end
|
||||||
|
stack[val] = nil
|
||||||
|
return "[" .. table.concat(res, ",") .. "]"
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Treat as an object
|
||||||
|
for k, v in pairs(val) do
|
||||||
|
if type(k) ~= "string" then
|
||||||
|
error("invalid table: mixed or invalid key types")
|
||||||
|
end
|
||||||
|
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
||||||
|
end
|
||||||
|
stack[val] = nil
|
||||||
|
return "{" .. table.concat(res, ",") .. "}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_string(val)
|
||||||
|
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_number(val)
|
||||||
|
-- Check for NaN, -inf and inf
|
||||||
|
if val ~= val or val <= -math.huge or val >= math.huge then
|
||||||
|
error("unexpected number value '" .. tostring(val) .. "'")
|
||||||
|
end
|
||||||
|
return string.format("%.14g", val)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local type_func_map = {
|
||||||
|
[ "nil" ] = encode_nil,
|
||||||
|
[ "table" ] = encode_table,
|
||||||
|
[ "string" ] = encode_string,
|
||||||
|
[ "number" ] = encode_number,
|
||||||
|
[ "boolean" ] = tostring,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encode = function(val, stack)
|
||||||
|
local t = type(val)
|
||||||
|
local f = type_func_map[t]
|
||||||
|
if f then
|
||||||
|
return f(val, stack)
|
||||||
|
end
|
||||||
|
error("unexpected type '" .. t .. "'")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function json.encode(val)
|
||||||
|
return ( encode(val) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Decode
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local parse
|
||||||
|
|
||||||
|
local function create_set(...)
|
||||||
|
local res = {}
|
||||||
|
for i = 1, select("#", ...) do
|
||||||
|
res[ select(i, ...) ] = true
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
local space_chars = create_set(" ", "\t", "\r", "\n")
|
||||||
|
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
||||||
|
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
||||||
|
local literals = create_set("true", "false", "null")
|
||||||
|
|
||||||
|
local literal_map = {
|
||||||
|
[ "true" ] = true,
|
||||||
|
[ "false" ] = false,
|
||||||
|
[ "null" ] = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local function next_char(str, idx, set, negate)
|
||||||
|
for i = idx, #str do
|
||||||
|
if set[str:sub(i, i)] ~= negate then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return #str + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function decode_error(str, idx, msg)
|
||||||
|
local line_count = 1
|
||||||
|
local col_count = 1
|
||||||
|
for i = 1, idx - 1 do
|
||||||
|
col_count = col_count + 1
|
||||||
|
if str:sub(i, i) == "\n" then
|
||||||
|
line_count = line_count + 1
|
||||||
|
col_count = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function codepoint_to_utf8(n)
|
||||||
|
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
||||||
|
local f = math.floor
|
||||||
|
if n <= 0x7f then
|
||||||
|
return string.char(n)
|
||||||
|
elseif n <= 0x7ff then
|
||||||
|
return string.char(f(n / 64) + 192, n % 64 + 128)
|
||||||
|
elseif n <= 0xffff then
|
||||||
|
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||||
|
elseif n <= 0x10ffff then
|
||||||
|
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
||||||
|
f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||||
|
end
|
||||||
|
error( string.format("invalid unicode codepoint '%x'", n) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_unicode_escape(s)
|
||||||
|
local n1 = tonumber( s:sub(1, 4), 16 )
|
||||||
|
local n2 = tonumber( s:sub(7, 10), 16 )
|
||||||
|
-- Surrogate pair?
|
||||||
|
if n2 then
|
||||||
|
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
||||||
|
else
|
||||||
|
return codepoint_to_utf8(n1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_string(str, i)
|
||||||
|
local res = ""
|
||||||
|
local j = i + 1
|
||||||
|
local k = j
|
||||||
|
|
||||||
|
while j <= #str do
|
||||||
|
local x = str:byte(j)
|
||||||
|
|
||||||
|
if x < 32 then
|
||||||
|
decode_error(str, j, "control character in string")
|
||||||
|
|
||||||
|
elseif x == 92 then -- `\`: Escape
|
||||||
|
res = res .. str:sub(k, j - 1)
|
||||||
|
j = j + 1
|
||||||
|
local c = str:sub(j, j)
|
||||||
|
if c == "u" then
|
||||||
|
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
|
||||||
|
or str:match("^%x%x%x%x", j + 1)
|
||||||
|
or decode_error(str, j - 1, "invalid unicode escape in string")
|
||||||
|
res = res .. parse_unicode_escape(hex)
|
||||||
|
j = j + #hex
|
||||||
|
else
|
||||||
|
if not escape_chars[c] then
|
||||||
|
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
|
||||||
|
end
|
||||||
|
res = res .. escape_char_map_inv[c]
|
||||||
|
end
|
||||||
|
k = j + 1
|
||||||
|
|
||||||
|
elseif x == 34 then -- `"`: End of string
|
||||||
|
res = res .. str:sub(k, j - 1)
|
||||||
|
return res, j + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
decode_error(str, i, "expected closing quote for string")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_number(str, i)
|
||||||
|
local x = next_char(str, i, delim_chars)
|
||||||
|
local s = str:sub(i, x - 1)
|
||||||
|
local n = tonumber(s)
|
||||||
|
if not n then
|
||||||
|
decode_error(str, i, "invalid number '" .. s .. "'")
|
||||||
|
end
|
||||||
|
return n, x
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_literal(str, i)
|
||||||
|
local x = next_char(str, i, delim_chars)
|
||||||
|
local word = str:sub(i, x - 1)
|
||||||
|
if not literals[word] then
|
||||||
|
decode_error(str, i, "invalid literal '" .. word .. "'")
|
||||||
|
end
|
||||||
|
return literal_map[word], x
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_array(str, i)
|
||||||
|
local res = {}
|
||||||
|
local n = 1
|
||||||
|
i = i + 1
|
||||||
|
while 1 do
|
||||||
|
local x
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
-- Empty / end of array?
|
||||||
|
if str:sub(i, i) == "]" then
|
||||||
|
i = i + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Read token
|
||||||
|
x, i = parse(str, i)
|
||||||
|
res[n] = x
|
||||||
|
n = n + 1
|
||||||
|
-- Next token
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
local chr = str:sub(i, i)
|
||||||
|
i = i + 1
|
||||||
|
if chr == "]" then break end
|
||||||
|
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
||||||
|
end
|
||||||
|
return res, i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_object(str, i)
|
||||||
|
local res = {}
|
||||||
|
i = i + 1
|
||||||
|
while 1 do
|
||||||
|
local key, val
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
-- Empty / end of object?
|
||||||
|
if str:sub(i, i) == "}" then
|
||||||
|
i = i + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Read key
|
||||||
|
if str:sub(i, i) ~= '"' then
|
||||||
|
decode_error(str, i, "expected string for key")
|
||||||
|
end
|
||||||
|
key, i = parse(str, i)
|
||||||
|
-- Read ':' delimiter
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
if str:sub(i, i) ~= ":" then
|
||||||
|
decode_error(str, i, "expected ':' after key")
|
||||||
|
end
|
||||||
|
i = next_char(str, i + 1, space_chars, true)
|
||||||
|
-- Read value
|
||||||
|
val, i = parse(str, i)
|
||||||
|
-- Set
|
||||||
|
res[key] = val
|
||||||
|
-- Next token
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
local chr = str:sub(i, i)
|
||||||
|
i = i + 1
|
||||||
|
if chr == "}" then break end
|
||||||
|
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
||||||
|
end
|
||||||
|
return res, i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local char_func_map = {
|
||||||
|
[ '"' ] = parse_string,
|
||||||
|
[ "0" ] = parse_number,
|
||||||
|
[ "1" ] = parse_number,
|
||||||
|
[ "2" ] = parse_number,
|
||||||
|
[ "3" ] = parse_number,
|
||||||
|
[ "4" ] = parse_number,
|
||||||
|
[ "5" ] = parse_number,
|
||||||
|
[ "6" ] = parse_number,
|
||||||
|
[ "7" ] = parse_number,
|
||||||
|
[ "8" ] = parse_number,
|
||||||
|
[ "9" ] = parse_number,
|
||||||
|
[ "-" ] = parse_number,
|
||||||
|
[ "t" ] = parse_literal,
|
||||||
|
[ "f" ] = parse_literal,
|
||||||
|
[ "n" ] = parse_literal,
|
||||||
|
[ "[" ] = parse_array,
|
||||||
|
[ "{" ] = parse_object,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
parse = function(str, idx)
|
||||||
|
local chr = str:sub(idx, idx)
|
||||||
|
local f = char_func_map[chr]
|
||||||
|
if f then
|
||||||
|
return f(str, idx)
|
||||||
|
end
|
||||||
|
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function json.decode(str)
|
||||||
|
if type(str) ~= "string" then
|
||||||
|
error("expected argument of type string, got " .. type(str))
|
||||||
|
end
|
||||||
|
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
||||||
|
idx = next_char(str, idx, space_chars, true)
|
||||||
|
if idx <= #str then
|
||||||
|
decode_error(str, idx, "trailing garbage")
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return json
|
|
@ -0,0 +1,189 @@
|
||||||
|
local middleclass = {
|
||||||
|
_VERSION = 'middleclass v4.1.1',
|
||||||
|
_DESCRIPTION = 'Object Orientation for Lua',
|
||||||
|
_URL = 'https://github.com/kikito/middleclass',
|
||||||
|
_LICENSE = [[
|
||||||
|
MIT LICENSE
|
||||||
|
Copyright (c) 2011 Enrique García Cota
|
||||||
|
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 function _createIndexWrapper(aClass, f)
|
||||||
|
if f == nil then
|
||||||
|
return aClass.__instanceDict
|
||||||
|
elseif type(f) == "function" then
|
||||||
|
return function(self, name)
|
||||||
|
local value = aClass.__instanceDict[name]
|
||||||
|
|
||||||
|
if value ~= nil then
|
||||||
|
return value
|
||||||
|
else
|
||||||
|
return (f(self, name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else -- if type(f) == "table" then
|
||||||
|
return function(self, name)
|
||||||
|
local value = aClass.__instanceDict[name]
|
||||||
|
|
||||||
|
if value ~= nil then
|
||||||
|
return value
|
||||||
|
else
|
||||||
|
return f[name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _propagateInstanceMethod(aClass, name, f)
|
||||||
|
f = name == "__index" and _createIndexWrapper(aClass, f) or f
|
||||||
|
aClass.__instanceDict[name] = f
|
||||||
|
|
||||||
|
for subclass in pairs(aClass.subclasses) do
|
||||||
|
if rawget(subclass.__declaredMethods, name) == nil then
|
||||||
|
_propagateInstanceMethod(subclass, name, f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _declareInstanceMethod(aClass, name, f)
|
||||||
|
aClass.__declaredMethods[name] = f
|
||||||
|
|
||||||
|
if f == nil and aClass.super then
|
||||||
|
f = aClass.super.__instanceDict[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
_propagateInstanceMethod(aClass, name, f)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _tostring(self) return "class " .. self.name end
|
||||||
|
local function _call(self, ...) return self:new(...) end
|
||||||
|
|
||||||
|
local function _createClass(name, super)
|
||||||
|
local dict = {}
|
||||||
|
dict.__index = dict
|
||||||
|
|
||||||
|
local aClass = { name = name, super = super, static = {},
|
||||||
|
__instanceDict = dict, __declaredMethods = {},
|
||||||
|
subclasses = setmetatable({}, {__mode='k'}) }
|
||||||
|
|
||||||
|
if super then
|
||||||
|
setmetatable(aClass.static, {
|
||||||
|
__index = function(_,k)
|
||||||
|
local result = rawget(dict,k)
|
||||||
|
if result == nil then
|
||||||
|
return super.static[k]
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
})
|
||||||
|
else
|
||||||
|
setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) end })
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(aClass, { __index = aClass.static, __tostring = _tostring,
|
||||||
|
__call = _call, __newindex = _declareInstanceMethod })
|
||||||
|
|
||||||
|
return aClass
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _includeMixin(aClass, mixin)
|
||||||
|
assert(type(mixin) == 'table', "mixin must be a table")
|
||||||
|
|
||||||
|
for name,method in pairs(mixin) do
|
||||||
|
if name ~= "included" and name ~= "static" then aClass[name] = method end
|
||||||
|
end
|
||||||
|
|
||||||
|
for name,method in pairs(mixin.static or {}) do
|
||||||
|
aClass.static[name] = method
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(mixin.included)=="function" then mixin:included(aClass) end
|
||||||
|
return aClass
|
||||||
|
end
|
||||||
|
|
||||||
|
local DefaultMixin = {
|
||||||
|
__tostring = function(self) return "instance of " .. tostring(self.class) end,
|
||||||
|
|
||||||
|
initialize = function(self, ...) end,
|
||||||
|
|
||||||
|
isInstanceOf = function(self, aClass)
|
||||||
|
return type(aClass) == 'table'
|
||||||
|
and type(self) == 'table'
|
||||||
|
and (self.class == aClass
|
||||||
|
or type(self.class) == 'table'
|
||||||
|
and type(self.class.isSubclassOf) == 'function'
|
||||||
|
and self.class:isSubclassOf(aClass))
|
||||||
|
end,
|
||||||
|
|
||||||
|
static = {
|
||||||
|
allocate = function(self)
|
||||||
|
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
||||||
|
return setmetatable({ class = self }, self.__instanceDict)
|
||||||
|
end,
|
||||||
|
|
||||||
|
new = function(self, ...)
|
||||||
|
assert(type(self) == 'table', "Make sure that you are using 'Class:new' instead of 'Class.new'")
|
||||||
|
local instance = self:allocate()
|
||||||
|
instance:initialize(...)
|
||||||
|
return instance
|
||||||
|
end,
|
||||||
|
|
||||||
|
subclass = function(self, name)
|
||||||
|
assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
|
||||||
|
assert(type(name) == "string", "You must provide a name(string) for your class")
|
||||||
|
|
||||||
|
local subclass = _createClass(name, self)
|
||||||
|
|
||||||
|
for methodName, f in pairs(self.__instanceDict) do
|
||||||
|
if not (methodName == "__index" and type(f) == "table") then
|
||||||
|
_propagateInstanceMethod(subclass, methodName, f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
subclass.initialize = function(instance, ...) return self.initialize(instance, ...) end
|
||||||
|
|
||||||
|
self.subclasses[subclass] = true
|
||||||
|
self:subclassed(subclass)
|
||||||
|
|
||||||
|
return subclass
|
||||||
|
end,
|
||||||
|
|
||||||
|
subclassed = function(self, other) end,
|
||||||
|
|
||||||
|
isSubclassOf = function(self, other)
|
||||||
|
return type(other) == 'table' and
|
||||||
|
type(self.super) == 'table' and
|
||||||
|
( self.super == other or self.super:isSubclassOf(other) )
|
||||||
|
end,
|
||||||
|
|
||||||
|
include = function(self, ...)
|
||||||
|
assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
|
||||||
|
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function middleclass.class(name, super)
|
||||||
|
assert(type(name) == 'string', "A name (string) is needed for the new class")
|
||||||
|
return super and super:subclass(name) or _includeMixin(_createClass(name), DefaultMixin)
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
|
||||||
|
|
||||||
|
return middleclass
|
|
@ -0,0 +1,26 @@
|
||||||
|
local Server = class('Server')
|
||||||
|
|
||||||
|
freekill.server_callback = {}
|
||||||
|
|
||||||
|
function Server:initialize()
|
||||||
|
self.server = freekill.ServerInstance
|
||||||
|
self.server.callback = function(_self, command, json_data)
|
||||||
|
local cb = freekill.server_callback[command]
|
||||||
|
if (type(cb) == "function") then
|
||||||
|
cb(json_data)
|
||||||
|
else
|
||||||
|
print("Server error: Unknown command " .. command);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
freekill.server_callback["create_room"] = function(json_data)
|
||||||
|
-- json_data: [ int id, string name, int capacity ]
|
||||||
|
local data = json.decode(json_data)
|
||||||
|
local owner = freekill.ServerInstance:findPlayer(data[1])
|
||||||
|
local roomName = data[2]
|
||||||
|
local capacity = data[3]
|
||||||
|
freekill.ServerInstance:createRoom(owner, roomName, capacity)
|
||||||
|
end
|
||||||
|
|
||||||
|
ServerInstance = Server:new()
|
|
@ -0,0 +1,39 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
id: join_server
|
||||||
|
anchors.centerIn: parent
|
||||||
|
Column {
|
||||||
|
spacing: 8
|
||||||
|
TextField {
|
||||||
|
id: server_addr
|
||||||
|
text: "127.0.0.1"
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
text: "player"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Join Server"
|
||||||
|
onClicked: {
|
||||||
|
mainWindow.state = "busy";
|
||||||
|
mainWindow.busyString = "Connecting to host...";
|
||||||
|
Backend.joinServer(server_addr.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Console start"
|
||||||
|
onClicked: {
|
||||||
|
mainWindow.state = "busy";
|
||||||
|
mainWindow.busyString = "Connecting to host...";
|
||||||
|
Backend.startServer(9527);
|
||||||
|
Backend.joinServer("127.0.0.1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
width: 640; height: 480
|
||||||
|
Component {
|
||||||
|
id: roomDelegate
|
||||||
|
|
||||||
|
Row {
|
||||||
|
spacing: 24
|
||||||
|
Text {
|
||||||
|
width: 40
|
||||||
|
text: String(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: 40
|
||||||
|
text: roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: 20
|
||||||
|
text: gameMode
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: 10
|
||||||
|
color: (playerNum == capacity) ? "red" : "black"
|
||||||
|
text: String(playerNum) + "/" + String(capacity)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Enter"
|
||||||
|
font.underline: true
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: { parent.color = "blue" }
|
||||||
|
onExited: { parent.color = "black" }
|
||||||
|
onClicked: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: roomModel
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
width: root.width * 0.7
|
||||||
|
height: root.height
|
||||||
|
color: "#e2e2e1"
|
||||||
|
radius: 4
|
||||||
|
Text {
|
||||||
|
text: "Room List"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
height: parent.height * 0.9
|
||||||
|
width: parent.width * 0.95
|
||||||
|
anchors.centerIn: parent
|
||||||
|
id: roomList
|
||||||
|
delegate: roomDelegate
|
||||||
|
model: roomModel
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: scrollbar
|
||||||
|
anchors.right: roomList.right
|
||||||
|
y: roomList.visibleArea.yPosition * roomList.height
|
||||||
|
width: 10
|
||||||
|
radius: 4
|
||||||
|
height: roomList.visibleArea.heightRatio * roomList.height
|
||||||
|
color: "#a89da8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Text {
|
||||||
|
text: "Avatar"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Create Room"
|
||||||
|
onClicked: {}
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Generals Overview"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Cards Overview"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Scenarios Overview"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "About"
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Exit Lobby"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
// toast.show("Welcome to FreeKill lobby!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: mainWindow
|
||||||
|
visible: true
|
||||||
|
width: 720
|
||||||
|
height: 480
|
||||||
|
property var callbacks: ({
|
||||||
|
"error_msg": function(json_data) {
|
||||||
|
toast.show(json_data);
|
||||||
|
if (mainWindow.state === "busy")
|
||||||
|
mainWindow.state = "init";
|
||||||
|
},
|
||||||
|
"enter_lobby": function(json_data) {
|
||||||
|
mainWindow.state = "lobby";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: mainLoader
|
||||||
|
source: "Page/Init.qml"
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
property string state: "init"
|
||||||
|
|
||||||
|
onStateChanged: {
|
||||||
|
switch (state) {
|
||||||
|
case "init":
|
||||||
|
mainLoader.source = "Page/Init.qml";
|
||||||
|
break;
|
||||||
|
case "lobby":
|
||||||
|
mainLoader.source = "Page/Lobby.qml";
|
||||||
|
break;
|
||||||
|
case "room":
|
||||||
|
mainLoader.source = "Page/Room.qml";
|
||||||
|
break;
|
||||||
|
case "busy":
|
||||||
|
mainLoader.source = "";
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property string busyString: "Busy"
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
running: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: mainWindow.state === "busy"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: toast
|
||||||
|
opacity: 0
|
||||||
|
z: 998
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
y: parent.height * 0.8
|
||||||
|
radius: 16
|
||||||
|
color: "#F2808A87"
|
||||||
|
height: toast_text.height + 20
|
||||||
|
width: toast_text.width + 40
|
||||||
|
Text {
|
||||||
|
id: toast_text
|
||||||
|
text: "FreeKill"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 240
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SequentialAnimation {
|
||||||
|
id: keepAnim
|
||||||
|
running: toast.opacity == 1
|
||||||
|
PauseAnimation {
|
||||||
|
duration: 2800
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptAction {
|
||||||
|
script: {
|
||||||
|
toast.opacity = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show(text) {
|
||||||
|
opacity = 1
|
||||||
|
toast_text.text = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Backend
|
||||||
|
function onNotifyUI(command, json_data) {
|
||||||
|
let cb = callbacks[command]
|
||||||
|
if (typeof(cb) === "function") {
|
||||||
|
cb(json_data);
|
||||||
|
} else {
|
||||||
|
callbacks["error_msg"]("Unknown UI command " + command + "!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
set(freekill_SRCS
|
||||||
|
"main.cpp"
|
||||||
|
"core/player.cpp"
|
||||||
|
"core/global.cpp"
|
||||||
|
"network/server_socket.cpp"
|
||||||
|
"network/client_socket.cpp"
|
||||||
|
"network/router.cpp"
|
||||||
|
"server/server.cpp"
|
||||||
|
"server/serverplayer.cpp"
|
||||||
|
"server/room.cpp"
|
||||||
|
"server/gamelogic.cpp"
|
||||||
|
"client/client.cpp"
|
||||||
|
"client/clientplayer.cpp"
|
||||||
|
"ui/qmlbackend.cpp"
|
||||||
|
"swig/freekill-wrap.cxx"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(freekill_HEADERS
|
||||||
|
"core/global.h"
|
||||||
|
"core/player.h"
|
||||||
|
"network/server_socket.h"
|
||||||
|
"network/client_socket.h"
|
||||||
|
"network/router.h"
|
||||||
|
"server/server.h"
|
||||||
|
"server/serverplayer.h"
|
||||||
|
"server/room.h"
|
||||||
|
"server/gamelogic.h"
|
||||||
|
"client/client.h"
|
||||||
|
"client/clientplayer.h"
|
||||||
|
"ui/qmlbackend.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/win/lua54.dll)
|
||||||
|
else ()
|
||||||
|
set(LUA_LIB lua5.4)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
source_group("Include" FILES ${freekill_HEADERS})
|
||||||
|
add_executable(FreeKill ${freekill_SRCS})
|
||||||
|
target_link_libraries(FreeKill ${LUA_LIB} Qt5::Qml Qt5::Gui Qt5::Network Qt5::Multimedia)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${PROJECT_SOURCE_DIR}/src/swig/freekill-wrap.cxx
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/src/swig/freekill.i
|
||||||
|
COMMENT "Generating freekill-wrap.cxx"
|
||||||
|
COMMAND swig -c++ -lua -Wall -o
|
||||||
|
${PROJECT_SOURCE_DIR}/src/swig/freekill-wrap.cxx
|
||||||
|
${PROJECT_SOURCE_DIR}/src/swig/freekill.i
|
||||||
|
)
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "client.h"
|
||||||
|
#include "client_socket.h"
|
||||||
|
#include "clientplayer.h"
|
||||||
|
|
||||||
|
Client *ClientInstance;
|
||||||
|
ClientPlayer *Self;
|
||||||
|
|
||||||
|
Client::Client(QObject* parent)
|
||||||
|
: QObject(parent), callback(0)
|
||||||
|
{
|
||||||
|
ClientInstance = this;
|
||||||
|
Self = nullptr;
|
||||||
|
|
||||||
|
ClientSocket *socket = new ClientSocket;
|
||||||
|
connect(socket, &ClientSocket::error_message, this, &Client::error_message);
|
||||||
|
router = new Router(this, socket, Router::TYPE_CLIENT);
|
||||||
|
|
||||||
|
L = CreateLuaState();
|
||||||
|
DoLuaScript(L, "lua/freekill.lua");
|
||||||
|
DoLuaScript(L, "lua/client/client.lua");
|
||||||
|
}
|
||||||
|
|
||||||
|
Client::~Client()
|
||||||
|
{
|
||||||
|
ClientInstance = nullptr;
|
||||||
|
router->getSocket()->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::connectToHost(const QHostAddress& server, ushort port)
|
||||||
|
{
|
||||||
|
router->getSocket()->connectToHost(server, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::requestServer(const QString& command, const QString& json_data, int timeout)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER;
|
||||||
|
router->request(type, command, json_data, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::replyToServer(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER;
|
||||||
|
router->reply(type, command, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::notifyServer(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER;
|
||||||
|
router->notify(type, command, json_data);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef _CLIENT_H
|
||||||
|
#define _CLIENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <lua.hpp>
|
||||||
|
#include "router.h"
|
||||||
|
#include "clientplayer.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
class Client : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Client(QObject *parent = nullptr);
|
||||||
|
~Client();
|
||||||
|
|
||||||
|
void connectToHost(const QHostAddress &server, ushort port);
|
||||||
|
|
||||||
|
// TODO: database of the server
|
||||||
|
// void signup
|
||||||
|
// void login
|
||||||
|
|
||||||
|
void requestServer(const QString &command,
|
||||||
|
const QString &json_data, int timeout = -1);
|
||||||
|
void replyToServer(const QString &command, const QString &json_data);
|
||||||
|
void notifyServer(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
void callLua(const QString &command, const QString &json_data);
|
||||||
|
LuaFunction callback;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void error_message(const QString &msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Router *router;
|
||||||
|
QMap<uint, ClientPlayer *> players;
|
||||||
|
|
||||||
|
lua_State *L;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Client *ClientInstance;
|
||||||
|
|
||||||
|
#endif // _CLIENT_H
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "clientplayer.h"
|
||||||
|
|
||||||
|
ClientPlayer::ClientPlayer(uint id, QObject* parent)
|
||||||
|
: Player(parent)
|
||||||
|
{
|
||||||
|
setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientPlayer::~ClientPlayer()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _CLIENTPLAYER_H
|
||||||
|
#define _CLIENTPLAYER_H
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
class ClientPlayer : public Player {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ClientPlayer(uint id, QObject *parent = nullptr);
|
||||||
|
~ClientPlayer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ClientPlayer *Self;
|
||||||
|
|
||||||
|
#endif // _CLIENTPLAYER_H
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int luaopen_freekill(lua_State *);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State *CreateLuaState()
|
||||||
|
{
|
||||||
|
lua_State *L = luaL_newstate();
|
||||||
|
luaL_openlibs(L);
|
||||||
|
luaopen_freekill(L);
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DoLuaScript(lua_State *L, const char *script)
|
||||||
|
{
|
||||||
|
int error = luaL_dofile(L, script);
|
||||||
|
if (error) {
|
||||||
|
QString error_msg = lua_tostring(L, -1);
|
||||||
|
qDebug() << error_msg;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef _GLOBAL_H
|
||||||
|
#define _GLOBAL_H
|
||||||
|
|
||||||
|
#include <lua.hpp>
|
||||||
|
|
||||||
|
// utilities
|
||||||
|
typedef int LuaFunction;
|
||||||
|
|
||||||
|
lua_State *CreateLuaState();
|
||||||
|
bool DoLuaScript(lua_State *L, const char *script);
|
||||||
|
|
||||||
|
#endif // _GLOBAL_H
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
Player::Player(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, id(0)
|
||||||
|
, state(Player::Invalid)
|
||||||
|
, ready(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Player::~Player()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Player::getId() const
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setId(uint id)
|
||||||
|
{
|
||||||
|
this->id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Player::getScreenName() const
|
||||||
|
{
|
||||||
|
return screenName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setScreenName(const QString& name)
|
||||||
|
{
|
||||||
|
this->screenName = name;
|
||||||
|
emit screenNameChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Player::getAvatar() const
|
||||||
|
{
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setAvatar(const QString& avatar)
|
||||||
|
{
|
||||||
|
this->avatar = avatar;
|
||||||
|
emit avatarChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
Player::State Player::getState() const
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Player::getStateString() const
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case Online:
|
||||||
|
return QStringLiteral("online");
|
||||||
|
case Trust:
|
||||||
|
return QStringLiteral("trust");
|
||||||
|
case Offline:
|
||||||
|
return QStringLiteral("offline");
|
||||||
|
default:
|
||||||
|
return QStringLiteral("invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setState(Player::State state)
|
||||||
|
{
|
||||||
|
this->state = state;
|
||||||
|
emit stateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setStateString(const QString &state)
|
||||||
|
{
|
||||||
|
if (state == QStringLiteral("online"))
|
||||||
|
setState(Online);
|
||||||
|
else if (state == QStringLiteral("trust"))
|
||||||
|
setState(Trust);
|
||||||
|
else if (state == QStringLiteral("offline"))
|
||||||
|
setState(Offline);
|
||||||
|
else
|
||||||
|
setState(Invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::isReady() const
|
||||||
|
{
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setReady(bool ready)
|
||||||
|
{
|
||||||
|
this->ready = ready;
|
||||||
|
emit readyChanged();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef _PLAYER_H
|
||||||
|
#define _PLAYER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
// Common part of ServerPlayer and ClientPlayer
|
||||||
|
// dont initialize it directly
|
||||||
|
class Player : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum State{
|
||||||
|
Invalid,
|
||||||
|
Online,
|
||||||
|
Trust,
|
||||||
|
Offline
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Player(QObject *parent = nullptr);
|
||||||
|
~Player();
|
||||||
|
|
||||||
|
uint getId() const;
|
||||||
|
void setId(uint id);
|
||||||
|
|
||||||
|
QString getScreenName() const;
|
||||||
|
void setScreenName(const QString &name);
|
||||||
|
|
||||||
|
QString getAvatar() const;
|
||||||
|
void setAvatar(const QString &avatar);
|
||||||
|
|
||||||
|
State getState() const;
|
||||||
|
QString getStateString() const;
|
||||||
|
void setState(State state);
|
||||||
|
void setStateString(const QString &state);
|
||||||
|
|
||||||
|
bool isReady() const;
|
||||||
|
void setReady(bool ready);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void screenNameChanged();
|
||||||
|
void avatarChanged();
|
||||||
|
void stateChanged();
|
||||||
|
void readyChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint id;
|
||||||
|
QString screenName;
|
||||||
|
QString avatar;
|
||||||
|
State state;
|
||||||
|
bool ready;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _PLAYER_H
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include "qmlbackend.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
QGuiApplication::setApplicationName("FreeKill");
|
||||||
|
QGuiApplication::setApplicationVersion("Alpha 0.0.1");
|
||||||
|
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription("FreeKill server");
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
parser.addOption({{"s", "server"}, "start server at <port>", "port"});
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
bool startServer = parser.isSet("server");
|
||||||
|
ushort serverPort = 9527;
|
||||||
|
|
||||||
|
if (startServer) {
|
||||||
|
bool ok = false;
|
||||||
|
if (parser.value("server").toInt(&ok) && ok)
|
||||||
|
serverPort = parser.value("server").toInt();
|
||||||
|
Server *server = new Server;
|
||||||
|
if (!server->listen(QHostAddress::Any, serverPort)) {
|
||||||
|
fprintf(stderr, "cannot listen on port %d!\n", serverPort);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
QmlBackend backend;
|
||||||
|
engine.rootContext()->setContextProperty("Backend", &backend);
|
||||||
|
engine.load("qml/main.qml");
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include "client_socket.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
ClientSocket::ClientSocket() : socket(new QTcpSocket(this))
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientSocket::ClientSocket(QTcpSocket* socket)
|
||||||
|
{
|
||||||
|
socket->setParent(this);
|
||||||
|
this->socket = socket;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::init()
|
||||||
|
{
|
||||||
|
connect(socket, &QTcpSocket::connected,
|
||||||
|
this, &ClientSocket::connected);
|
||||||
|
connect(socket, &QTcpSocket::disconnected,
|
||||||
|
this, &ClientSocket::disconnected);
|
||||||
|
connect(socket, &QTcpSocket::readyRead,
|
||||||
|
this, &ClientSocket::getMessage);
|
||||||
|
connect(socket, &QTcpSocket::errorOccurred,
|
||||||
|
this, &ClientSocket::raiseError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::connectToHost(const QHostAddress &address, ushort port)
|
||||||
|
{
|
||||||
|
socket->connectToHost(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::getMessage()
|
||||||
|
{
|
||||||
|
while (socket->canReadLine()) {
|
||||||
|
char msg[16000]; // buffer
|
||||||
|
socket->readLine(msg, sizeof(msg));
|
||||||
|
emit message_got(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::disconnectFromHost()
|
||||||
|
{
|
||||||
|
socket->disconnectFromHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::send(const QByteArray &msg)
|
||||||
|
{
|
||||||
|
socket->write(msg);
|
||||||
|
if (!msg.endsWith("\n"))
|
||||||
|
socket->write("\n");
|
||||||
|
socket->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientSocket::isConnected() const
|
||||||
|
{
|
||||||
|
return socket->state() == QTcpSocket::ConnectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ClientSocket::peerName() const
|
||||||
|
{
|
||||||
|
QString peer_name = socket->peerName();
|
||||||
|
if (peer_name.isEmpty())
|
||||||
|
peer_name = QString("%1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
|
|
||||||
|
return peer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ClientSocket::peerAddress() const
|
||||||
|
{
|
||||||
|
return socket->peerAddress().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientSocket::raiseError(QAbstractSocket::SocketError socket_error)
|
||||||
|
{
|
||||||
|
// translate error message
|
||||||
|
QString reason;
|
||||||
|
switch (socket_error) {
|
||||||
|
case QAbstractSocket::ConnectionRefusedError:
|
||||||
|
reason = tr("Connection was refused or timeout"); break;
|
||||||
|
case QAbstractSocket::RemoteHostClosedError:
|
||||||
|
reason = tr("Remote host close this connection"); break;
|
||||||
|
case QAbstractSocket::HostNotFoundError:
|
||||||
|
reason = tr("Host not found"); break;
|
||||||
|
case QAbstractSocket::SocketAccessError:
|
||||||
|
reason = tr("Socket access error"); break;
|
||||||
|
case QAbstractSocket::NetworkError:
|
||||||
|
return; // this error is ignored ...
|
||||||
|
default: reason = tr("Unknow error"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit error_message(tr("Connection failed, error code = %1\n reason:\n %2")
|
||||||
|
.arg(socket_error).arg(reason));
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef _CLIENT_SOCKET_H
|
||||||
|
#define _CLIENT_SOCKET_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
|
||||||
|
class ClientSocket : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClientSocket();
|
||||||
|
// For server use
|
||||||
|
ClientSocket(QTcpSocket *socket);
|
||||||
|
|
||||||
|
void connectToHost(const QHostAddress &address = QHostAddress::LocalHost, ushort port = 9527u);
|
||||||
|
void disconnectFromHost();
|
||||||
|
void send(const QByteArray& msg);
|
||||||
|
bool isConnected() const;
|
||||||
|
QString peerName() const;
|
||||||
|
QString peerAddress() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void message_got(const QByteArray& msg);
|
||||||
|
void error_message(const QString &msg);
|
||||||
|
void disconnected();
|
||||||
|
void connected();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void getMessage();
|
||||||
|
void raiseError(QAbstractSocket::SocketError error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpSocket *socket;
|
||||||
|
void init();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _CLIENT_SOCKET_H
|
|
@ -0,0 +1,196 @@
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include "router.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
this->type = type;
|
||||||
|
this->socket = nullptr;
|
||||||
|
setSocket(socket);
|
||||||
|
expectedReplyId = -1;
|
||||||
|
replyTimeout = 0;
|
||||||
|
extraReplyReadySemaphore = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Router::~Router()
|
||||||
|
{
|
||||||
|
abortRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientSocket* Router::getSocket() const
|
||||||
|
{
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::setSocket(ClientSocket *socket)
|
||||||
|
{
|
||||||
|
if (this->socket != nullptr) {
|
||||||
|
this->socket->disconnect(this);
|
||||||
|
disconnect(this->socket);
|
||||||
|
this->socket->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->socket = nullptr;
|
||||||
|
if (socket != nullptr) {
|
||||||
|
connect(this, &Router::messageReady, socket, &ClientSocket::send);
|
||||||
|
connect(socket, &ClientSocket::message_got, this, &Router::handlePacket);
|
||||||
|
connect(socket, &ClientSocket::disconnected, this, &Router::abortRequest);
|
||||||
|
socket->setParent(this);
|
||||||
|
this->socket = socket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::setReplyReadySemaphore(QSemaphore *semaphore)
|
||||||
|
{
|
||||||
|
extraReplyReadySemaphore = semaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::request(int type, const QString& command,
|
||||||
|
const QString& json_data, int timeout)
|
||||||
|
{
|
||||||
|
// In case a request is called without a following waitForReply call
|
||||||
|
if (replyReadySemaphore.available() > 0)
|
||||||
|
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||||
|
|
||||||
|
static int requestId = 0;
|
||||||
|
requestId++;
|
||||||
|
|
||||||
|
replyMutex.lock();
|
||||||
|
expectedReplyId = requestId;
|
||||||
|
replyTimeout = 0;
|
||||||
|
requestStartTime = QDateTime::currentDateTime();
|
||||||
|
m_reply = QString();
|
||||||
|
replyMutex.unlock();
|
||||||
|
|
||||||
|
QJsonArray body;
|
||||||
|
body << requestId;
|
||||||
|
body << type;
|
||||||
|
body << command;
|
||||||
|
body << json_data;
|
||||||
|
body << timeout;
|
||||||
|
|
||||||
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::reply(int type, const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
QJsonArray body;
|
||||||
|
body << this->requestId;
|
||||||
|
body << type;
|
||||||
|
body << command;
|
||||||
|
body << json_data;
|
||||||
|
|
||||||
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::notify(int type, const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
QJsonArray body;
|
||||||
|
body << -2; // requestId = -2 mean this is for notification
|
||||||
|
body << type;
|
||||||
|
body << command;
|
||||||
|
body << json_data;
|
||||||
|
|
||||||
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Router::getTimeout() const
|
||||||
|
{
|
||||||
|
return requestTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancel last request from the sender
|
||||||
|
void Router::cancelRequest()
|
||||||
|
{
|
||||||
|
replyMutex.lock();
|
||||||
|
expectedReplyId = -1;
|
||||||
|
replyTimeout = 0;
|
||||||
|
extraReplyReadySemaphore = nullptr;
|
||||||
|
replyMutex.unlock();
|
||||||
|
|
||||||
|
if (replyReadySemaphore.available() > 0)
|
||||||
|
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Router::waitForReply()
|
||||||
|
{
|
||||||
|
replyReadySemaphore.acquire();
|
||||||
|
return m_reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Router::waitForReply(int timeout)
|
||||||
|
{
|
||||||
|
replyReadySemaphore.tryAcquire(1, timeout);
|
||||||
|
return m_reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::abortRequest()
|
||||||
|
{
|
||||||
|
replyMutex.lock();
|
||||||
|
if (expectedReplyId != -1) {
|
||||||
|
replyReadySemaphore.release();
|
||||||
|
if (extraReplyReadySemaphore)
|
||||||
|
extraReplyReadySemaphore->release();
|
||||||
|
expectedReplyId = -1;
|
||||||
|
extraReplyReadySemaphore = nullptr;
|
||||||
|
}
|
||||||
|
replyMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Router::handlePacket(const QByteArray& rawPacket)
|
||||||
|
{
|
||||||
|
QJsonDocument packet = QJsonDocument::fromJson(rawPacket);
|
||||||
|
if (packet.isNull() || !packet.isArray())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int requestId = packet[0].toInt();
|
||||||
|
int type = packet[1].toInt();
|
||||||
|
QString command = packet[2].toString();
|
||||||
|
QString json_data = packet[3].toString();
|
||||||
|
|
||||||
|
if (type & TYPE_NOTIFICATION) {
|
||||||
|
if (type & DEST_CLIENT) {
|
||||||
|
qobject_cast<Client *>(parent())->callLua(command, json_data);
|
||||||
|
} else {
|
||||||
|
qDebug() << rawPacket << Qt::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type & TYPE_REQUEST) {
|
||||||
|
this->requestId = requestId;
|
||||||
|
this->requestTimeout = packet[4].toInt();
|
||||||
|
|
||||||
|
if (type & DEST_CLIENT) {
|
||||||
|
qobject_cast<Client *>(parent())->callLua(command, json_data);
|
||||||
|
} else {
|
||||||
|
qDebug() << rawPacket << Qt::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type & TYPE_REPLY) {
|
||||||
|
QMutexLocker locker(&replyMutex);
|
||||||
|
|
||||||
|
if (requestId != this->expectedReplyId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->expectedReplyId = -1;
|
||||||
|
|
||||||
|
if (replyTimeout >= 0 && replyTimeout <
|
||||||
|
requestStartTime.secsTo(QDateTime::currentDateTime()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_reply = json_data;
|
||||||
|
// TODO: callback?
|
||||||
|
qDebug() << rawPacket << Qt::endl;
|
||||||
|
|
||||||
|
replyReadySemaphore.release();
|
||||||
|
if (extraReplyReadySemaphore) {
|
||||||
|
extraReplyReadySemaphore->release();
|
||||||
|
extraReplyReadySemaphore = nullptr;
|
||||||
|
}
|
||||||
|
locker.unlock();
|
||||||
|
emit replyReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
#ifndef _ROUTER_H
|
||||||
|
#define _ROUTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QSemaphore>
|
||||||
|
#include "client_socket.h"
|
||||||
|
|
||||||
|
class Router : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum PacketType {
|
||||||
|
TYPE_REQUEST = 0x100,
|
||||||
|
TYPE_REPLY = 0x200,
|
||||||
|
TYPE_NOTIFICATION = 0x400,
|
||||||
|
SRC_CLIENT = 0x010,
|
||||||
|
SRC_SERVER = 0x020,
|
||||||
|
SRC_LOBBY = 0x040,
|
||||||
|
DEST_CLIENT = 0x001,
|
||||||
|
DEST_SERVER = 0x002,
|
||||||
|
DEST_LOBBY = 0x004
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RouterType {
|
||||||
|
TYPE_SERVER,
|
||||||
|
TYPE_CLIENT
|
||||||
|
};
|
||||||
|
Router(QObject *parent, ClientSocket *socket, RouterType type);
|
||||||
|
~Router();
|
||||||
|
|
||||||
|
ClientSocket *getSocket() const;
|
||||||
|
void setSocket(ClientSocket *socket);
|
||||||
|
|
||||||
|
void setReplyReadySemaphore(QSemaphore *semaphore);
|
||||||
|
|
||||||
|
void request(int type, const QString &command,
|
||||||
|
const QString &json_data, int timeout);
|
||||||
|
void reply(int type, const QString &command, const QString &json_data);
|
||||||
|
void notify(int type, const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
int getTimeout() const;
|
||||||
|
|
||||||
|
void cancelRequest();
|
||||||
|
|
||||||
|
QString waitForReply();
|
||||||
|
QString waitForReply(int timeout);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void messageReady(const QByteArray &message);
|
||||||
|
void unknownPacket(const QByteArray &packet);
|
||||||
|
void replyReady();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void abortRequest();
|
||||||
|
void handlePacket(const QByteArray &rawPacket);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientSocket *socket;
|
||||||
|
RouterType type;
|
||||||
|
|
||||||
|
// For sender
|
||||||
|
int requestId;
|
||||||
|
int requestTimeout;
|
||||||
|
|
||||||
|
// For receiver
|
||||||
|
QDateTime requestStartTime;
|
||||||
|
QMutex replyMutex;
|
||||||
|
int expectedReplyId;
|
||||||
|
int replyTimeout;
|
||||||
|
QString m_reply; // should be json string
|
||||||
|
QSemaphore replyReadySemaphore;
|
||||||
|
QSemaphore *extraReplyReadySemaphore;
|
||||||
|
|
||||||
|
// Two Lua global table for callbacks and interactions
|
||||||
|
// stored in the lua_State of the sender
|
||||||
|
// LuaTable interactions;
|
||||||
|
// LuaTable callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _ROUTER_H
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "server_socket.h"
|
||||||
|
#include "client_socket.h"
|
||||||
|
#include <QTcpServer>
|
||||||
|
|
||||||
|
ServerSocket::ServerSocket()
|
||||||
|
{
|
||||||
|
server = new QTcpServer(this);
|
||||||
|
connect(server, &QTcpServer::newConnection,
|
||||||
|
this, &ServerSocket::processNewConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServerSocket::listen(const QHostAddress &address, ushort port)
|
||||||
|
{
|
||||||
|
return server->listen(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSocket::processNewConnection()
|
||||||
|
{
|
||||||
|
QTcpSocket *socket = server->nextPendingConnection();
|
||||||
|
ClientSocket *connection = new ClientSocket(socket);
|
||||||
|
emit new_connection(connection);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef _SERVER_SOCKET_H
|
||||||
|
#define _SERVER_SOCKET_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
class QTcpServer;
|
||||||
|
class ClientSocket;
|
||||||
|
|
||||||
|
class ServerSocket : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ServerSocket();
|
||||||
|
|
||||||
|
bool listen(const QHostAddress &address = QHostAddress::Any, ushort port = 9527u);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void new_connection(ClientSocket *socket);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void processNewConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpServer *server;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SERVER_SOCKET_H
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>qml/main.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "gamelogic.h"
|
||||||
|
|
||||||
|
GameLogic::GameLogic(Room *room)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLogic::run()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _GAMELOGIC_H
|
||||||
|
#define _GAMELOGIC_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
class Room;
|
||||||
|
|
||||||
|
// Just like the class 'RoomThread' in QSanguosha
|
||||||
|
class GameLogic : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GameLogic(Room *room);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _GAMELOGIC_H
|
|
@ -0,0 +1,124 @@
|
||||||
|
#include "room.h"
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
Room::Room(Server* server)
|
||||||
|
{
|
||||||
|
static uint roomId = 0;
|
||||||
|
id = roomId;
|
||||||
|
roomId++;
|
||||||
|
this->server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
Room::~Room()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
Server *Room::getServer() const
|
||||||
|
{
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Room::getId() const
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::isLobby() const
|
||||||
|
{
|
||||||
|
return id == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Room::getName() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::setName(const QString &name)
|
||||||
|
{
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Room::getCapacity() const
|
||||||
|
{
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::setCapacity(uint capacity)
|
||||||
|
{
|
||||||
|
this->capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::isFull() const
|
||||||
|
{
|
||||||
|
return players.count() == capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::isAbandoned() const
|
||||||
|
{
|
||||||
|
return players.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPlayer *Room::getOwner() const
|
||||||
|
{
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::setOwner(ServerPlayer *owner)
|
||||||
|
{
|
||||||
|
this->owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::addPlayer(ServerPlayer *player)
|
||||||
|
{
|
||||||
|
players.insert(player->getId(), player);
|
||||||
|
emit playerAdded(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::removePlayer(ServerPlayer *player)
|
||||||
|
{
|
||||||
|
players.remove(player->getId());
|
||||||
|
emit playerRemoved(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<uint, ServerPlayer *> Room::getPlayers() const
|
||||||
|
{
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPlayer *Room::findPlayer(uint id) const
|
||||||
|
{
|
||||||
|
return players.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::setGameLogic(GameLogic *logic)
|
||||||
|
{
|
||||||
|
this->logic = logic;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameLogic *Room::getGameLogic() const
|
||||||
|
{
|
||||||
|
return logic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::startGame()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::doRequest(const QList<ServerPlayer *> targets, int timeout)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::doNotify(const QList<ServerPlayer *> targets, int timeout)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::run()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef _ROOM_H
|
||||||
|
#define _ROOM_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QHash>
|
||||||
|
class Server;
|
||||||
|
class ServerPlayer;
|
||||||
|
class GameLogic;
|
||||||
|
|
||||||
|
class Room : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Room(Server *m_server);
|
||||||
|
~Room();
|
||||||
|
|
||||||
|
// Property reader & setter
|
||||||
|
// ==================================={
|
||||||
|
Server *getServer() const;
|
||||||
|
uint getId() const;
|
||||||
|
bool isLobby() const;
|
||||||
|
QString getName() const;
|
||||||
|
void setName(const QString &name);
|
||||||
|
uint getCapacity() const;
|
||||||
|
void setCapacity(uint capacity);
|
||||||
|
bool isFull() const;
|
||||||
|
bool isAbandoned() const;
|
||||||
|
|
||||||
|
ServerPlayer *getOwner() const;
|
||||||
|
void setOwner(ServerPlayer *owner);
|
||||||
|
|
||||||
|
void addPlayer(ServerPlayer *player);
|
||||||
|
void removePlayer(ServerPlayer *player);
|
||||||
|
QHash<uint, ServerPlayer*> getPlayers() const;
|
||||||
|
ServerPlayer *findPlayer(uint id) const;
|
||||||
|
|
||||||
|
void setGameLogic(GameLogic *logic);
|
||||||
|
GameLogic *getGameLogic() const;
|
||||||
|
// ====================================}
|
||||||
|
|
||||||
|
void startGame();
|
||||||
|
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
||||||
|
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void abandoned();
|
||||||
|
|
||||||
|
void aboutToStart();
|
||||||
|
void started();
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
void playerAdded(ServerPlayer *player);
|
||||||
|
void playerRemoved(ServerPlayer *player);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Server *server;
|
||||||
|
uint id; // Lobby's id is 0
|
||||||
|
QString name; // “阴间大乱斗”
|
||||||
|
uint capacity; // by default is 5, max is 8
|
||||||
|
bool m_abandoned; // If room is empty, delete it
|
||||||
|
|
||||||
|
ServerPlayer *owner; // who created this room?
|
||||||
|
QHash<uint, ServerPlayer *> players;
|
||||||
|
GameLogic *logic;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _ROOM_H
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "server.h"
|
||||||
|
#include "server_socket.h"
|
||||||
|
#include "client_socket.h"
|
||||||
|
#include "room.h"
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
Server *ServerInstance;
|
||||||
|
|
||||||
|
Server::Server(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
ServerInstance = this;
|
||||||
|
server = new ServerSocket();
|
||||||
|
server->setParent(this);
|
||||||
|
connect(server, &ServerSocket::new_connection,
|
||||||
|
this, &Server::processNewConnection);
|
||||||
|
|
||||||
|
// create lobby
|
||||||
|
createRoom(NULL, "Lobby", UINT32_MAX);
|
||||||
|
connect(lobby(), &Room::playerAdded, this, &Server::updateRoomList);
|
||||||
|
|
||||||
|
L = CreateLuaState();
|
||||||
|
DoLuaScript(L, "lua/freekill.lua");
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::~Server()
|
||||||
|
{
|
||||||
|
ServerInstance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::listen(const QHostAddress& address, ushort port)
|
||||||
|
{
|
||||||
|
return server->listen(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::createRoom(ServerPlayer* owner, const QString &name, uint capacity)
|
||||||
|
{
|
||||||
|
Room *room = new Room(this);
|
||||||
|
connect(room, &Room::abandoned, this, &Server::onRoomAbandoned);
|
||||||
|
room->setName(name);
|
||||||
|
room->setCapacity(capacity);
|
||||||
|
room->setOwner(owner);
|
||||||
|
// TODO
|
||||||
|
// room->addPlayer(owner);
|
||||||
|
rooms.insert(room->getId(), room);
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
qDebug() << "Room #" << room->getId() << " created.";
|
||||||
|
#endif
|
||||||
|
emit roomCreated(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
Room *Server::findRoom(uint id) const
|
||||||
|
{
|
||||||
|
return rooms.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Room *Server::lobby() const
|
||||||
|
{
|
||||||
|
return findRoom(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPlayer *Server::findPlayer(uint id) const
|
||||||
|
{
|
||||||
|
return players.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::updateRoomList(ServerPlayer* user)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::processNewConnection(ClientSocket* client)
|
||||||
|
{
|
||||||
|
// version check, file check, ban IP, reconnect, etc
|
||||||
|
ServerPlayer *player = new ServerPlayer(lobby());
|
||||||
|
player->setSocket(client);
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
qDebug() << "ServerPlayer #" << player->getUid() << "connected.";
|
||||||
|
qDebug() << "His address is " << client->peerAddress();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
player->doNotify("enter_lobby", "{}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::onRoomAbandoned()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::onUserDisconnected()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::onUserStateChanged()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef _SERVER_H
|
||||||
|
#define _SERVER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <lua.hpp>
|
||||||
|
|
||||||
|
class ServerSocket;
|
||||||
|
class ClientSocket;
|
||||||
|
class Room;
|
||||||
|
class ServerPlayer;
|
||||||
|
|
||||||
|
typedef int LuaFunction;
|
||||||
|
|
||||||
|
class Server : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Server(QObject *parent = nullptr);
|
||||||
|
~Server();
|
||||||
|
|
||||||
|
bool listen(const QHostAddress &address = QHostAddress::Any, ushort port = 9527u);
|
||||||
|
|
||||||
|
void createRoom(ServerPlayer *owner, const QString &name, uint capacity);
|
||||||
|
Room *findRoom(uint id) const;
|
||||||
|
Room *lobby() const;
|
||||||
|
|
||||||
|
ServerPlayer *findPlayer(uint id) const;
|
||||||
|
|
||||||
|
void updateRoomList(ServerPlayer *user);
|
||||||
|
|
||||||
|
void callLua(const QString &command, const QString &json_data);
|
||||||
|
LuaFunction callback;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void roomCreated(Room *room);
|
||||||
|
void playerAdded(ServerPlayer *player);
|
||||||
|
void playerRemoved(ServerPlayer *player);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void processNewConnection(ClientSocket *client);
|
||||||
|
|
||||||
|
void onRoomAbandoned();
|
||||||
|
void onUserDisconnected();
|
||||||
|
void onUserStateChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ServerSocket *server;
|
||||||
|
QHash<uint, Room *> rooms;
|
||||||
|
QHash<uint, ServerPlayer *> players;
|
||||||
|
|
||||||
|
lua_State *L;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Server *ServerInstance;
|
||||||
|
|
||||||
|
#endif // _SERVER_H
|
|
@ -0,0 +1,76 @@
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "room.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
ServerPlayer::ServerPlayer(Room *room)
|
||||||
|
: uid(0)
|
||||||
|
{
|
||||||
|
static int m_playerid = 0;
|
||||||
|
m_playerid++;
|
||||||
|
|
||||||
|
uid = m_playerid;
|
||||||
|
|
||||||
|
socket = nullptr;
|
||||||
|
router = new Router(this, socket, Router::TYPE_SERVER);
|
||||||
|
|
||||||
|
this->room = room;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPlayer::~ServerPlayer()
|
||||||
|
{
|
||||||
|
router->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ServerPlayer::getUid() const
|
||||||
|
{
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::setSocket(ClientSocket *socket)
|
||||||
|
{
|
||||||
|
this->socket = socket;
|
||||||
|
router->setSocket(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
Server *ServerPlayer::getServer() const
|
||||||
|
{
|
||||||
|
return room->getServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Room *ServerPlayer::getRoom() const
|
||||||
|
{
|
||||||
|
return room;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::setRoom(Room* room)
|
||||||
|
{
|
||||||
|
this->room = room;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::speak(const QString& message)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::doRequest(const QString& command, const QString& json_data, int timeout)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_REQUEST | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||||
|
router->request(type, command, json_data, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::doReply(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_REPLY | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||||
|
router->reply(type, command, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::doNotify(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
int type = Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||||
|
router->notify(type, command, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayer::prepareForRequest(const QString& command, const QVariant& data)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef _SERVERPLAYER_H
|
||||||
|
#define _SERVERPLAYER_H
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
#include "router.h"
|
||||||
|
#include <QVariant>
|
||||||
|
class ClientSocket;
|
||||||
|
class Server;
|
||||||
|
class Room;
|
||||||
|
|
||||||
|
class ServerPlayer : public Player {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ServerPlayer(Room *room);
|
||||||
|
~ServerPlayer();
|
||||||
|
|
||||||
|
uint getUid() const;
|
||||||
|
|
||||||
|
void setSocket(ClientSocket *socket);
|
||||||
|
|
||||||
|
Server *getServer() const;
|
||||||
|
Room *getRoom() const;
|
||||||
|
void setRoom(Room *room);
|
||||||
|
|
||||||
|
void speak(const QString &message);
|
||||||
|
|
||||||
|
void doRequest(const QString &command,
|
||||||
|
const QString &json_data, int timeout = -1);
|
||||||
|
void doReply(const QString &command, const QString &json_data);
|
||||||
|
void doNotify(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
void prepareForRequest(const QString &command,
|
||||||
|
const QVariant &data = QVariant());
|
||||||
|
private:
|
||||||
|
uint uid;
|
||||||
|
ClientSocket *socket; // socket for communicating with client
|
||||||
|
Router *router;
|
||||||
|
Server *server;
|
||||||
|
Room *room; // Room that player is in, maybe lobby
|
||||||
|
|
||||||
|
QString requestCommand;
|
||||||
|
QVariant requestData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SERVERPLAYER_H
|
|
@ -0,0 +1,232 @@
|
||||||
|
%module freekill
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include "client.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "serverplayer.h"
|
||||||
|
#include "clientplayer.h"
|
||||||
|
#include "room.h"
|
||||||
|
#include "qmlbackend.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
// ------------------------------------------------------
|
||||||
|
// type bindings
|
||||||
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
// LuaFunction(int) and lua function
|
||||||
|
%naturalvar LuaFunction;
|
||||||
|
%typemap(in) LuaFunction
|
||||||
|
%{
|
||||||
|
if (lua_isfunction(L, $input)) {
|
||||||
|
lua_pushvalue(L, $input);
|
||||||
|
$1 = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
} else {
|
||||||
|
$1 = 0;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(out) LuaFunction
|
||||||
|
%{
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, $1);
|
||||||
|
SWIG_arg ++;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// QString and lua string
|
||||||
|
%naturalvar QString;
|
||||||
|
|
||||||
|
%typemap(in, checkfn = "lua_isstring") QString
|
||||||
|
%{ $1 = lua_tostring(L, $input); %}
|
||||||
|
|
||||||
|
%typemap(out) QString
|
||||||
|
%{ lua_pushstring(L, $1.toUtf8()); SWIG_arg++; %}
|
||||||
|
|
||||||
|
// const QString &
|
||||||
|
%typemap(in, checkfn = "lua_isstring") QString const &
|
||||||
|
%{
|
||||||
|
if (1) { // to avoid 'Jump bypasses variable initialization' error
|
||||||
|
QString $1_str = QString::fromUtf8(lua_tostring(L, $input));
|
||||||
|
$1 = &$1_str;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(out) QString const &
|
||||||
|
%{ lua_pushstring(L, $1.toUtf8()); SWIG_arg++; %}
|
||||||
|
|
||||||
|
// ------------------------------------------------------
|
||||||
|
// classes and functions
|
||||||
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
class QObject {
|
||||||
|
public:
|
||||||
|
QString objectName();
|
||||||
|
void setObjectName(const char *name);
|
||||||
|
bool inherits(const char *class_name);
|
||||||
|
bool setProperty(const char *name, const QVariant &value);
|
||||||
|
QVariant property(const char *name) const;
|
||||||
|
void setParent(QObject *parent);
|
||||||
|
void deleteLater();
|
||||||
|
};
|
||||||
|
|
||||||
|
class QThread {};
|
||||||
|
|
||||||
|
class QmlBackend : public QObject {
|
||||||
|
public:
|
||||||
|
void emitNotifyUI(const char *command, const char *json_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern QmlBackend *Backend;
|
||||||
|
|
||||||
|
class Client : public QObject {
|
||||||
|
public:
|
||||||
|
void requestServer(const QString &command,
|
||||||
|
const QString &json_data, int timeout = -1);
|
||||||
|
void replyToServer(const QString &command, const QString &json_data);
|
||||||
|
void notifyServer(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
LuaFunction callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Client *ClientInstance;
|
||||||
|
|
||||||
|
%{
|
||||||
|
void Client::callLua(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
Q_ASSERT(callback);
|
||||||
|
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
|
||||||
|
SWIG_NewPointerObj(L, this, SWIGTYPE_p_Client, 0);
|
||||||
|
lua_pushstring(L, command.toUtf8());
|
||||||
|
lua_pushstring(L, json_data.toUtf8());
|
||||||
|
|
||||||
|
int error = lua_pcall(L, 3, 0, 0);
|
||||||
|
if (error) {
|
||||||
|
const char *error_msg = lua_tostring(L, -1);
|
||||||
|
qDebug() << error_msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
class Server : public QObject {
|
||||||
|
public:
|
||||||
|
void createRoom(ServerPlayer *owner, const QString &name, unsigned int capacity);
|
||||||
|
Room *findRoom(unsigned int id) const;
|
||||||
|
Room *lobby() const;
|
||||||
|
|
||||||
|
ServerPlayer *findPlayer(unsigned int id) const;
|
||||||
|
|
||||||
|
void updateRoomList(ServerPlayer *user);
|
||||||
|
|
||||||
|
LuaFunction callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
%{
|
||||||
|
void Server::callLua(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
Q_ASSERT(callback);
|
||||||
|
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
|
||||||
|
SWIG_NewPointerObj(L, this, SWIGTYPE_p_Server, 0);
|
||||||
|
lua_pushstring(L, command.toUtf8());
|
||||||
|
lua_pushstring(L, json_data.toUtf8());
|
||||||
|
|
||||||
|
int error = lua_pcall(L, 3, 0, 0);
|
||||||
|
if (error) {
|
||||||
|
const char *error_msg = lua_tostring(L, -1);
|
||||||
|
qDebug() << error_msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
extern Server *ServerInstance;
|
||||||
|
|
||||||
|
class Player : public QObject {
|
||||||
|
enum State{
|
||||||
|
Invalid,
|
||||||
|
Online,
|
||||||
|
Trust,
|
||||||
|
Offline
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int getId() const;
|
||||||
|
void setId(unsigned int id);
|
||||||
|
|
||||||
|
QString getScreenName() const;
|
||||||
|
void setScreenName(const QString &name);
|
||||||
|
|
||||||
|
QString getAvatar() const;
|
||||||
|
void setAvatar(const QString &avatar);
|
||||||
|
|
||||||
|
State getState() const;
|
||||||
|
QString getStateString() const;
|
||||||
|
void setState(State state);
|
||||||
|
void setStateString(const QString &state);
|
||||||
|
|
||||||
|
bool isReady() const;
|
||||||
|
void setReady(bool ready);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClientPlayer : public Player {
|
||||||
|
public:
|
||||||
|
ClientPlayer(unsigned int id, QObject *parent = nullptr);
|
||||||
|
~ClientPlayer();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ClientPlayer *Self;
|
||||||
|
|
||||||
|
class ServerPlayer : public Player {
|
||||||
|
public:
|
||||||
|
explicit ServerPlayer(Room *room);
|
||||||
|
~ServerPlayer();
|
||||||
|
|
||||||
|
unsigned int getUid() const;
|
||||||
|
|
||||||
|
void setSocket(ClientSocket *socket);
|
||||||
|
|
||||||
|
Server *getServer() const;
|
||||||
|
Room *getRoom() const;
|
||||||
|
void setRoom(Room *room);
|
||||||
|
|
||||||
|
void speak(const QString &message);
|
||||||
|
|
||||||
|
void doRequest(const QString &command,
|
||||||
|
const QString &json_data, int timeout = -1);
|
||||||
|
void doReply(const QString &command, const QString &json_data);
|
||||||
|
void doNotify(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
void prepareForRequest(const QString &command,
|
||||||
|
const QVariant &data = QVariant());
|
||||||
|
};
|
||||||
|
|
||||||
|
class Room : public QThread {
|
||||||
|
public:
|
||||||
|
explicit Room(Server *m_server);
|
||||||
|
~Room();
|
||||||
|
|
||||||
|
// Property reader & setter
|
||||||
|
// ==================================={
|
||||||
|
Server *getServer() const;
|
||||||
|
unsigned int getId() const;
|
||||||
|
bool isLobby() const;
|
||||||
|
QString getName() const;
|
||||||
|
void setName(const QString &name);
|
||||||
|
unsigned int getCapacity() const;
|
||||||
|
void setCapacity(unsigned int capacity);
|
||||||
|
bool isFull() const;
|
||||||
|
bool isAbandoned() const;
|
||||||
|
|
||||||
|
ServerPlayer *getOwner() const;
|
||||||
|
void setOwner(ServerPlayer *owner);
|
||||||
|
|
||||||
|
void addPlayer(ServerPlayer *player);
|
||||||
|
void removePlayer(ServerPlayer *player);
|
||||||
|
QHash<unsigned int, ServerPlayer*> getPlayers() const;
|
||||||
|
ServerPlayer *findPlayer(unsigned int id) const;
|
||||||
|
|
||||||
|
void setGameLogic(GameLogic *logic);
|
||||||
|
GameLogic *getGameLogic() const;
|
||||||
|
// ====================================}
|
||||||
|
|
||||||
|
void startGame();
|
||||||
|
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
||||||
|
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
||||||
|
};
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "qmlbackend.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
QmlBackend *Backend;
|
||||||
|
|
||||||
|
QmlBackend::QmlBackend(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
Backend = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QmlBackend::startServer(ushort port)
|
||||||
|
{
|
||||||
|
class Server *server = new class Server(this);
|
||||||
|
if (!server->listen(QHostAddress::Any, port)) {
|
||||||
|
server->deleteLater();
|
||||||
|
emit notifyUI("error_msg", tr("Cannot start server!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlBackend::joinServer(QString address)
|
||||||
|
{
|
||||||
|
class Client *client = new class Client(this);
|
||||||
|
connect(client, &Client::error_message, [this, client](const QString &msg){
|
||||||
|
client->deleteLater();
|
||||||
|
emit notifyUI("error_msg", msg);
|
||||||
|
});
|
||||||
|
QString addr = "127.0.0.1";
|
||||||
|
ushort port = 9527u;
|
||||||
|
|
||||||
|
if (address.contains(QChar(':'))) {
|
||||||
|
QStringList texts = address.split(QChar(':'));
|
||||||
|
addr = texts.value(0);
|
||||||
|
port = texts.value(1).toUShort();
|
||||||
|
} else {
|
||||||
|
addr = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->connectToHost(QHostAddress(addr), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlBackend::replyToServer(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
ClientInstance->replyToServer(command, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlBackend::notifyServer(const QString& command, const QString& json_data)
|
||||||
|
{
|
||||||
|
ClientInstance->notifyServer(command, json_data);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef _QMLBACKEND_H
|
||||||
|
#define _QMLBACKEND_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
class QmlBackend : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum WindowType {
|
||||||
|
Server,
|
||||||
|
Lobby,
|
||||||
|
Room,
|
||||||
|
NotStarted
|
||||||
|
};
|
||||||
|
|
||||||
|
QmlBackend(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
// For lua use
|
||||||
|
void emitNotifyUI(const char *command, const char *json_data) {
|
||||||
|
emit notifyUI(command, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void notifyUI(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void startServer(ushort port);
|
||||||
|
void joinServer(QString address);
|
||||||
|
void replyToServer(const QString &command, const QString &json_data);
|
||||||
|
void notifyServer(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WindowType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern QmlBackend *Backend;
|
||||||
|
|
||||||
|
#endif // _QMLBACKEND_H
|
Loading…
Reference in New Issue