From 6fb0158d39df7f023f91b91fb1f6362bff53bce0 Mon Sep 17 00:00:00 2001 From: Notify-ctrl <1969315774@qq.com> Date: Mon, 24 Jan 2022 10:23:08 +0800 Subject: [PATCH] Initial import commit 1 GPLv3 commit commit commit commit commit commit --- .gitignore | 8 + CMakeLists.txt | 28 ++ LICENSE | 674 ++++++++++++++++++++++++++++ include/lua/lapi.h | 49 +++ include/lua/lauxlib.h | 301 +++++++++++++ include/lua/lcode.h | 104 +++++ include/lua/lctype.h | 101 +++++ include/lua/ldebug.h | 63 +++ include/lua/ldo.h | 79 ++++ include/lua/lfunc.h | 64 +++ include/lua/lgc.h | 199 +++++++++ include/lua/ljumptab.h | 112 +++++ include/lua/llex.h | 91 ++++ include/lua/llimits.h | 367 ++++++++++++++++ include/lua/lmem.h | 93 ++++ include/lua/lobject.h | 800 ++++++++++++++++++++++++++++++++++ include/lua/lopcodes.h | 405 +++++++++++++++++ include/lua/lopnames.h | 103 +++++ include/lua/lparser.h | 171 ++++++++ include/lua/lprefix.h | 45 ++ include/lua/lstate.h | 404 +++++++++++++++++ include/lua/lstring.h | 57 +++ include/lua/ltable.h | 66 +++ include/lua/ltm.h | 103 +++++ include/lua/lua.h | 518 ++++++++++++++++++++++ include/lua/lua.hpp | 9 + include/lua/luaconf.h | 786 +++++++++++++++++++++++++++++++++ include/lua/lualib.h | 52 +++ include/lua/lundump.h | 36 ++ include/lua/lvm.h | 136 ++++++ include/lua/lzio.h | 66 +++ lib/win/lua54.dll | Bin 0 -> 230180 bytes lua/client/client.lua | 25 ++ lua/core/card.lua | 52 +++ lua/freekill.lua | 16 + lua/lib/json.lua | 388 +++++++++++++++++ lua/lib/middleclass.lua | 189 ++++++++ lua/server/server.lua | 26 ++ qml/Page/Init.qml | 39 ++ qml/Page/Lobby.qml | 112 +++++ qml/Page/Room.qml | 8 + qml/main.qml | 108 +++++ src/CMakeLists.txt | 49 +++ src/client/client.cpp | 50 +++ src/client/client.h | 42 ++ src/client/clientplayer.cpp | 11 + src/client/clientplayer.h | 17 + src/core/global.cpp | 27 ++ src/core/global.h | 12 + src/core/player.cpp | 94 ++++ src/core/player.h | 53 +++ src/main.cpp | 42 ++ src/network/client_socket.cpp | 95 ++++ src/network/client_socket.h | 40 ++ src/network/router.cpp | 196 +++++++++ src/network/router.h | 83 ++++ src/network/server_socket.cpp | 23 + src/network/server_socket.h | 28 ++ src/resources.qrc | 5 + src/server/gamelogic.cpp | 11 + src/server/gamelogic.h | 17 + src/server/room.cpp | 124 ++++++ src/server/room.h | 69 +++ src/server/server.cpp | 100 +++++ src/server/server.h | 58 +++ src/server/serverplayer.cpp | 76 ++++ src/server/serverplayer.h | 45 ++ src/swig/freekill.i | 232 ++++++++++ src/ui/qmlbackend.cpp | 52 +++ src/ui/qmlbackend.h | 40 ++ 70 files changed, 8744 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 include/lua/lapi.h create mode 100644 include/lua/lauxlib.h create mode 100644 include/lua/lcode.h create mode 100644 include/lua/lctype.h create mode 100644 include/lua/ldebug.h create mode 100644 include/lua/ldo.h create mode 100644 include/lua/lfunc.h create mode 100644 include/lua/lgc.h create mode 100644 include/lua/ljumptab.h create mode 100644 include/lua/llex.h create mode 100644 include/lua/llimits.h create mode 100644 include/lua/lmem.h create mode 100644 include/lua/lobject.h create mode 100644 include/lua/lopcodes.h create mode 100644 include/lua/lopnames.h create mode 100644 include/lua/lparser.h create mode 100644 include/lua/lprefix.h create mode 100644 include/lua/lstate.h create mode 100644 include/lua/lstring.h create mode 100644 include/lua/ltable.h create mode 100644 include/lua/ltm.h create mode 100644 include/lua/lua.h create mode 100644 include/lua/lua.hpp create mode 100644 include/lua/luaconf.h create mode 100644 include/lua/lualib.h create mode 100644 include/lua/lundump.h create mode 100644 include/lua/lvm.h create mode 100644 include/lua/lzio.h create mode 100644 lib/win/lua54.dll create mode 100644 lua/client/client.lua create mode 100644 lua/core/card.lua create mode 100644 lua/freekill.lua create mode 100644 lua/lib/json.lua create mode 100644 lua/lib/middleclass.lua create mode 100644 lua/server/server.lua create mode 100644 qml/Page/Init.qml create mode 100644 qml/Page/Lobby.qml create mode 100644 qml/Page/Room.qml create mode 100644 qml/main.qml create mode 100644 src/CMakeLists.txt create mode 100644 src/client/client.cpp create mode 100644 src/client/client.h create mode 100644 src/client/clientplayer.cpp create mode 100644 src/client/clientplayer.h create mode 100644 src/core/global.cpp create mode 100644 src/core/global.h create mode 100644 src/core/player.cpp create mode 100644 src/core/player.h create mode 100644 src/main.cpp create mode 100644 src/network/client_socket.cpp create mode 100644 src/network/client_socket.h create mode 100644 src/network/router.cpp create mode 100644 src/network/router.h create mode 100644 src/network/server_socket.cpp create mode 100644 src/network/server_socket.h create mode 100644 src/resources.qrc create mode 100644 src/server/gamelogic.cpp create mode 100644 src/server/gamelogic.h create mode 100644 src/server/room.cpp create mode 100644 src/server/room.h create mode 100644 src/server/server.cpp create mode 100644 src/server/server.h create mode 100644 src/server/serverplayer.cpp create mode 100644 src/server/serverplayer.h create mode 100644 src/swig/freekill.i create mode 100644 src/ui/qmlbackend.cpp create mode 100644 src/ui/qmlbackend.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0c585e1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +build/ +.kdev4/ +*.user +*-swp +*.kdev4 +FreeKill +FreeKill.exe +freekill-wrap.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..626eb678 --- /dev/null +++ b/CMakeLists.txt @@ -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) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/include/lua/lapi.h b/include/lua/lapi.h new file mode 100644 index 00000000..9e99cc44 --- /dev/null +++ b/include/lua/lapi.h @@ -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 diff --git a/include/lua/lauxlib.h b/include/lua/lauxlib.h new file mode 100644 index 00000000..5b977e2a --- /dev/null +++ b/include/lua/lauxlib.h @@ -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 +#include + +#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 + #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 + + diff --git a/include/lua/lcode.h b/include/lua/lcode.h new file mode 100644 index 00000000..32658244 --- /dev/null +++ b/include/lua/lcode.h @@ -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 diff --git a/include/lua/lctype.h b/include/lua/lctype.h new file mode 100644 index 00000000..864e1901 --- /dev/null +++ b/include/lua/lctype.h @@ -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 + +#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 + + +#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 + diff --git a/include/lua/ldebug.h b/include/lua/ldebug.h new file mode 100644 index 00000000..974960e9 --- /dev/null +++ b/include/lua/ldebug.h @@ -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 diff --git a/include/lua/ldo.h b/include/lua/ldo.h new file mode 100644 index 00000000..911e67f6 --- /dev/null +++ b/include/lua/ldo.h @@ -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 + diff --git a/include/lua/lfunc.h b/include/lua/lfunc.h new file mode 100644 index 00000000..dc1cebcc --- /dev/null +++ b/include/lua/lfunc.h @@ -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 diff --git a/include/lua/lgc.h b/include/lua/lgc.h new file mode 100644 index 00000000..4a125634 --- /dev/null +++ b/include/lua/lgc.h @@ -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 diff --git a/include/lua/ljumptab.h b/include/lua/ljumptab.h new file mode 100644 index 00000000..8306f250 --- /dev/null +++ b/include/lua/ljumptab.h @@ -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 + +}; diff --git a/include/lua/llex.h b/include/lua/llex.h new file mode 100644 index 00000000..389d2f86 --- /dev/null +++ b/include/lua/llex.h @@ -0,0 +1,91 @@ +/* +** $Id: llex.h $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include + +#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 diff --git a/include/lua/llimits.h b/include/lua/llimits.h new file mode 100644 index 00000000..52a32f92 --- /dev/null +++ b/include/lua/llimits.h @@ -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 +#include + + +#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 +#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 diff --git a/include/lua/lmem.h b/include/lua/lmem.h new file mode 100644 index 00000000..8c75a44b --- /dev/null +++ b/include/lua/lmem.h @@ -0,0 +1,93 @@ +/* +** $Id: lmem.h $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#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 + diff --git a/include/lua/lobject.h b/include/lua/lobject.h new file mode 100644 index 00000000..0e05b3e4 --- /dev/null +++ b/include/lua/lobject.h @@ -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 + + +#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<

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 + diff --git a/include/lua/lopcodes.h b/include/lua/lopcodes.h new file mode 100644 index 00000000..7c274515 --- /dev/null +++ b/include/lua/lopcodes.h @@ -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<>1) /* 'sBx' is signed */ + + +#if L_INTHASBITS(SIZE_Ax) +#define MAXARG_Ax ((1<> 1) + + +#define MAXARG_A ((1<> 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)) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<> 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 ; + 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 diff --git a/include/lua/lopnames.h b/include/lua/lopnames.h new file mode 100644 index 00000000..965cec9b --- /dev/null +++ b/include/lua/lopnames.h @@ -0,0 +1,103 @@ +/* +** $Id: lopnames.h $ +** Opcode names +** See Copyright Notice in lua.h +*/ + +#if !defined(lopnames_h) +#define lopnames_h + +#include + + +/* 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 + diff --git a/include/lua/lparser.h b/include/lua/lparser.h new file mode 100644 index 00000000..5e4500f1 --- /dev/null +++ b/include/lua/lparser.h @@ -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 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 diff --git a/include/lua/lprefix.h b/include/lua/lprefix.h new file mode 100644 index 00000000..484f2ad6 --- /dev/null +++ b/include/lua/lprefix.h @@ -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 + diff --git a/include/lua/lstate.h b/include/lua/lstate.h new file mode 100644 index 00000000..61e82cde --- /dev/null +++ b/include/lua/lstate.h @@ -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 +#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 + diff --git a/include/lua/lstring.h b/include/lua/lstring.h new file mode 100644 index 00000000..450c2390 --- /dev/null +++ b/include/lua/lstring.h @@ -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 diff --git a/include/lua/ltable.h b/include/lua/ltable.h new file mode 100644 index 00000000..7bbbcb21 --- /dev/null +++ b/include/lua/ltable.h @@ -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 diff --git a/include/lua/ltm.h b/include/lua/ltm.h new file mode 100644 index 00000000..73b833c6 --- /dev/null +++ b/include/lua/ltm.h @@ -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 diff --git a/include/lua/lua.h b/include/lua/lua.h new file mode 100644 index 00000000..e6618392 --- /dev/null +++ b/include/lua/lua.h @@ -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 +#include + + +#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 ('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 diff --git a/include/lua/lua.hpp b/include/lua/lua.hpp new file mode 100644 index 00000000..ec417f59 --- /dev/null +++ b/include/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/include/lua/luaconf.h b/include/lua/luaconf.h new file mode 100644 index 00000000..d42d14b7 --- /dev/null +++ b/include/lua/luaconf.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 +#include + + +/* +** =================================================================== +** 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 +#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 +#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 + diff --git a/include/lua/lualib.h b/include/lua/lualib.h new file mode 100644 index 00000000..26255290 --- /dev/null +++ b/include/lua/lualib.h @@ -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 diff --git a/include/lua/lundump.h b/include/lua/lundump.h new file mode 100644 index 00000000..f3748a99 --- /dev/null +++ b/include/lua/lundump.h @@ -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 diff --git a/include/lua/lvm.h b/include/lua/lvm.h new file mode 100644 index 00000000..1bc16f3a --- /dev/null +++ b/include/lua/lvm.h @@ -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 diff --git a/include/lua/lzio.h b/include/lua/lzio.h new file mode 100644 index 00000000..38f397fd --- /dev/null +++ b/include/lua/lzio.h @@ -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 diff --git a/lib/win/lua54.dll b/lib/win/lua54.dll new file mode 100644 index 0000000000000000000000000000000000000000..77ff13fd9e05518c3e62ed53264c0c1c14ce4688 GIT binary patch literal 230180 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 z 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 KppkkK{eJ-j{0s2_ literal 0 HcmV?d00001 diff --git a/lua/client/client.lua b/lua/client/client.lua new file mode 100644 index 00000000..0ed8b6f8 --- /dev/null +++ b/lua/client/client.lua @@ -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() diff --git a/lua/core/card.lua b/lua/core/card.lua new file mode 100644 index 00000000..31e9bc11 --- /dev/null +++ b/lua/core/card.lua @@ -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 diff --git a/lua/freekill.lua b/lua/freekill.lua new file mode 100644 index 00000000..4ae794e6 --- /dev/null +++ b/lua/freekill.lua @@ -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 diff --git a/lua/lib/json.lua b/lua/lib/json.lua new file mode 100644 index 00000000..711ef786 --- /dev/null +++ b/lua/lib/json.lua @@ -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 diff --git a/lua/lib/middleclass.lua b/lua/lib/middleclass.lua new file mode 100644 index 00000000..b479f1ef --- /dev/null +++ b/lua/lib/middleclass.lua @@ -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 diff --git a/lua/server/server.lua b/lua/server/server.lua new file mode 100644 index 00000000..67b33266 --- /dev/null +++ b/lua/server/server.lua @@ -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() diff --git a/qml/Page/Init.qml b/qml/Page/Init.qml new file mode 100644 index 00000000..c49f6525 --- /dev/null +++ b/qml/Page/Init.qml @@ -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"); + } + } + } + } +} diff --git a/qml/Page/Lobby.qml b/qml/Page/Lobby.qml new file mode 100644 index 00000000..885b7e90 --- /dev/null +++ b/qml/Page/Lobby.qml @@ -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!") + } +} + diff --git a/qml/Page/Room.qml b/qml/Page/Room.qml new file mode 100644 index 00000000..22c5da15 --- /dev/null +++ b/qml/Page/Room.qml @@ -0,0 +1,8 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.0 +import QtQuick.Window 2.0 + +Item { + id: root +} + diff --git a/qml/main.qml b/qml/main.qml new file mode 100644 index 00000000..76ed0efa --- /dev/null +++ b/qml/main.qml @@ -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 + "!"); + } + } + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..6a430bbc --- /dev/null +++ b/src/CMakeLists.txt @@ -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 +) diff --git a/src/client/client.cpp b/src/client/client.cpp new file mode 100644 index 00000000..5d16316e --- /dev/null +++ b/src/client/client.cpp @@ -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); +} diff --git a/src/client/client.h b/src/client/client.h new file mode 100644 index 00000000..8bd31bac --- /dev/null +++ b/src/client/client.h @@ -0,0 +1,42 @@ +#ifndef _CLIENT_H +#define _CLIENT_H + +#include +#include +#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 players; + + lua_State *L; +}; + +extern Client *ClientInstance; + +#endif // _CLIENT_H diff --git a/src/client/clientplayer.cpp b/src/client/clientplayer.cpp new file mode 100644 index 00000000..d4461390 --- /dev/null +++ b/src/client/clientplayer.cpp @@ -0,0 +1,11 @@ +#include "clientplayer.h" + +ClientPlayer::ClientPlayer(uint id, QObject* parent) + : Player(parent) +{ + setId(id); +} + +ClientPlayer::~ClientPlayer() +{ +} diff --git a/src/client/clientplayer.h b/src/client/clientplayer.h new file mode 100644 index 00000000..733a85c8 --- /dev/null +++ b/src/client/clientplayer.h @@ -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 diff --git a/src/core/global.cpp b/src/core/global.cpp new file mode 100644 index 00000000..9cb75ec3 --- /dev/null +++ b/src/core/global.cpp @@ -0,0 +1,27 @@ +#include "global.h" +#include + +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; +} + diff --git a/src/core/global.h b/src/core/global.h new file mode 100644 index 00000000..036a9b1a --- /dev/null +++ b/src/core/global.h @@ -0,0 +1,12 @@ +#ifndef _GLOBAL_H +#define _GLOBAL_H + +#include + +// utilities +typedef int LuaFunction; + +lua_State *CreateLuaState(); +bool DoLuaScript(lua_State *L, const char *script); + +#endif // _GLOBAL_H diff --git a/src/core/player.cpp b/src/core/player.cpp new file mode 100644 index 00000000..89083e33 --- /dev/null +++ b/src/core/player.cpp @@ -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(); +} + diff --git a/src/core/player.h b/src/core/player.h new file mode 100644 index 00000000..8ca97f5e --- /dev/null +++ b/src/core/player.h @@ -0,0 +1,53 @@ +#ifndef _PLAYER_H +#define _PLAYER_H + +#include + +// 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 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..c7e6cb64 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#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"}); + 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(); +} diff --git a/src/network/client_socket.cpp b/src/network/client_socket.cpp new file mode 100644 index 00000000..58f00b65 --- /dev/null +++ b/src/network/client_socket.cpp @@ -0,0 +1,95 @@ +#include "client_socket.h" +#include +#include + +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)); +} diff --git a/src/network/client_socket.h b/src/network/client_socket.h new file mode 100644 index 00000000..23853077 --- /dev/null +++ b/src/network/client_socket.h @@ -0,0 +1,40 @@ +#ifndef _CLIENT_SOCKET_H +#define _CLIENT_SOCKET_H + +#include +#include +#include + +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 diff --git a/src/network/router.cpp b/src/network/router.cpp new file mode 100644 index 00000000..51a597bc --- /dev/null +++ b/src/network/router.cpp @@ -0,0 +1,196 @@ +#include +#include +#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(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(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(); + } +} + diff --git a/src/network/router.h b/src/network/router.h new file mode 100644 index 00000000..9e7a8ba0 --- /dev/null +++ b/src/network/router.h @@ -0,0 +1,83 @@ +#ifndef _ROUTER_H +#define _ROUTER_H + +#include +#include +#include +#include +#include +#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 diff --git a/src/network/server_socket.cpp b/src/network/server_socket.cpp new file mode 100644 index 00000000..cbf2322b --- /dev/null +++ b/src/network/server_socket.cpp @@ -0,0 +1,23 @@ +#include "server_socket.h" +#include "client_socket.h" +#include + +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); +} + diff --git a/src/network/server_socket.h b/src/network/server_socket.h new file mode 100644 index 00000000..ec9966a9 --- /dev/null +++ b/src/network/server_socket.h @@ -0,0 +1,28 @@ +#ifndef _SERVER_SOCKET_H +#define _SERVER_SOCKET_H + +#include +#include + +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 diff --git a/src/resources.qrc b/src/resources.qrc new file mode 100644 index 00000000..7c75584c --- /dev/null +++ b/src/resources.qrc @@ -0,0 +1,5 @@ + + + qml/main.qml + + diff --git a/src/server/gamelogic.cpp b/src/server/gamelogic.cpp new file mode 100644 index 00000000..c20467ea --- /dev/null +++ b/src/server/gamelogic.cpp @@ -0,0 +1,11 @@ +#include "gamelogic.h" + +GameLogic::GameLogic(Room *room) +{ + +} + +void GameLogic::run() +{ + +} diff --git a/src/server/gamelogic.h b/src/server/gamelogic.h new file mode 100644 index 00000000..fbe323eb --- /dev/null +++ b/src/server/gamelogic.h @@ -0,0 +1,17 @@ +#ifndef _GAMELOGIC_H +#define _GAMELOGIC_H + +#include +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 diff --git a/src/server/room.cpp b/src/server/room.cpp new file mode 100644 index 00000000..18189d5e --- /dev/null +++ b/src/server/room.cpp @@ -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 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 targets, int timeout) +{ + // TODO +} + +void Room::doNotify(const QList targets, int timeout) +{ + // TODO +} + +void Room::run() +{ + // TODO +} + diff --git a/src/server/room.h b/src/server/room.h new file mode 100644 index 00000000..959c2241 --- /dev/null +++ b/src/server/room.h @@ -0,0 +1,69 @@ +#ifndef _ROOM_H +#define _ROOM_H + +#include +#include +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 getPlayers() const; + ServerPlayer *findPlayer(uint id) const; + + void setGameLogic(GameLogic *logic); + GameLogic *getGameLogic() const; + // ====================================} + + void startGame(); + void doRequest(const QList targets, int timeout); + void doNotify(const QList 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 players; + GameLogic *logic; +}; + +#endif // _ROOM_H diff --git a/src/server/server.cpp b/src/server/server.cpp new file mode 100644 index 00000000..c08906fb --- /dev/null +++ b/src/server/server.cpp @@ -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 +} diff --git a/src/server/server.h b/src/server/server.h new file mode 100644 index 00000000..f6bf4f4d --- /dev/null +++ b/src/server/server.h @@ -0,0 +1,58 @@ +#ifndef _SERVER_H +#define _SERVER_H + +#include +#include +#include +#include + +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 rooms; + QHash players; + + lua_State *L; +}; + +extern Server *ServerInstance; + +#endif // _SERVER_H diff --git a/src/server/serverplayer.cpp b/src/server/serverplayer.cpp new file mode 100644 index 00000000..48ab5550 --- /dev/null +++ b/src/server/serverplayer.cpp @@ -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) +{ + ; +} diff --git a/src/server/serverplayer.h b/src/server/serverplayer.h new file mode 100644 index 00000000..af1def6b --- /dev/null +++ b/src/server/serverplayer.h @@ -0,0 +1,45 @@ +#ifndef _SERVERPLAYER_H +#define _SERVERPLAYER_H + +#include "player.h" +#include "router.h" +#include +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 diff --git a/src/swig/freekill.i b/src/swig/freekill.i new file mode 100644 index 00000000..06d7e955 --- /dev/null +++ b/src/swig/freekill.i @@ -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 getPlayers() const; + ServerPlayer *findPlayer(unsigned int id) const; + + void setGameLogic(GameLogic *logic); + GameLogic *getGameLogic() const; + // ====================================} + + void startGame(); + void doRequest(const QList targets, int timeout); + void doNotify(const QList targets, int timeout); +}; diff --git a/src/ui/qmlbackend.cpp b/src/ui/qmlbackend.cpp new file mode 100644 index 00000000..b95ebb6c --- /dev/null +++ b/src/ui/qmlbackend.cpp @@ -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); +} diff --git a/src/ui/qmlbackend.h b/src/ui/qmlbackend.h new file mode 100644 index 00000000..7eae0774 --- /dev/null +++ b/src/ui/qmlbackend.h @@ -0,0 +1,40 @@ +#ifndef _QMLBACKEND_H +#define _QMLBACKEND_H + +#include +#include +#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