diff --git a/build/premake/src/CHANGES.txt b/build/premake/src/CHANGES.txt new file mode 100644 index 0000000000..9a34d5f666 --- /dev/null +++ b/build/premake/src/CHANGES.txt @@ -0,0 +1,164 @@ +Premake Changelog +----------------- + +3.1 +* Added support for Visual Studio 2005 +* Added support for Windows resources to GNU make target +* Added path handling functions to Lua environment +* Added matchrecursive() for recursive file searches +* Added os.fileexists() function to Lua environment +* Added os.appendfile() function to Lua environment +* Changed `monoresgen` to `resgen` to keep up with Mono project +* Added `mono2` .NET compiler set for Mono .NET 2.0 support +* Feature 1096677: exclude files from matchfiles (package.excludes) +* Bug 1439463: VS2003 RTTI problem +* Bug 1439446: GNU Makefile problem under Mingw32 +* Bug 1422068: package.path="." causes bad makefiles +* Bug 1431530: makefile target fails when project path specified + +3.0 +* Upgraded Lua interpreter to version 5.0.1 +* The options table now stores simple values, rather than tables +* Completed MonoDevelop support +* Improved .NET resource handling for GNU generator +* Added unit test suite +* Merged Scott Graham unicode build flag patch +* Removed package.warninglevel in favor of extra-warnings flag +* Added package.targetprefix +* Overhauled structure of generated GNU makefiles +* Added --os command line option +* Fixed bug 1268588: Use gcc to link C packages +* Fixed bug 1363306: GNU C# should copy referenced DLLs + +2.4 +* Added chdir() to Lua script environment +* Merged Thomas Harning's patch for .NET resources on GNU +* Fixed bug 1194702: Can't put multiple packages in same directory +* Fixed bug in GNU shared library builds (doh!) +* Added target 'vs2002' to replace 'vs7' + +2.3 +* Added 'project.config[]' with 'bindir' and 'libdir' +* Merged Scott Graham's "warninglevel" patch. +* Fixed bug 1153484: Import lib in wrong directory. +* Fixed bug 1013352: Stack overflow with large projects. +* Fixed bug 945406: package.files, bad value = crash + +2.2 +* Worked around VS.NET bug for .NET assemblies > 64K. +* Added --very-verbose flag to GNU generator. +* GNU generator now supports assembly sources. + +2.1 +* File extension of generated binaries can now be set + with config.targetextension. +* Windows targets now handle .def files for DLLs. + +2.0 +* Can now specify build actions per file +* Include paths are now passed to VC7 resource compiler +* Removed _WIN32 define from Cygwin makefiles +* Added package.objdir to set intermediates directory +* Added rmdir() to Lua script environment +* A big bag of bug fixes + +1.9 +* Made verbose mode even more verbose. +* posix.c now builds properly as C. +* Fixed package dependency generation for GNU and VS2003. +* Display Lua version number in usage text. +* Fixed VS link between *.aspx and *.aspx.cs files. +* Fixed VS link between *.resx and *.cs files. +* Fixed *.d file generation for gcc 2.9x. +* Unified various help options under '--help'. +* Bin and Lib paths can now be arbitrarily long. +* linkoptions are now applied in VC6 and VC7 projects. + +1.8 +* Added support for ASP.NET projects. +* Fixed a bug in VC6 support for static libraries. +* matchfiles() now uses package path instead of script path. +* Added --verbose option. +* No longer apply no-rtti and no-exceptions to *.c files. + +1.7 +* Location of generated project files can now be specified with + the project.path variable. +* Inter-package dependencies are fixed for GNU makefiles. +* No longer need to execute in same directory as project script. +* Added "c" language specifier. +* Added support for .resx and .config files to C# projects. +* Added support for full assembly names in .NET references. +* Fixed handling of paths in package.target variable. +* Improved support for SharpDevelop. +* Started support for OS X. +* Added support for Digital Mars compiler. + +1.6.1 +* VS7 generator crashed if a package was built before one of its + dependencies. Now immediately assigns UUID before processing. + +1.6 +* Added support for Visual Studio 2003 and SharpDevelop. +* Added binaries directory as a reference path for VS7. + +1.5 +* Added initial support for building static libraries. +* Added "no-main" flag, prevents overriding WinMain() on + Windows builds. +* Added "--no-rtti" and "no-exceptions" build flags to + disable those C++ features. +* Display error message when project has no packages. +* Moved VC7 *.pdb files into intermediates directory. + +1.4 +* Bug fixes to the path manipulation routines. +* GNU makefiles are regenerated when premake scripts change. + +1.3 +* Added support for the Cygwin environment. +* Added "static-runtime" build flag to statically link against C/C++ + standard runtime libraries. +* Bug fixes to Visual Studio 6 and 7 generators and path reversing + algorithm. + +1.2 +* Standardized format of command-line options. +* Can now handle custom command-line options in script. +* Added new function findlib(). +* Added new C++ build flag "managed" for writing C++ .NET code. +* Can now use open-source C# compilers in VS6 generator. +* Several bug fixes to the VS7 generator. + +1.1 +* Added support for custom build configurations. Added "optimize", + "optimize-size", "optimize-speed", and "no-symbols" flags to control + build settings. +* Added matchfiles() to select files using wildcards. +* Added "unsafe" flag for C# projects. +* Added newpackage() function for creating new package objects inline, + instead of creating separate scripts. +* Changed include() to dopackage() and option() to addoption(). The old + versions have been kept for compatibility, but will be deprecated + eventually. +* Major cleanup of the source code. + +1.0 +* Fixed a bug related to the reference paths in VS7 C# projects. +* Display a warning message if a reference path can't be found. +* Automatically create bin and lib directories if they do not exist. +* GNU C# projects will now properly use the configured library paths. + +0.9.2 +* Added --with-mono and --with-pnet options. +* VS7 C# projects will now properly use the configured library paths. + +0.9.1 +* Switched to Lua (http://www.lua.org/) for project script parsing. +* Add support for custom project options. +* Changed 'type' to 'kind' to avoid conflict with Lua function of the same name. +* Changed 'conexe' to 'exe' because I liked it better. +* Changed 'library' to 'dll' for C# projects to keep things consistent. + +0.9.0 +* Initial public release. diff --git a/build/premake/src/LICENSE.txt b/build/premake/src/LICENSE.txt new file mode 100644 index 0000000000..5b6e7c66c2 --- /dev/null +++ b/build/premake/src/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/build/premake/src/Makefile b/build/premake/src/Makefile new file mode 100644 index 0000000000..dcad364f7a --- /dev/null +++ b/build/premake/src/Makefile @@ -0,0 +1,25 @@ +# Makefile autogenerated by premake +# Don't edit this file! Instead edit `premake.lua` then rerun `make` +# Options: +# CONFIG=[Debug|Release] + +ifndef CONFIG + CONFIG=Debug +endif + +export CONFIG + +.PHONY: all clean Premake + +all: Premake + +Makefile: premake.lua Src/premake.lua + @echo ==== Regenerating Makefiles ==== + @premake --file $^ --os linux --target gnu + +Premake: + @echo ==== Building Premake ==== + @$(MAKE) --no-print-directory -C Src + +clean: + @$(MAKE) --no-print-directory -C Src clean diff --git a/build/premake/src/Premake.Tests.nunit b/build/premake/src/Premake.Tests.nunit new file mode 100644 index 0000000000..325324170e --- /dev/null +++ b/build/premake/src/Premake.Tests.nunit @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/build/premake/src/Premake.dsw b/build/premake/src/Premake.dsw new file mode 100644 index 0000000000..657620752f --- /dev/null +++ b/build/premake/src/Premake.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Premake"=Src/Premake.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/build/premake/src/Premake.sln b/build/premake/src/Premake.sln new file mode 100644 index 0000000000..85d2c8aba0 --- /dev/null +++ b/build/premake/src/Premake.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Premake", "Src\Premake.vcproj", "{B33708C1-1744-52D6-8DCE-385E5CF8C348}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B33708C1-1744-52D6-8DCE-385E5CF8C348}.Debug|Win32.ActiveCfg = Debug|Win32 + {B33708C1-1744-52D6-8DCE-385E5CF8C348}.Debug|Win32.Build.0 = Debug|Win32 + {B33708C1-1744-52D6-8DCE-385E5CF8C348}.Release|Win32.ActiveCfg = Release|Win32 + {B33708C1-1744-52D6-8DCE-385E5CF8C348}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/build/premake/src/README.txt b/build/premake/src/README.txt new file mode 100644 index 0000000000..4c6383f58d --- /dev/null +++ b/build/premake/src/README.txt @@ -0,0 +1,20 @@ +PREMAKE v3.1 + +Copyright (C) 2002-2006 by Jason Perkins +Distributed under the GNU General Public License, see LICENSE.txt + +The Lua language and runtime library is (C) TeCGraf, PUC-Rio. +See their website at http://www.lua.org/ + + +BUILDING PREMAKE + + GNU make: type 'make' + + MS Visual C++ 6: open Premake.dsw and build. + + MS Visual C++ 2002-2005: open Premake.sln and build. + + +For questions, comments, or more information, visit the project +website at http://premake.sourceforge.net/ diff --git a/build/premake/src/Src/Lua/COPYRIGHT b/build/premake/src/Src/Lua/COPYRIGHT new file mode 100644 index 0000000000..eef88b050c --- /dev/null +++ b/build/premake/src/Src/Lua/COPYRIGHT @@ -0,0 +1,54 @@ +Lua Copyright Notice +-------------------- + +Lua is free and non-proprietary. +It can be used for both academic and commercial purposes at absolutely no cost. +There are no royalties or GNU-like "copyleft" restrictions. +Lua (probably) qualifies as Open Source software. +Nevertheless, Lua is not in the public domain and TeCGraf keeps its copyright. + +If you use Lua, please give us credit (a nice way to do this is to include a +Lua logo in a web page for your product), but we would appreciate *not* +receiving lengthy legal documents to sign. + +The legal details are below. + +=============================================================================== + +Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. + +Permission is hereby granted, without written agreement and without license +or royalty fees, to use, copy, modify, translate, and distribute +this software and its documentation (hereby called the "package") +for any purpose, including commercial applications, subject to +the following conditions: + + * The above copyright notice and this permission notice shall appear in all + copies or substantial portions of this package. + + * The origin of this package must not be misrepresented; you must not + claim that you wrote the original package. If you use this package in a + product, an acknowledgment in the product documentation would be greatly + appreciated (but it is not required). + + * Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original package. + +The authors specifically disclaim any warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a particular +purpose. The package provided hereunder is on an "as is" basis, and the +authors have no obligation to provide maintenance, support, updates, +enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the +authors be held liable to any party for direct, indirect, special, +incidental, or consequential damages arising out of the use of this package +and its documentation. + +The Lua language and this implementation have been entirely designed and written +by Waldemar Celes, Roberto Ierusalimschy, and Luiz Henrique de Figueiredo +at TeCGraf, PUC-Rio in Brazil. + +This implementation contains no third-party code. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/build/premake/src/Src/Lua/README b/build/premake/src/Src/Lua/README new file mode 100644 index 0000000000..81f767aee8 --- /dev/null +++ b/build/premake/src/Src/Lua/README @@ -0,0 +1,72 @@ +This is Lua 4.0. +See HISTORY for a summary of changes since the last version. + +* What is Lua? + ------------ + Lua is a powerful, light-weight programming language designed for extending + applications. Lua is also frequently used as a general-purpose, stand-alone + language. + + Lua combines simple procedural syntax (similar to Pascal) with powerful + data description constructs based on associative arrays and extensible + semantics. Lua is dynamically typed, interpreted from bytecodes, and has + automatic memory management, making it ideal for configuration, scripting, + and rapid prototyping. + + Lua is a language engine that you can embed into your application. + This means that, besides syntax and semantics, Lua has an API that + allows the application to exchange data with Lua programs and also to + extend Lua with C functions. In this sense, Lua can be regarded as a + language framework for building domain-specific languages. + + Lua is implemented as a small library of C functions, written in ANSI C, + and compiles unmodified in all known platforms. The implementation goals + are simplicity, efficiency, portability, and low embedding cost. + The result is a fast language engine with small footprint, making it + ideal in embedded systems too. + + Lua was awarded the first prize (technological category) in the + Second Compaq Award for Research and Development in Computer Science in 1997. + This award was a joint venture of Compaq Computer in Brazil, the Brazilian + Ministry of Science and Technology, and the Brazilian Academy of Sciences. + + Lua has been used in many different projects around the world. + For a short list, see http://www.tecgraf.puc-rio.br/lua/uses.html . + +* Availability + ------------ + Lua is freely available for both academic and commercial purposes and + can be downloaded from the sites below. See COPYRIGHT for details. + + Home page: http://www.tecgraf.puc-rio.br/lua/ + http://csg.uwaterloo.ca/~lhf/lua/ + In Brazil: ftp://ftp.tecgraf.puc-rio.br/pub/lua/ + In Canada: ftp://csg.uwaterloo.ca/pub/lhf/lua/ + In the US: ftp://ftp.freesoftware.com/pub/languages/lua/ + In Germany: ftp://ftp.uni-trier.de/pub/languages/lua/ + In Germany: ftp://ftp.gwdg.de/pub/languages/lua/ + In Greece: ftp://ftp.ntua.gr/pub/lang/lua/ + In Japan: ftp://ftp.u-aizu.ac.jp/pub/lang/lua/ + In Denmark: ftp://ftp.ucore.com/lua/dist + +* Installation + ------------ + See INSTALL. + +* Contacting the authors + ---------------------- + Lua was designed and implemented by Waldemar Celes, Roberto Ierusalimschy + and Luiz Henrique de Figueiredo. + They can be contacted by email at lua@tecgraf.puc-rio.br. + + Send your comments, questions, and bug reports to lua@tecgraf.puc-rio.br. + For reporting bugs, try also the mailing list: lua-l@tecgraf.puc-rio.br. + For more information about this list, including instructions on how to + subscribe, see http://www.tecgraf.puc-rio.br/lua/lua-l.html . + + Lua is developed at TeCGraf, the Computer Graphics Technology Group + of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro in Brazil). + TeCGraf is a laboratory of the Department of Computer Science. + Dozens of industrial products developed by TeCGraf use Lua. + +(end of README) diff --git a/build/premake/src/Src/Lua/lapi.c b/build/premake/src/Src/Lua/lapi.c new file mode 100644 index 0000000000..d5dd9ca465 --- /dev/null +++ b/build/premake/src/Src/Lua/lapi.c @@ -0,0 +1,922 @@ +/* +** $Id: lapi.c,v 1.235 2003/04/07 14:36:08 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lapi_c + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + +const char lua_ident[] = + "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#ifndef api_check +#define api_check(L, o) /*{ assert(o); }*/ +#endif + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + + +static TObject *negindex (lua_State *L, int idx) { + if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx != 0 && -idx <= L->top - L->base); + return L->top+idx; + } + else switch (idx) { /* pseudo-indices */ + case LUA_REGISTRYINDEX: return registry(L); + case LUA_GLOBALSINDEX: return gt(L); + default: { + TObject *func = (L->base - 1); + idx = LUA_GLOBALSINDEX - idx; + lua_assert(iscfunction(func)); + return (idx <= clvalue(func)->c.nupvalues) + ? &clvalue(func)->c.upvalue[idx-1] + : NULL; + } + } +} + + +static TObject *luaA_index (lua_State *L, int idx) { + if (idx > 0) { + api_check(L, idx <= L->top - L->base); + return L->base + idx - 1; + } + else { + TObject *o = negindex(L, idx); + api_check(L, o != NULL); + return o; + } +} + + +static TObject *luaA_indexAcceptable (lua_State *L, int idx) { + if (idx > 0) { + TObject *o = L->base+(idx-1); + api_check(L, idx <= L->stack_last - L->base); + if (o >= L->top) return NULL; + else return o; + } + else + return negindex(L, idx); +} + + +void luaA_pushobject (lua_State *L, const TObject *o) { + setobj2s(L->top, o); + incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res; + lua_lock(L); + if ((L->top - L->base + size) > LUA_MAXCSTACK) + res = 0; /* stack overflow */ + else { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + lua_lock(to); + api_checknelems(from, n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to->top, from->top + i); + api_incr_top(to); + } + lua_unlock(to); +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L->top, L1); + api_incr_top(L); + lua_unlock(L); + lua_userstateopen(L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return (L->top - L->base); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - L->base); + while (L->top < L->base + idx) + setnilvalue(L->top++); + L->top = L->base + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - L->base)); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = luaA_index(L, idx); + while (++p < L->top) setobjs2s(p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = luaA_index(L, idx); + for (q = L->top; q>p; q--) setobjs2s(q, q-1); + setobjs2s(p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + lua_lock(L); + api_checknelems(L, 1); + setobj(luaA_index(L, idx), L->top - 1); /* write barrier */ + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L->top, luaA_index(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL) ? 0 : iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TObject n; + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL && tonumber(o, &n)); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o))); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = luaA_indexAcceptable(L, index1); + StkId o2 = luaA_indexAcceptable(L, index2); + return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = luaA_indexAcceptable(L, index1); + o2 = luaA_indexAcceptable(L, index2); + i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ + : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = luaA_indexAcceptable(L, index1); + o2 = luaA_indexAcceptable(L, index2); + i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */ + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TObject n; + const TObject *o = luaA_indexAcceptable(L, idx); + if (o != NULL && tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL) && !l_isfalse(o); +} + + +LUA_API const char *lua_tostring (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) + return NULL; + else if (ttisstring(o)) + return svalue(o); + else { + const char *s; + lua_lock(L); /* `luaV_tostring' may create a new string */ + s = (luaV_tostring(L, o) ? svalue(o) : NULL); + luaC_checkGC(L); + lua_unlock(L); + return s; + } +} + + +LUA_API size_t lua_strlen (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) + return 0; + else if (ttisstring(o)) + return tsvalue(o)->tsv.len; + else { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0); + lua_unlock(L); + return l; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) return NULL; + switch (ttype(o)) { + case LUA_TUSERDATA: return (uvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) return NULL; + else { + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TFUNCTION: return clvalue(o); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(&cl->c.upvalue[n], L->top+n); + setclvalue(L->top, cl); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = luaA_index(L, idx); + setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0)); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = luaA_index(L, idx); + api_check(L, ttistable(o)); + setobj2s(L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_newtable (lua_State *L) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L->top, luaH_new(L, 0, 0)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TObject *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = luaA_indexAcceptable(L, objindex); + if (obj != NULL) { + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->uv.metatable; + break; + } + } + if (mt == NULL || mt == hvalue(defaultmeta(L))) + res = 0; + else { + sethvalue(L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = luaA_index(L, idx); + setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = luaA_index(L, idx); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */ + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = luaA_index(L, idx); + api_check(L, ttistable(o)); + setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */ + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TObject *obj, *mt; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + obj = luaA_index(L, objindex); + mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); + api_check(L, ttistable(mt)); + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = hvalue(mt); /* write barrier */ + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */ + break; + } + default: { + res = 0; /* cannot set */ + break; + } + } + L->top--; + lua_unlock(L); + return res; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 0; + lua_lock(L); + api_checknelems(L, 1); + o = luaA_index(L, idx); + L->top--; + api_check(L, ttistable(L->top)); + if (isLfunction(o)) { + res = 1; + clvalue(o)->l.g = *(L->top); + } + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc)); + c.func = L->top - (nargs+1); /* function to be called */ + c.nresults = nresults; + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0); + cl->c.f = c->func; + setclvalue(L->top, cl); /* push function */ + incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + int c; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(&z, reader, data, chunkname); + c = luaZ_lookahead(&z); + status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0])); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) { + int status; + TObject *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) { + luaU_dump(L, clvalue(o)->l.p, writer, data); + status = 1; + } + else + status = 0; + lua_unlock(L); + return status; +} + + +/* +** Garbage-collection functions +*/ + +/* GC values are expressed in Kbytes: #bytes/2^10 */ +#define GCscalel(x) ((x)>>10) +#define GCscale(x) (cast(int, GCscalel(x))) +#define GCunscale(x) (cast(lu_mem, x)<<10) + +LUA_API int lua_getgcthreshold (lua_State *L) { + int threshold; + lua_lock(L); + threshold = GCscale(G(L)->GCthreshold); + lua_unlock(L); + return threshold; +} + +LUA_API int lua_getgccount (lua_State *L) { + int count; + lua_lock(L); + count = GCscale(G(L)->nblocks); + lua_unlock(L); + return count; +} + +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { + lua_lock(L); + if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM)) + G(L)->GCthreshold = MAX_LUMEM; + else + G(L)->GCthreshold = GCunscale(newthreshold); + luaC_checkGC(L); + lua_unlock(L); +} + + +/* +** miscellaneous functions +*/ + + +LUA_API const char *lua_version (void) { + return LUA_VERSION; +} + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + if (n >= 2) { + luaV_concat(L, n, L->top - L->base - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L->top, luaS_newlstr(L, NULL, 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size); + setuvalue(L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + +LUA_API int lua_pushupvalues (lua_State *L) { + Closure *func; + int n, i; + lua_lock(L); + api_check(L, iscfunction(L->base - 1)); + func = clvalue(L->base - 1); + n = func->c.nupvalues; + luaD_checkstack(L, n + LUA_MINSTACK); + for (i=0; itop, &func->c.upvalue[i]); + L->top++; + } + lua_unlock(L); + return n; +} + + +static const char *aux_upvalue (lua_State *L, int funcindex, int n, + TObject **val) { + Closure *f; + StkId fi = luaA_index(L, funcindex); + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (n > f->c.nupvalues) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (n > p->sizeupvalues) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + setobj2s(L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + api_checknelems(L, 1); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + L->top--; + setobj(val, L->top); /* write barrier */ + } + lua_unlock(L); + return name; +} + diff --git a/build/premake/src/Src/Lua/lapi.h b/build/premake/src/Src/Lua/lapi.h new file mode 100644 index 0000000000..d12612f304 --- /dev/null +++ b/build/premake/src/Src/Lua/lapi.h @@ -0,0 +1,16 @@ +/* +** $Id: lapi.h,v 1.21 2002/03/04 21:29:41 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +void luaA_pushobject (lua_State *L, const TObject *o); + +#endif diff --git a/build/premake/src/Src/Lua/lauxlib.c b/build/premake/src/Src/Lua/lauxlib.c new file mode 100644 index 0000000000..ee2d1339b0 --- /dev/null +++ b/build/premake/src/Src/Lua/lauxlib.c @@ -0,0 +1,591 @@ +/* +** $Id: lauxlib.c,v 1.100 2003/04/07 14:35:00 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c + +#include "lua.h" + +#include "lauxlib.h" + + +/* number of prereserved references (for internal use) */ +#define RESERVED_REFS 2 + +/* reserved references */ +#define FREELIST_REF 1 /* free list of references */ +#define ARRAYSIZE_REF 2 /* array sizes */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + lua_getstack(L, 0, &ar); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling `%s' on bad self (%s)", ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to `%s' (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, lua_typename(L, lua_type(L,narg))); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Snl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { + int i; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + return -1; /* name not found */ +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushstring(L, tname); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */ + lua_pushvalue(L, -1); + lua_pushstring(L, tname); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ + return 1; +} + + +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + const char *tn; + if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ + tn = lua_tostring(L, -1); + if (tn && (strcmp(tn, tname) == 0)) { + lua_pop(L, 1); + return lua_touserdata(L, ud); + } + else { + lua_pop(L, 1); + return NULL; + } +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tostring(L, narg); + if (!s) tag_error(L, narg, LUA_TSTRING); + if (len) *len = lua_strlen(L, narg); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + if (lua_isnoneornil(L, narg)) return def; + else return luaL_checknumber(L, narg); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup) { + if (libname) { + lua_pushstring(L, libname); + lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */ + if (lua_isnil(L, -1)) { /* no? */ + lua_pop(L, 1); + lua_newtable(L); /* create it */ + lua_pushstring(L, libname); + lua_pushvalue(L, -2); + lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */ + } + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + lua_pushstring(L, l->name); + for (i=0; ifunc, nup); + lua_settable(L, -(nup+3)); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +static int checkint (lua_State *L, int topop) { + int n = (int)lua_tonumber(L, -1); + if (n == 0 && !lua_isnumber(L, -1)) n = -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_pop(L, 1); /* remove nil */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(N).__mode = "k" */ + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ + } +} + + +void luaL_setn (lua_State *L, int t, int n) { + t = abs_index(L, t); + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushnumber(L, (lua_Number)n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushnumber(L, (lua_Number)n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +int luaL_getn (lua_State *L, int t) { + int n; + t = abs_index(L, t); + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + for (n = 1; ; n++) { /* else must count elements */ + lua_rawgeti(L, t, n); + if (lua_isnil(L, -1)) break; + lua_pop(L, 1); + } + lua_pop(L, 1); + return n - 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_putchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl = lua_strlen(L, -1); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, lua_tostring(L, -1), vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ + } + else { /* no free elements */ + ref = luaL_getn(L, t); + if (ref < RESERVED_REFS) + ref = RESERVED_REFS; /* skip reserved references */ + ref++; /* create new reference */ + luaL_setn(L, t, ref); + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushnumber(L, (lua_Number)ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, int fnameindex) { + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + } + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */ + c = ungetc(getc(lf.f), lf.f); + if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ + fclose(lf.f); + lf.f = fopen(filename, "rb"); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ + } + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** compatibility code +** ======================================================= +*/ + + +static void callalert (lua_State *L, int status) { + if (status != 0) { + lua_getglobal(L, "_ALERT"); + if (lua_isfunction(L, -1)) { + lua_insert(L, -2); + lua_call(L, 1, 0); + } + else { /* no _ALERT function; print it on stderr */ + fprintf(stderr, "%s\n", lua_tostring(L, -2)); + lua_pop(L, 2); /* remove error message and _ALERT */ + } + } +} + + +static int aux_do (lua_State *L, int status) { + if (status == 0) { /* parse OK? */ + status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ + } + callalert(L, status); + return status; +} + + +LUALIB_API int lua_dofile (lua_State *L, const char *filename) { + return aux_do(L, luaL_loadfile(L, filename)); +} + + +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + return aux_do(L, luaL_loadbuffer(L, buff, size, name)); +} + + +LUALIB_API int lua_dostring (lua_State *L, const char *str) { + return lua_dobuffer(L, str, strlen(str), str); +} + +/* }====================================================== */ diff --git a/build/premake/src/Src/Lua/lauxlib.h b/build/premake/src/Src/Lua/lauxlib.h new file mode 100644 index 0000000000..450e16c720 --- /dev/null +++ b/build/premake/src/Src/Lua/lauxlib.h @@ -0,0 +1,145 @@ +/* +** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + + +typedef struct luaL_reg { + const char *name; + lua_CFunction func; +} luaL_reg; + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup); +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 int luaL_typerror (lua_State *L, int narg, const char *tname); +LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l); +LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg); +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def); + +LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg); +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); +LUALIB_API void luaL_checkany (lua_State *L, int narg); + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname); +LUALIB_API void luaL_getmetatable (lua_State *L, 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_findstring (const char *st, const char *const lst[]); + +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_getn (lua_State *L, int t); +LUALIB_API void luaL_setn (lua_State *L, int t, int n); + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, + const char *name); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \ + luaL_argerror(L, numarg,extramsg) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n)) +#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n)) +#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,(lua_Number)(d))) +#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,(lua_Number)(d))) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#ifndef LUAL_BUFFERSIZE +#define LUAL_BUFFERSIZE BUFSIZ +#endif + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_putchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); +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); + + +/* }====================================================== */ + + + +/* +** Compatibility macros and functions +*/ + +LUALIB_API int lua_dofile (lua_State *L, const char *filename); +LUALIB_API int lua_dostring (lua_State *L, const char *str); +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz, + const char *n); + + +#define luaL_check_lstr luaL_checklstring +#define luaL_opt_lstr luaL_optlstring +#define luaL_check_number luaL_checknumber +#define luaL_opt_number luaL_optnumber +#define luaL_arg_check luaL_argcheck +#define luaL_check_string luaL_checkstring +#define luaL_opt_string luaL_optstring +#define luaL_check_int luaL_checkint +#define luaL_check_long luaL_checklong +#define luaL_opt_int luaL_optint +#define luaL_opt_long luaL_optlong + + +#endif + + diff --git a/build/premake/src/Src/Lua/lbaselib.c b/build/premake/src/Src/Lua/lbaselib.c new file mode 100644 index 0000000000..b6a4baedc2 --- /dev/null +++ b/build/premake/src/Src/Lua/lbaselib.c @@ -0,0 +1,675 @@ +/* +** $Id: lbaselib.c,v 1.130b 2003/04/03 13:35:34 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, "`tostring' must return a string to `print'"); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + luaL_checkany(L, 1); + if (!lua_isstring(L, 1) || level == 0) + lua_pushvalue(L, 1); /* propagate error message without changes */ + else { /* add extra information */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = luaL_optint(L, 1, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int aux_getfenv (lua_State *L) { + lua_getfenv(L, -1); + lua_pushliteral(L, "__fenv"); + lua_rawget(L, -2); + return !lua_isnil(L, -1); +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L); + if (!aux_getfenv(L)) /* __fenv not defined? */ + lua_pop(L, 1); /* remove it, to return real environment */ + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L); + if (aux_getfenv(L)) /* __fenv defined? */ + luaL_error(L, "`setfenv' cannot change a protected environment"); + else + lua_pop(L, 2); /* remove __fenv and real environment table */ + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) + lua_replace(L, LUA_GLOBALSINDEX); + else if (lua_setfenv(L, -2) == 0) + luaL_error(L, "`setfenv' cannot change environment of given function"); + return 0; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushnumber(L, (lua_Number)lua_getgccount(L)); + lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L)); + return 2; +} + + +static int luaB_collectgarbage (lua_State *L) { + lua_setgcthreshold(L, luaL_optint(L, 1, 0)); + return 0; +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, lua_typename(L, lua_type(L, 1))); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushliteral(L, "next"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int luaB_ipairs (lua_State *L) { + lua_Number i = lua_tonumber(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ + lua_pushliteral(L, "ipairs"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnumber(L, 0); /* and initial value */ + return 3; + } + else { /* `for' step */ + i++; /* next value */ + lua_pushnumber(L, i); + lua_rawgeti(L, 1, (int)i); + return (lua_isnil(L, -1)) ? 0 : 2; + } +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + int status = luaL_loadfile(L, fname); + if (status != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + lua_settop(L, 1); + return 1; +} + + +static int luaB_unpack (lua_State *L) { + int n, i; + luaL_checktype(L, 1, LUA_TTABLE); + n = luaL_getn(L, 1); + luaL_checkstack(L, n, "table too big to unpack"); + for (i=1; i<=n; i++) /* push arg[1...n] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + char buff[128]; + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + return 1; + case LUA_TSTRING: + lua_pushvalue(L, 1); + return 1; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + return 1; + case LUA_TTABLE: + sprintf(buff, "table: %p", lua_topointer(L, 1)); + break; + case LUA_TFUNCTION: + sprintf(buff, "function: %p", lua_topointer(L, 1)); + break; + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); + break; + case LUA_TTHREAD: + sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + return 1; + } + lua_pushstring(L, buff); + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +/* +** {====================================================== +** `require' function +** ======================================================= +*/ + + +/* name of global that holds table with loaded packages */ +#define REQTAB "_LOADED" + +/* name of global that holds the search path for packages */ +#define LUA_PATH "LUA_PATH" + +#ifndef LUA_PATH_SEP +#define LUA_PATH_SEP ';' +#endif + +#ifndef LUA_PATH_MARK +#define LUA_PATH_MARK '?' +#endif + +#ifndef LUA_PATH_DEFAULT +#define LUA_PATH_DEFAULT "?;?.lua" +#endif + + +static const char *getpath (lua_State *L) { + const char *path; + lua_getglobal(L, LUA_PATH); /* try global variable */ + path = lua_tostring(L, -1); + lua_pop(L, 1); + if (path) return path; + path = getenv(LUA_PATH); /* else try environment variable */ + if (path) return path; + return LUA_PATH_DEFAULT; /* else use default */ +} + + +static const char *pushnextpath (lua_State *L, const char *path) { + const char *l; + if (*path == '\0') return NULL; /* no more paths */ + if (*path == LUA_PATH_SEP) path++; /* skip separator */ + l = strchr(path, LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path+strlen(path); + lua_pushlstring(L, path, l - path); /* directory name */ + return l; +} + + +static void pushcomposename (lua_State *L) { + const char *path = lua_tostring(L, -1); + const char *wild; + int n = 1; + while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { + /* is there stack space for prefix, name, and eventual last sufix? */ + luaL_checkstack(L, 3, "too many marks in a path component"); + lua_pushlstring(L, path, wild - path); /* push prefix */ + lua_pushvalue(L, 1); /* push package name (in place of MARK) */ + path = wild + 1; /* continue after MARK */ + n += 2; + } + lua_pushstring(L, path); /* push last sufix (`n' already includes this) */ + lua_concat(L, n); +} + + +static int luaB_require (lua_State *L) { + const char *path; + int status = LUA_ERRFILE; /* not found (yet) */ + luaL_checkstring(L, 1); + lua_settop(L, 1); + lua_getglobal(L, REQTAB); + if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); + path = getpath(L); + lua_pushvalue(L, 1); /* check package's name in book-keeping table */ + lua_rawget(L, 2); + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded; return its result */ + else { /* must load it */ + while (status == LUA_ERRFILE) { + lua_settop(L, 3); /* reset stack position */ + if ((path = pushnextpath(L, path)) == NULL) break; + pushcomposename(L); + status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ + } + } + switch (status) { + case 0: { + lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ + lua_insert(L, -2); /* put it below function */ + lua_pushvalue(L, 1); + lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ + lua_call(L, 0, 1); /* run loaded module */ + lua_insert(L, -2); /* put result below previous name */ + lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ + if (lua_isnil(L, -1)) { /* no/nil return? */ + lua_pushboolean(L, 1); + lua_replace(L, -2); /* replace to true */ + } + lua_pushvalue(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, 2); /* mark it as loaded */ + return 1; /* return value */ + } + case LUA_ERRFILE: { /* file not found */ + return luaL_error(L, "could not load package `%s' from path `%s'", + lua_tostring(L, 1), getpath(L)); + } + default: { + return luaL_error(L, "error loading package `%s' (%s)", + lua_tostring(L, 1), lua_tostring(L, -1)); + } + } +} + +/* }====================================================== */ + + +static const luaL_reg base_funcs[] = { + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"setmetatable", luaB_setmetatable}, + {"getfenv", luaB_getfenv}, + {"setfenv", luaB_setfenv}, + {"next", luaB_next}, + {"ipairs", luaB_ipairs}, + {"pairs", luaB_pairs}, + {"print", luaB_print}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"assert", luaB_assert}, + {"unpack", luaB_unpack}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"pcall", luaB_pcall}, + {"xpcall", luaB_xpcall}, + {"collectgarbage", luaB_collectgarbage}, + {"gcinfo", luaB_gcinfo}, + {"loadfile", luaB_loadfile}, + {"dofile", luaB_dofile}, + {"loadstring", luaB_loadstring}, + {"require", luaB_require}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + lua_xmove(L, co, narg); + status = lua_resume(co, narg); + if (status == 0) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); + } + return 1; +} + + +static const luaL_reg co_funcs[] = { + {"create", luaB_cocreate}, + {"wrap", luaB_cowrap}, + {"resume", luaB_coresume}, + {"yield", luaB_yield}, + {"status", luaB_costatus}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +static void base_open (lua_State *L) { + lua_pushliteral(L, "_G"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ + lua_pushliteral(L, "_VERSION"); + lua_pushliteral(L, LUA_VERSION); + lua_rawset(L, -3); /* set global _VERSION */ + /* `newproxy' needs a weaktable as upvalue */ + lua_pushliteral(L, "newproxy"); + lua_newtable(L); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(w).__mode = "k" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_rawset(L, -3); /* set global `newproxy' */ + lua_rawset(L, -1); /* set global _G */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); + lua_newtable(L); + lua_setglobal(L, REQTAB); + return 0; +} + diff --git a/build/premake/src/Src/Lua/lcode.c b/build/premake/src/Src/Lua/lcode.c new file mode 100644 index 0000000000..d626ecd60e --- /dev/null +++ b/build/premake/src/Src/Lua/lcode.c @@ -0,0 +1,714 @@ +/* +** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget && /* no jumps to current position? */ + GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pto = GETARG_B(*previous); + if (pfrom <= from && from <= pto+1) { /* can connect both? */ + if (from+n-1 > pto) + SETARG_B(*previous, from+n-1); + return; + } + } + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void luaK_fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int luaK_getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT)) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list, int cond) { + for (; list != NO_JUMP; list = luaK_getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; + } + return 0; /* not found */ +} + + +static void patchtestreg (Instruction *i, int reg) { + if (reg == NO_REG) reg = GETARG_B(*i); + SETARG_A(*i, reg); +} + + +static void luaK_patchlistaux (FuncState *fs, int list, + int ttarget, int treg, int ftarget, int freg, int dtarget) { + while (list != NO_JUMP) { + int next = luaK_getjump(fs, list); + Instruction *i = getjumpcontrol(fs, list); + if (GET_OPCODE(*i) != OP_TEST) { + lua_assert(dtarget != NO_JUMP); + luaK_fixjump(fs, list, dtarget); /* jump to default target */ + } + else { + if (GETARG_C(*i)) { + lua_assert(ttarget != NO_JUMP); + patchtestreg(i, treg); + luaK_fixjump(fs, list, ttarget); + } + else { + lua_assert(ftarget != NO_JUMP); + patchtestreg(i, freg); + luaK_fixjump(fs, list, ftarget); + } + } + list = next; + } +} + + +static void luaK_dischargejpc (FuncState *fs) { + luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + luaK_fixjump(fs, list, l2); + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast(lu_byte, newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (reg >= fs->nactvar && reg < MAXSTACK) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->info); +} + + +static int addk (FuncState *fs, TObject *k, TObject *v) { + const TObject *idx = luaH_get(fs->h, k); + if (ttisnumber(idx)) { + lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v)); + return cast(int, nvalue(idx)); + } + else { /* constant not found; create a new entry */ + Proto *f = fs->f; + luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, + MAXARG_Bx, "constant table overflow"); + setobj2n(&f->k[fs->nk], v); + setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk)); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TObject o; + setsvalue(&o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TObject o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int nil_constant (FuncState *fs) { + TObject k, v; + setnilvalue(&v); + sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */ + return addk(fs, &k, &v); +} + + +void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + if (nresults == 1) { /* `regular' expression? */ + e->k = VNONRELOC; + e->info = GETARG_A(getcode(fs, e)); + } + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->aux); + freereg(fs, e->info); + e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); + e->k = VRELOCABLE; + break; + } + case VCALL: { + luaK_setcallreturns(fs, e, 1); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->info); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->info) + luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { + int fj = NO_JUMP; /* first jump (over LOAD ops.) */ + if (e->k != VJMP) + fj = luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); + luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); + } + e->f = e->t = NO_JUMP; + e->info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + luaK_exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->info; /* exp is already in a register */ + if (e->info >= fs->nactvar) { /* reg. is not a local? */ + luaK_exp2reg(fs, e, e->info); /* put value on it */ + return e->info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VNIL: { + if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */ + e->info = nil_constant(fs); + e->k = VK; + return e->info + MAXSTACK; + } + else break; + } + case VK: { + if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */ + return e->info + MAXSTACK; + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, exp); + luaK_exp2reg(fs, exp, var->info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, exp); + luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, exp); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, exp); + luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, exp); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int func; + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + func = fs->freereg; + luaK_reserveregs(fs, 2); + luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->info); + lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VFALSE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ +} + + +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VTRUE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + pc = e->info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + if (op == OPR_MINUS) { + luaK_exp2val(fs, e); + if (e->k == VK && ttisnumber(&fs->f->k[e->info])) + e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info])); + else { + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0); + e->k = VRELOCABLE; + } + } + else /* op == NOT */ + codenot(fs, e); +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + luaK_patchtohere(fs, v->t); + v->t = NO_JUMP; + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + luaK_patchtohere(fs, v->f); + v->f = NO_JUMP; + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +static void codebinop (FuncState *fs, expdesc *res, BinOpr op, + int o1, int o2) { + if (op <= OPR_POW) { /* arithmetic operator? */ + OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */ + res->info = luaK_codeABC(fs, opc, 0, o1, o2); + res->k = VRELOCABLE; + } + else { /* test operator */ + static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; + int cond = 1; + if (op >= OPR_GT) { /* `>' or `>='? */ + int temp; /* exchange args and replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + } + else if (op == OPR_NE) cond = 0; + res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2); + res->k = VJMP; + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e1->f, e2->f); + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e1->t, e2->t); + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->info); + e1->k = e2->k; e1->info = e2->info; + } + else { + luaK_exp2nextreg(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); + e1->k = VRELOCABLE; + } + break; + } + default: { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + codebinop(fs, e1, op, o1, o2); + } + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + luaK_dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + diff --git a/build/premake/src/Src/Lua/lcode.h b/build/premake/src/Src/Lua/lcode.h new file mode 100644 index 0000000000..74908c6580 --- /dev/null +++ b/build/premake/src/Src/Lua/lcode.h @@ -0,0 +1,74 @@ +/* +** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp $ +** 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 +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + +#define binopistest(op) ((op) >= OPR_NE) + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +int luaK_code (FuncState *fs, Instruction i, int line); +int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +void luaK_fixline (FuncState *fs, int line); +void luaK_nil (FuncState *fs, int from, int n); +void luaK_reserveregs (FuncState *fs, int n); +void luaK_checkstack (FuncState *fs, int n); +int luaK_stringK (FuncState *fs, TString *s); +int luaK_numberK (FuncState *fs, lua_Number r); +void luaK_dischargevars (FuncState *fs, expdesc *e); +int luaK_exp2anyreg (FuncState *fs, expdesc *e); +void luaK_exp2nextreg (FuncState *fs, expdesc *e); +void luaK_exp2val (FuncState *fs, expdesc *e); +int luaK_exp2RK (FuncState *fs, expdesc *e); +void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +void luaK_goiftrue (FuncState *fs, expdesc *e); +void luaK_goiffalse (FuncState *fs, expdesc *e); +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); +int luaK_jump (FuncState *fs); +void luaK_patchlist (FuncState *fs, int list, int target); +void luaK_patchtohere (FuncState *fs, int list); +void luaK_concat (FuncState *fs, int *l1, int l2); +int luaK_getlabel (FuncState *fs); +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); + + +#endif diff --git a/build/premake/src/Src/Lua/ldblib.c b/build/premake/src/Src/Lua/ldblib.c new file mode 100644 index 0000000000..6dc9b64cfc --- /dev/null +++ b/build/premake/src/Src/Lua/ldblib.c @@ -0,0 +1,299 @@ +/* +** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, i); + lua_pushstring(L, v); + lua_rawset(L, -3); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushstring(L, i); + lua_pushnumber(L, (lua_Number)v); + lua_rawset(L, -3); +} + + +static int getinfo (lua_State *L) { + lua_Debug ar; + const char *options = luaL_optstring(L, 2, "flnSu"); + if (lua_isnumber(L, 1)) { + if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, 1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, 1); + } + else + return luaL_argerror(L, 1, "function or level expected"); + if (!lua_getinfo(L, options, &ar)) + return luaL_argerror(L, 2, "invalid option"); + lua_newtable(L); + for (; *options; options++) { + switch (*options) { + case 'S': + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabss(L, "what", ar.what); + break; + case 'l': + settabsi(L, "currentline", ar.currentline); + break; + case 'u': + settabsi(L, "nups", ar.nups); + break; + case 'n': + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + break; + case 'f': + lua_pushliteral(L, "func"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + break; + } + } + return 1; /* return table */ +} + + +static int getlocal (lua_State *L) { + lua_Debug ar; + const char *name; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); + if (name) { + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int setlocal (lua_State *L) { + lua_Debug ar; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + luaL_checkany(L, 3); + lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushnumber(L, (lua_Number)ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } + else + lua_pop(L, 1); /* pop result from gettable */ +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int sethook (lua_State *L) { + if (lua_isnoneornil(L, 1)) { + lua_settop(L, 1); + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, 2); + int count = luaL_optint(L, 3, 0); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_sethook(L, hookf, makemask(smask, count), count); + } + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, 1); + lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ + return 0; +} + + +static int gethook (lua_State *L) { + char buff[5]; + int mask = lua_gethookmask(L); + lua_Hook hook = lua_gethook(L); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); + return 3; +} + + +static int debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + lua_dostring(L, buffer); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int errorfb (lua_State *L) { + int level = 1; /* skip level 0 (it's this function) */ + int firstpart = 1; /* still before eventual `...' */ + lua_Debug ar; + if (lua_gettop(L) == 0) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, 1)) return 1; /* no string message */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + switch (*ar.namewhat) { + case 'g': /* global */ + case 'l': /* local */ + case 'f': /* field */ + case 'm': /* method */ + lua_pushfstring(L, " in function `%s'", ar.name); + break; + default: { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + } + lua_concat(L, lua_gettop(L)); + } + lua_concat(L, lua_gettop(L)); + return 1; +} + + +static const luaL_reg dblib[] = { + {"getlocal", getlocal}, + {"getinfo", getinfo}, + {"gethook", gethook}, + {"getupvalue", getupvalue}, + {"sethook", sethook}, + {"setlocal", setlocal}, + {"setupvalue", setupvalue}, + {"debug", debug}, + {"traceback", errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); + lua_pushliteral(L, "_TRACEBACK"); + lua_pushcfunction(L, errorfb); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/build/premake/src/Src/Lua/ldebug.c b/build/premake/src/Src/Lua/ldebug.c new file mode 100644 index 0000000000..8e511e3bd9 --- /dev/null +++ b/build/premake/src/Src/Lua/ldebug.c @@ -0,0 +1,585 @@ +/* +** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define ldebug_c + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (CallInfo *ci, const char **name); + + +#define isLua(ci) (!((ci)->state & CI_C)) + + +static int currentpc (CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci->state & CI_HASFRAME) /* function has a frame? */ + ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */ + /* function's pc is saved */ + return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); +} + + +static int currentline (CallInfo *ci) { + int pc = currentpc(ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +void luaG_inithooks (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */ + currentpc(ci); + L->hookinit = 1; +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast(lu_byte, mask); + L->hookinit = 0; + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + lua_lock(L); + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (!(ci->state & CI_C)) /* Lua function? */ + level -= ci->u.l.tailcalls; /* skip lost tail calls */ + } + if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ + else if (level < 0) { /* level is of a lost tail call */ + status = 1; + ar->i_ci = 0; + } + else { + status = 1; + ar->i_ci = ci - L->base_ci; + } + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + CallInfo *ci; + Proto *fp; + lua_lock(L); + name = NULL; + ci = L->base_ci + ar->i_ci; + fp = getluaproto(ci); + if (fp) { /* is a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(ci)); + if (name) + luaA_pushobject(L, ci->base+(n-1)); /* push value */ + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + CallInfo *ci; + Proto *fp; + lua_lock(L); + name = NULL; + ci = L->base_ci + ar->i_ci; + fp = getluaproto(ci); + L->top--; /* pop new value */ + if (fp) { /* is a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(ci)); + if (!name || name[0] == '(') /* `(' starts private locals */ + name = NULL; + else + setobjs2s(ci->base+(n-1), L->top); + } + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, StkId func) { + Closure *cl = clvalue(func); + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->lineDefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static const char *travglobals (lua_State *L, const TObject *o) { + Table *g = hvalue(gt(L)); + int i = sizenode(g); + while (i--) { + Node *n = gnode(g, i); + if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n))) + return getstr(tsvalue(gkey(n))); + } + return NULL; +} + + +static void info_tailcall (lua_State *L, lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; + setnilvalue(L->top); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + StkId f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = clvalue(f)->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + /* try to find a global name */ + if ((ar->name = travglobals(L, f)) != NULL) + ar->namewhat = "global"; + else ar->namewhat = ""; /* not found */ + } + break; + } + case 'f': { + setobj2s(L->top, f); + break; + } + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status = 1; + lua_lock(L); + if (*what == '>') { + StkId f = L->top - 1; + if (!ttisfunction(f)) + luaG_runerror(L, "value for `lua_getinfo' is not a function"); + status = auxgetinfo(L, what + 1, ar, f, NULL); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + CallInfo *ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->base - 1)); + status = auxgetinfo(L, what, ar, ci->base - 1, ci); + } + else + info_tailcall(L, ar); + if (strchr(what, 'f')) incr_top(L); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize); + check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +static int checkopenop (const Proto *pt, int pc) { + Instruction i = pt->code[pc+1]; + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: { + check(GETARG_B(i) == 0); + return 1; + } + case OP_SETLISTO: return 1; + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkRK (const Proto *pt, int r) { + return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek)); +} + + +static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + const Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + if (testOpMode(op, OpModeBreg)) { + checkreg(pt, b); + } + else if (testOpMode(op, OpModeBrk)) + check(checkRK(pt, b)); + if (testOpMode(op, OpModeCrk)) + check(checkRK(pt, c)); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (testOpMode(op, OpModeK)) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + break; + } + } + if (testOpMode(op, OpModesetA)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testOpMode(op, OpModeT)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + /* `c' is a register, and at least two operands */ + check(c < MAXSTACK && b < c); + break; + } + case OP_TFORLOOP: + checkreg(pt, a+c+5); + if (reg >= a) last = pc; /* affect all registers above base */ + /* go through */ + case OP_FORLOOP: + checkreg(pt, a+2); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1); + break; + } + case OP_CLOSURE: { + int nup; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (; nup>0; nup--) { + OpCode op1 = GET_OPCODE(pt->code[pc+nup]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return luaG_symbexec(pt, pt->sizecode, NO_REG); +} + + +static const char *kname (Proto *p, int c) { + c = c - MAXSTACK; + if (c >= 0 && ttisstring(&p->k[c])) + return svalue(&p->k[c]); + else + return "?"; +} + + +static const char *getobjname (CallInfo *ci, int stackpos, const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL) + return getobjname(ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TObject *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TObject *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L->ci, o - L->base, &name) : NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s `%s' (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1)) p1 = p2; + lua_assert(!ttisstring(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) { + TObject temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); + return 0; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +void luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L->top, L->top - 1); /* move argument */ + setobjs2s(L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/build/premake/src/Src/Lua/ldebug.h b/build/premake/src/Src/Lua/ldebug.h new file mode 100644 index 0000000000..7ff395839c --- /dev/null +++ b/build/premake/src/Src/Lua/ldebug.h @@ -0,0 +1,31 @@ +/* +** $Id: ldebug.h,v 1.32 2002/11/18 11:01:55 roberto Exp $ +** 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) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +void luaG_inithooks (lua_State *L); +void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); +void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); +void luaG_runerror (lua_State *L, const char *fmt, ...); +void luaG_errormsg (lua_State *L); +int luaG_checkcode (const Proto *pt); + + +#endif diff --git a/build/premake/src/Src/Lua/ldo.c b/build/premake/src/Src/Lua/ldo.c new file mode 100644 index 0000000000..a6d344cd57 --- /dev/null +++ b/build/premake/src/Src/Lua/ldo.c @@ -0,0 +1,471 @@ +/* +** $Id: ldo.c,v 1.217a 2003/04/03 13:35:34 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions (based on long jumps) +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + jmp_buf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(oldtop, luaS_new(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(oldtop, luaS_new(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + longjmp(L->errorJmp->b, 1); + } + else { + G(L)->panic(L); + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + if (setjmp(lj.b) == 0) + (*f)(L, ud); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + + +static void restore_stack_limit (lua_State *L) { + L->stack_last = L->stack+L->stacksize-1; + if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ + int inuse = (L->ci - L->base_ci); + if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUA_MAXCALLS); + } +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TObject *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + } + L->base = L->ci->base; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TObject *oldstack = L->stack; + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); + L->stacksize = newsize; + L->stack_last = L->stack+newsize-1-EXTRA_STACK; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = cast(unsigned short, newsize); + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci; +} + + +void luaD_growstack (lua_State *L, int n) { + if (n <= L->stacksize) /* double size is enough? */ + luaD_reallocstack(L, 2*L->stacksize); + else + luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK); +} + + +static void luaD_growCI (lua_State *L) { + if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUA_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = L->ci - L->base_ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static void adjust_varargs (lua_State *L, int nfixargs, StkId base) { + int i; + Table *htab; + TObject nname; + int actual = L->top - base; /* actual number of arguments */ + if (actual < nfixargs) { + luaD_checkstack(L, nfixargs - actual); + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); + } + actual -= nfixargs; /* number of extra arguments */ + htab = luaH_new(L, actual, 1); /* create `arg' table */ + for (i=0; itop - actual + i); + /* store counter in field `n' */ + setsvalue(&nname, luaS_newliteral(L, "n")); + setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual)); + L->top -= actual; /* remove extra elements from the stack */ + sethvalue(L->top, htab); + incr_top(L); +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(func, tm); /* tag method is the new function to be called */ + return func; +} + + +StkId luaD_precall (lua_State *L, StkId func) { + LClosure *cl; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + if (L->ci + 1 == L->end_ci) luaD_growCI(L); + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); + cl = &clvalue(func)->l; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + Proto *p = cl->p; + if (p->is_vararg) /* varargs? */ + adjust_varargs(L, p->numparams, func+1); + luaD_checkstack(L, p->maxstacksize); + ci = ++L->ci; /* now `enter' new function */ + L->base = L->ci->base = restorestack(L, funcr) + 1; + ci->top = L->base + p->maxstacksize; + ci->u.l.savedpc = p->code; /* starting point */ + ci->u.l.tailcalls = 0; + ci->state = CI_SAVEDPC; + while (L->top < ci->top) + setnilvalue(L->top++); + L->top = ci->top; + return NULL; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = ++L->ci; /* now `enter' new function */ + L->base = L->ci->base = restorestack(L, funcr) + 1; + ci->top = L->top + LUA_MINSTACK; + ci->state = CI_C; /* a C function */ + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); +#ifdef LUA_COMPATUPVALUES + lua_pushupvalues(L); +#endif + n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */ + lua_lock(L); + return L->top - n; + } +} + + +static StkId callrethooks (lua_State *L, StkId firstResult) { + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ + luaD_callhook(L, LUA_HOOKRET, -1); + if (!(L->ci->state & CI_C)) { /* Lua function? */ + while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { + StkId res; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + res = L->base - 1; /* res == final position of 1st result */ + L->ci--; + L->base = L->ci->base; /* restore base */ + /* move results to correct place */ + while (wanted != 0 && firstResult < L->top) { + setobjs2s(res++, firstResult++); + wanted--; + } + while (wanted-- > 0) + setnilvalue(res++); + L->top = res; +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + StkId firstResult; + lua_assert(!(L->ci->state & CI_CALLING)); + if (++L->nCcalls >= LUA_MAXCCALLS) { + if (L->nCcalls == LUA_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + firstResult = luaD_precall(L, func); + if (firstResult == NULL) /* is a Lua function? */ + firstResult = luaV_execute(L); /* call it */ + luaD_poscall(L, nResults, firstResult); + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstResult; + int nargs = *cast(int *, ud); + CallInfo *ci = L->ci; + if (ci == L->base_ci) { /* no activation record? */ + lua_assert(nargs < L->top - L->base); + luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ + } + else { /* inside a yield */ + lua_assert(ci->state & CI_YIELD); + if (ci->state & CI_C) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + int nresults; + lua_assert((ci-1)->state & CI_SAVEDPC); + lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); + nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; + luaD_poscall(L, nresults, L->top - nargs); /* complete it */ + if (nresults >= 0) L->top = L->ci->top; + } + else { /* yielded inside a hook: just continue its execution */ + ci->state &= ~CI_YIELD; + } + } + firstResult = luaV_execute(L); + if (firstResult != NULL) /* return? */ + luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lu_byte old_allowhooks; + lua_lock(L); + if (L->ci == L->base_ci) { + if (nargs >= L->top - L->base) + return resume_error(L, "cannot resume dead coroutine"); + } + else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */ + return resume_error(L, "cannot resume non-suspended coroutine"); + old_allowhooks = L->allowhook; + lua_assert(L->errfunc == 0 && L->nCcalls == 0); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status != 0) { /* error? */ + L->ci = L->base_ci; /* go back to initial level */ + L->base = L->ci->base; + L->nCcalls = 0; + luaF_close(L, L->base); /* close eventual pending closures */ + seterrorobj(L, status, L->base); + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + CallInfo *ci; + lua_lock(L); + ci = L->ci; + if (L->nCcalls > 0) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + if (ci->state & CI_C) { /* usual yield */ + if ((ci-1)->state & CI_C) + luaG_runerror(L, "cannot yield a C function"); + if (L->top - nresults > L->base) { /* is there garbage in the stack? */ + int i; + for (i=0; ibase + i, L->top - nresults + i); + L->top = L->base + nresults; + } + } /* else it's an yield inside a hook: nothing to do */ + ci->state |= CI_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != 0) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close eventual pending closures */ + seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + int bin; +}; + +static void f_parser (lua_State *L, void *ud) { + struct SParser *p; + Proto *tf; + Closure *cl; + luaC_checkGC(L); + p = cast(struct SParser *, ud); + tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff); + cl = luaF_newLclosure(L, 0, gt(L)); + cl->l.p = tf; + setclvalue(L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { + struct SParser p; + int status; + ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */ + p.z = z; p.bin = bin; + luaZ_initbuffer(L, &p.buff); + status = luaD_rawrunprotected(L, f_parser, &p); + luaZ_freebuffer(L, &p.buff); + if (status != 0) { /* error? */ + StkId oldtop = restorestack(L, oldtopr); + seterrorobj(L, status, oldtop); + } + return status; +} + + diff --git a/build/premake/src/Src/Lua/ldo.h b/build/premake/src/Src/Lua/ldo.h new file mode 100644 index 0000000000..2a61bf5bb2 --- /dev/null +++ b/build/premake/src/Src/Lua/ldo.h @@ -0,0 +1,60 @@ +/* +** $Id: ldo.h,v 1.56 2002/12/04 17:29:32 roberto Exp $ +** 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 control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) { /* empty */ } +#else +#define condhardstacktests(x) x +#endif + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +void luaD_resetprotection (lua_State *L); +int luaD_protectedparser (lua_State *L, ZIO *z, int bin); +void luaD_callhook (lua_State *L, int event, int line); +StkId luaD_precall (lua_State *L, StkId func); +void luaD_call (lua_State *L, StkId func, int nResults); +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +void luaD_poscall (lua_State *L, int wanted, StkId firstResult); +void luaD_reallocCI (lua_State *L, int newsize); +void luaD_reallocstack (lua_State *L, int newsize); +void luaD_growstack (lua_State *L, int n); + +void luaD_throw (lua_State *L, int errcode); +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + + +#endif diff --git a/build/premake/src/Src/Lua/ldump.c b/build/premake/src/Src/Lua/ldump.c new file mode 100644 index 0000000000..234b011f5f --- /dev/null +++ b/build/premake/src/Src/Lua/ldump.c @@ -0,0 +1,170 @@ +/* +** $Id: ldump.c,v 1.4 2003/02/11 23:52:12 lhf Exp $ +** save bytecodes +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c + +#include "lua.h" + +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lundump.h" + +#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D) + +typedef struct { + lua_State* L; + lua_Chunkwriter write; + void* data; +} DumpState; + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + lua_unlock(D->L); + (*D->write)(D->L,b,size,D->data); + lua_lock(D->L); +} + +static void DumpByte(int y, DumpState* D) +{ + char x=(char)y; + DumpBlock(&x,sizeof(x),D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpSize(size_t x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpString(TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + DumpSize(0,D); + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpSize(size,D); + DumpBlock(getstr(s),size,D); + } +} + +static void DumpCode(const Proto* f, DumpState* D) +{ + DumpInt(f->sizecode,D); + DumpVector(f->code,f->sizecode,sizeof(*f->code),D); +} + +static void DumpLocals(const Proto* f, DumpState* D) +{ + int i,n=f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } +} + +static void DumpLines(const Proto* f, DumpState* D) +{ + DumpInt(f->sizelineinfo,D); + DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D); +} + +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i,n=f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n; + DumpInt(n=f->sizek,D); + for (i=0; ik[i]; + DumpByte(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(tsvalue(o),D); + break; + case LUA_TNIL: + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + DumpInt(n=f->sizep,D); + for (i=0; ip[i],f->source,D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p) ? NULL : f->source,D); + DumpInt(f->lineDefined,D); + DumpByte(f->nups,D); + DumpByte(f->numparams,D); + DumpByte(f->is_vararg,D); + DumpByte(f->maxstacksize,D); + DumpLines(f,D); + DumpLocals(f,D); + DumpUpvalues(f,D); + DumpConstants(f,D); + DumpCode(f,D); +} + +static void DumpHeader(DumpState* D) +{ + DumpLiteral(LUA_SIGNATURE,D); + DumpByte(VERSION,D); + DumpByte(luaU_endianness(),D); + DumpByte(sizeof(int),D); + DumpByte(sizeof(size_t),D); + DumpByte(sizeof(Instruction),D); + DumpByte(SIZE_OP,D); + DumpByte(SIZE_A,D); + DumpByte(SIZE_B,D); + DumpByte(SIZE_C,D); + DumpByte(sizeof(lua_Number),D); + DumpNumber(TEST_NUMBER,D); +} + +/* +** dump function as precompiled chunk +*/ +void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data) +{ + DumpState D; + D.L=L; + D.write=w; + D.data=data; + DumpHeader(&D); + DumpFunction(Main,NULL,&D); +} + diff --git a/build/premake/src/Src/Lua/lfunc.c b/build/premake/src/Src/Lua/lfunc.c new file mode 100644 index 0000000000..31044fa56b --- /dev/null +++ b/build/premake/src/Src/Lua/lfunc.c @@ -0,0 +1,135 @@ +/* +** $Id: lfunc.c,v 1.67 2003/03/18 12:50:04 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TObject)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TObject *)*((n)-1))) + + + +Closure *luaF_newCclosure (lua_State *L, int nelems) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, valtogco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.nupvalues = cast(lu_byte, nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, valtogco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.g = *e; + c->l.nupvalues = cast(lu_byte, nelems); + return c; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *v; + while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { + if (p->v == level) return p; + pp = &p->next; + } + v = luaM_new(L, UpVal); /* not found: create a new one */ + v->tt = LUA_TUPVAL; + v->marked = 1; /* open upvalues should not be collected */ + v->v = level; /* current value lives in the stack */ + v->next = *pp; /* chain it in the proper position */ + *pp = valtogco(v); + return v; +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *p; + while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) { + setobj(&p->value, p->v); /* save current value (write barrier) */ + p->v = &p->value; /* now current value lives here */ + L->openupval = p->next; /* remove from `open' list */ + luaC_link(L, valtogco(p), LUA_TUPVAL); + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, valtogco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->lineDefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TObject); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_freelem(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_free(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/build/premake/src/Src/Lua/lfunc.h b/build/premake/src/Src/Lua/lfunc.h new file mode 100644 index 0000000000..5d5325076b --- /dev/null +++ b/build/premake/src/Src/Lua/lfunc.h @@ -0,0 +1,25 @@ +/* +** $Id: lfunc.h,v 1.21 2003/03/18 12:50:04 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +Proto *luaF_newproto (lua_State *L); +Closure *luaF_newCclosure (lua_State *L, int nelems); +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e); +UpVal *luaF_findupval (lua_State *L, StkId level); +void luaF_close (lua_State *L, StkId level); +void luaF_freeproto (lua_State *L, Proto *f); +void luaF_freeclosure (lua_State *L, Closure *c); + +const char *luaF_getlocalname (const Proto *func, int local_number, int pc); + + +#endif diff --git a/build/premake/src/Src/Lua/lgc.c b/build/premake/src/Src/Lua/lgc.c new file mode 100644 index 0000000000..5e036d387a --- /dev/null +++ b/build/premake/src/Src/Lua/lgc.c @@ -0,0 +1,498 @@ +/* +** $Id: lgc.c,v 1.171a 2003/04/03 13:35:34 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +typedef struct GCState { + GCObject *tmark; /* list of marked objects to be traversed */ + GCObject *wk; /* list of traversed key-weak tables (to be cleared) */ + GCObject *wv; /* list of traversed value-weak tables */ + GCObject *wkv; /* list of traversed key-value weak tables */ + global_State *g; +} GCState; + + +/* +** some userful bit tricks +*/ +#define setbit(x,b) ((x) |= (1<<(b))) +#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b)))) +#define testbit(x,b) ((x) & (1<<(b))) + +#define unmark(x) resetbit((x)->gch.marked, 0) +#define ismarked(x) ((x)->gch.marked & ((1<<4)|1)) + +#define stringmark(s) setbit((s)->tsv.marked, 0) + + +#define isfinalized(u) (!testbit((u)->uv.marked, 1)) +#define markfinalized(u) resetbit((u)->uv.marked, 1) + + +#define KEYWEAKBIT 1 +#define VALUEWEAKBIT 2 +#define KEYWEAK (1<gch.marked, 0); /* mark object */ + switch (o->gch.tt) { + case LUA_TUSERDATA: { + markvalue(st, gcotou(o)->uv.metatable); + break; + } + case LUA_TFUNCTION: { + gcotocl(o)->c.gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TTABLE: { + gcotoh(o)->gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TTHREAD: { + gcototh(o)->gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TPROTO: { + gcotop(o)->gclist = st->tmark; + st->tmark = o; + break; + } + default: lua_assert(o->gch.tt == LUA_TSTRING); + } +} + + +static void marktmu (GCState *st) { + GCObject *u; + for (u = st->g->tmudata; u; u = u->gch.next) { + unmark(u); /* may be marked, if left from previous GC */ + reallymarkobject(st, u); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L) { + size_t deadmem = 0; + GCObject **p = &G(L)->rootudata; + GCObject *curr; + GCObject *collected = NULL; /* to collect udata with gc event */ + GCObject **lastcollected = &collected; + while ((curr = *p) != NULL) { + lua_assert(curr->gch.tt == LUA_TUSERDATA); + if (ismarked(curr) || isfinalized(gcotou(curr))) + p = &curr->gch.next; /* don't bother with them */ + + else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { + markfinalized(gcotou(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gcotou(curr)->uv.len); + *p = curr->gch.next; + curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ + *lastcollected = curr; + lastcollected = &curr->gch.next; + } + } + /* insert collected udata with gc event into `tmudata' list */ + *lastcollected = G(L)->tmudata; + G(L)->tmudata = collected; + return deadmem; +} + + +static void removekey (Node *n) { + setnilvalue(gval(n)); /* remove corresponding value ... */ + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TNONE); /* dead key; remove it */ +} + + +static void traversetable (GCState *st, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TObject *mode; + markvalue(st, h->metatable); + lua_assert(h->lsizenode || h->node == st->g->dummynode); + mode = gfasttm(st->g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + GCObject **weaklist; + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + weaklist = (weakkey && weakvalue) ? &st->wkv : + (weakkey) ? &st->wk : + &st->wv; + h->gclist = *weaklist; /* must be cleared after GC, ... */ + *weaklist = valtogco(h); /* ... so put in the appropriate list */ + } + } + if (!weakvalue) { + i = h->sizearray; + while (i--) + markobject(st, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n))) { + lua_assert(!ttisnil(gkey(n))); + condmarkobject(st, gkey(n), !weakkey); + condmarkobject(st, gval(n), !weakvalue); + } + } +} + + +static void traverseproto (GCState *st, Proto *f) { + int i; + stringmark(f->source); + for (i=0; isizek; i++) { /* mark literal strings */ + if (ttisstring(f->k+i)) + stringmark(tsvalue(f->k+i)); + } + for (i=0; isizeupvalues; i++) /* mark upvalue names */ + stringmark(f->upvalues[i]); + for (i=0; isizep; i++) /* mark nested protos */ + markvalue(st, f->p[i]); + for (i=0; isizelocvars; i++) /* mark local-variable names */ + stringmark(f->locvars[i].varname); + lua_assert(luaG_checkcode(f)); +} + + + +static void traverseclosure (GCState *st, Closure *cl) { + if (cl->c.isC) { + int i; + for (i=0; ic.nupvalues; i++) /* mark its upvalues */ + markobject(st, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markvalue(st, hvalue(&cl->l.g)); + markvalue(st, cl->l.p); + for (i=0; il.nupvalues; i++) { /* mark its upvalues */ + UpVal *u = cl->l.upvals[i]; + if (!u->marked) { + markobject(st, &u->value); + u->marked = 1; + } + } + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int used = L->ci - L->base_ci; /* number of `ci' in use */ + if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); + used = max - L->stack; /* part of stack in use */ + if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); +} + + +static void traversestack (GCState *st, lua_State *L1) { + StkId o, lim; + CallInfo *ci; + markobject(st, gt(L1)); + lim = L1->top; + for (ci = L1->base_ci; ci <= L1->ci; ci++) { + lua_assert(ci->top <= L1->stack_last); + lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC)); + if (lim < ci->top) + lim = ci->top; + } + for (o = L1->stack; o < L1->top; o++) + markobject(st, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(L1, lim); +} + + +static void propagatemarks (GCState *st) { + while (st->tmark) { /* traverse marked objects */ + switch (st->tmark->gch.tt) { + case LUA_TTABLE: { + Table *h = gcotoh(st->tmark); + st->tmark = h->gclist; + traversetable(st, h); + break; + } + case LUA_TFUNCTION: { + Closure *cl = gcotocl(st->tmark); + st->tmark = cl->c.gclist; + traverseclosure(st, cl); + break; + } + case LUA_TTHREAD: { + lua_State *th = gcototh(st->tmark); + st->tmark = th->gclist; + traversestack(st, th); + break; + } + case LUA_TPROTO: { + Proto *p = gcotop(st->tmark); + st->tmark = p->gclist; + traverseproto(st, p); + break; + } + default: lua_assert(0); + } + } +} + + +static int valismarked (const TObject *o) { + if (ttisstring(o)) + stringmark(tsvalue(o)); /* strings are `values', so are never weak */ + return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0); +} + + +/* +** clear collected keys from weaktables +*/ +static void cleartablekeys (GCObject *l) { + while (l) { + Table *h = gcotoh(l); + int i = sizenode(h); + lua_assert(h->marked & KEYWEAK); + while (i--) { + Node *n = gnode(h, i); + if (!valismarked(gkey(n))) /* key was collected? */ + removekey(n); /* remove entry from table */ + } + l = h->gclist; + } +} + + +/* +** clear collected values from weaktables +*/ +static void cleartablevalues (GCObject *l) { + while (l) { + Table *h = gcotoh(l); + int i = h->sizearray; + lua_assert(h->marked & VALUEWEAK); + while (i--) { + TObject *o = &h->array[i]; + if (!valismarked(o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!valismarked(gval(n))) /* value was collected? */ + removekey(n); /* remove entry from table */ + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; + case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; + case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; + case LUA_TTHREAD: { + lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); + luaE_freethread(L, gcototh(o)); + break; + } + case LUA_TSTRING: { + luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); + break; + } + case LUA_TUSERDATA: { + luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); + break; + } + default: lua_assert(0); + } +} + + +static int sweeplist (lua_State *L, GCObject **p, int limit) { + GCObject *curr; + int count = 0; /* number of collected items */ + while ((curr = *p) != NULL) { + if (curr->gch.marked > limit) { + unmark(curr); + p = &curr->gch.next; + } + else { + count++; + *p = curr->gch.next; + freeobj(L, curr); + } + } + return count; +} + + +static void sweepstrings (lua_State *L, int all) { + int i; + for (i=0; istrt.size; i++) { /* for each list */ + G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all); + } +} + + +static void checkSizes (lua_State *L, size_t deadmem) { + /* check size of string hash */ + if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) && + G(L)->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, G(L)->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2; + luaZ_resizebuffer(L, &G(L)->buff, newsize); + } + G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */ +} + + +static void do1gcTM (lua_State *L, Udata *udata) { + const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + setobj2s(L->top, tm); + setuvalue(L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + } +} + + +void luaC_callGCTM (lua_State *L) { + lu_byte oldah = L->allowhook; + L->allowhook = 0; /* stop debug hooks during GC tag methods */ + L->top++; /* reserve space to keep udata while runs its gc method */ + while (G(L)->tmudata != NULL) { + GCObject *o = G(L)->tmudata; + Udata *udata = gcotou(o); + G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */ + udata->uv.next = G(L)->rootudata; /* return it to `root' list */ + G(L)->rootudata = o; + setuvalue(L->top - 1, udata); /* keep a reference to it */ + unmark(o); + markfinalized(udata); + do1gcTM(L, udata); + } + L->top--; + L->allowhook = oldah; /* restore hooks */ +} + + +void luaC_sweep (lua_State *L, int all) { + if (all) all = 256; /* larger than any mark */ + sweeplist(L, &G(L)->rootudata, all); + sweepstrings(L, all); + sweeplist(L, &G(L)->rootgc, all); +} + + +/* mark root set */ +static void markroot (GCState *st, lua_State *L) { + global_State *g = st->g; + markobject(st, defaultmeta(L)); + markobject(st, registry(L)); + traversestack(st, g->mainthread); + if (L != g->mainthread) /* another thread is running? */ + markvalue(st, L); /* cannot collect it */ +} + + +static size_t mark (lua_State *L) { + size_t deadmem; + GCState st; + GCObject *wkv; + st.g = G(L); + st.tmark = NULL; + st.wkv = st.wk = st.wv = NULL; + markroot(&st, L); + propagatemarks(&st); /* mark all reachable objects */ + cleartablevalues(st.wkv); + cleartablevalues(st.wv); + wkv = st.wkv; /* keys must be cleared after preserving udata */ + st.wkv = NULL; + st.wv = NULL; + deadmem = luaC_separateudata(L); /* separate userdata to be preserved */ + marktmu(&st); /* mark `preserved' userdata */ + propagatemarks(&st); /* remark, to propagate `preserveness' */ + cleartablekeys(wkv); + /* `propagatemarks' may resuscitate some weak tables; clear them too */ + cleartablekeys(st.wk); + cleartablevalues(st.wv); + cleartablekeys(st.wkv); + cleartablevalues(st.wkv); + return deadmem; +} + + +void luaC_collectgarbage (lua_State *L) { + size_t deadmem = mark(L); + luaC_sweep(L, 0); + checkSizes(L, deadmem); + luaC_callGCTM(L); +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + o->gch.next = G(L)->rootgc; + G(L)->rootgc = o; + o->gch.marked = 0; + o->gch.tt = tt; +} + diff --git a/build/premake/src/Src/Lua/lgc.h b/build/premake/src/Src/Lua/lgc.h new file mode 100644 index 0000000000..3f4d7486e9 --- /dev/null +++ b/build/premake/src/Src/Lua/lgc.h @@ -0,0 +1,25 @@ +/* +** $Id: lgc.h,v 1.19a 2003/02/28 19:45:15 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \ + if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); } + + +size_t luaC_separateudata (lua_State *L); +void luaC_callGCTM (lua_State *L); +void luaC_sweep (lua_State *L, int all); +void luaC_collectgarbage (lua_State *L); +void luaC_link (lua_State *L, GCObject *o, lu_byte tt); + + +#endif diff --git a/build/premake/src/Src/Lua/liolib.c b/build/premake/src/Src/Lua/liolib.c new file mode 100644 index 0000000000..c451e37d35 --- /dev/null +++ b/build/premake/src/Src/Lua/liolib.c @@ -0,0 +1,750 @@ +/* +** $Id: liolib.c,v 2.39a 2003/03/19 21:16:12 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + +#define liolib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +/* +** by default, gcc does not get `tmpname' +*/ +#ifndef USE_TMPNAME +#ifdef __GNUC__ +#define USE_TMPNAME 0 +#else +#define USE_TMPNAME 1 +#endif +#endif + + +/* +** by default, posix systems get `popen' +*/ +#ifndef USE_POPEN +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 2 +#define USE_POPEN 1 +#endif +#endif +#endif + +#ifndef USE_POPEN +#define USE_POPEN 0 +#endif + + + + +/* +** {====================================================== +** FILE Operations +** ======================================================= +*/ + + +#if !USE_POPEN +#define pclose(f) (-1) +#endif + + +#define FILEHANDLE "FILE*" + +#define IO_INPUT "_input" +#define IO_OUTPUT "_output" + + +static int pushresult (lua_State *L, int i, const char *filename) { + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + else + lua_pushfstring(L, "%s", strerror(errno)); + lua_pushnumber(L, errno); + return 3; + } +} + + +static FILE **topfile (lua_State *L, int findex) { + FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); + if (f == NULL) luaL_argerror(L, findex, "bad file"); + return f; +} + + +static int io_type (lua_State *L) { + FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); + if (f == NULL) lua_pushnil(L); + else if (*f == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L, int findex) { + FILE **f = topfile(L, findex); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** assumes that top of the stack is the `io' library, and next is +** the `io' metatable +*/ +static void registerfile (lua_State *L, FILE *f, const char *name, + const char *impname) { + lua_pushstring(L, name); + *newfile(L) = f; + if (impname) { + lua_pushstring(L, impname); + lua_pushvalue(L, -2); + lua_settable(L, -6); /* metatable[impname] = file */ + } + lua_settable(L, -3); /* io[name] = file */ +} + + +static int aux_close (lua_State *L) { + FILE *f = tofile(L, 1); + if (f == stdin || f == stdout || f == stderr) + return 0; /* file cannot be closed */ + else { + int ok = (pclose(f) != -1) || (fclose(f) == 0); + if (ok) + *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ + return ok; + } +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) { + lua_pushstring(L, IO_OUTPUT); + lua_rawget(L, lua_upvalueindex(1)); + } + return pushresult(L, aux_close(L), NULL); +} + + +static int io_gc (lua_State *L) { + FILE **f = topfile(L, 1); + if (*f != NULL) /* ignore closed files */ + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + char buff[128]; + FILE **f = topfile(L, 1); + if (*f == NULL) + strcpy(buff, "closed"); + else + sprintf(buff, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "file (%s)", buff); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_popen (lua_State *L) { +#if !USE_POPEN + luaL_error(L, "`popen' not supported"); + return 0; +#else + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = popen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +#endif +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *name) { + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return tofile(L, -1); +} + + +static int g_iofile (lua_State *L, const char *name, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + lua_pushstring(L, name); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, 1, lua_tostring(L, -1)); + } + } + else { + tofile(L, 1); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawset(L, lua_upvalueindex(1)); + } + /* return current value */ + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int close) { + lua_pushliteral(L, FILEHANDLE); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, idx); + lua_pushboolean(L, close); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 3); +} + + +static int f_lines (lua_State *L) { + tofile(L, 1); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + lua_pushstring(L, IO_INPUT); + lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + luaL_argcheck(L, *pf, 1, strerror(errno)); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_strlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_strlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tonumber(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + case 'w': /* word */ + return luaL_error(L, "obsolete option `*w' to `read'"); + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L, 1), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + if (read_line(L, f)) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(2)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L, 1), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); + long offset = luaL_optlong(L, 3, 0); + luaL_argcheck(L, op != -1, 2, "invalid mode"); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushnumber(L, ftell(f)); + return 1; + } +} + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L, 1)) == 0, NULL); +} + + +static const luaL_reg iolib[] = { + {"input", io_input}, + {"output", io_output}, + {"lines", io_lines}, + {"close", io_close}, + {"flush", io_flush}, + {"open", io_open}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_reg flib[] = { + {"flush", f_flush}, + {"read", f_read}, + {"lines", f_lines}, + {"seek", f_seek}, + {"write", f_write}, + {"close", io_close}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */ + /* file methods */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_openlib(L, NULL, flib, 0); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Other O.S. Operations +** ======================================================= +*/ + +static int io_execute (lua_State *L) { + lua_pushnumber(L, system(luaL_checkstring(L, 1))); + return 1; +} + + +static int io_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return pushresult(L, remove(filename) == 0, filename); +} + + +static int io_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int io_tmpname (lua_State *L) { +#if !USE_TMPNAME + luaL_error(L, "`tmpname' not supported"); + return 0; +#else + char buff[L_tmpnam]; + if (tmpnam(buff) != buff) + return luaL_error(L, "unable to generate a unique filename in `tmpname'"); + lua_pushstring(L, buff); + return 1; +#endif +} + + +static int io_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int io_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushnumber(L, value); + lua_rawset(L, -3); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushboolean(L, value); + lua_rawset(L, -3); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + if (lua_isnumber(L, -1)) + res = (int)(lua_tonumber(L, -1)); + else { + if (d == -2) + return luaL_error(L, "field `%s' missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int io_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = (time_t)(luaL_optnumber(L, 2, -1)); + struct tm *stm; + if (t == (time_t)(-1)) /* no time given? */ + t = time(NULL); /* use current time */ + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_newtable(L); + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char b[256]; + if (strftime(b, sizeof(b), s, stm)) + lua_pushstring(L, b); + else + return luaL_error(L, "`date' format too long"); + } + return 1; +} + + +static int io_time (lua_State *L) { + if (lua_isnoneornil(L, 1)) /* called without args? */ + lua_pushnumber(L, (lua_Number)time(NULL)); /* return current time */ + else { + time_t t; + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -2); + ts.tm_mon = getfield(L, "month", -2) - 1; + ts.tm_year = getfield(L, "year", -2) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + } + return 1; +} + + +static int io_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int io_setloc (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = lua_tostring(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); + luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); + luaL_argcheck(L, op != -1, 2, "invalid option"); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int io_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); + return 0; /* to avoid warnings */ +} + +static const luaL_reg syslib[] = { + {"clock", io_clock}, + {"date", io_date}, + {"difftime", io_difftime}, + {"execute", io_execute}, + {"exit", io_exit}, + {"getenv", io_getenv}, + {"remove", io_remove}, + {"rename", io_rename}, + {"setlocale", io_setloc}, + {"time", io_time}, + {"tmpname", io_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_io (lua_State *L) { + luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); + createmeta(L); + lua_pushvalue(L, -1); + luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); + /* put predefined file handles into `io' table */ + registerfile(L, stdin, "stdin", IO_INPUT); + registerfile(L, stdout, "stdout", IO_OUTPUT); + registerfile(L, stderr, "stderr", NULL); + return 1; +} + diff --git a/build/premake/src/Src/Lua/llex.c b/build/premake/src/Src/Lua/llex.c new file mode 100644 index 0000000000..045e999443 --- /dev/null +++ b/build/premake/src/Src/Lua/llex.c @@ -0,0 +1,417 @@ +/* +** $Id: llex.c,v 1.119 2003/03/24 12:39:34 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define llex_c + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "lzio.h" + + + +#define next(LS) (LS->current = zgetc(LS->z)) + + + +/* ORDER RESERVED */ +static const char *const token2string [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", "*name", + "..", "...", "==", ">=", "<=", "~=", + "*number", "*string", "" +}; + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.reserved = cast(lu_byte, i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { + if (val > limit) { + msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit); + luaX_syntaxerror(ls, msg); + } +} + + +void luaX_errorline (LexState *ls, const char *s, const char *token, int line) { + lua_State *L = ls->L; + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token); + luaD_throw(L, LUA_ERRSYNTAX); +} + + +static void luaX_error (LexState *ls, const char *s, const char *token) { + luaX_errorline(ls, s, token, ls->linenumber); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + const char *lasttoken; + switch (ls->t.token) { + case TK_NAME: + lasttoken = getstr(ls->t.seminfo.ts); + break; + case TK_STRING: + case TK_NUMBER: + lasttoken = luaZ_buffer(ls->buff); + break; + default: + lasttoken = luaX_token2str(ls, ls->t.token); + break; + } + luaX_error(ls, msg, lasttoken); +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == (unsigned char)token); + return luaO_pushfstring(ls->L, "%c", token); + } + else + return token2string[token-FIRST_RESERVED]; +} + + +static void luaX_lexerror (LexState *ls, const char *s, int token) { + if (token == TK_EOS) + luaX_error(ls, s, luaX_token2str(ls, token)); + else + luaX_error(ls, s, luaZ_buffer(ls->buff)); +} + + +static void inclinenumber (LexState *LS) { + next(LS); /* skip `\n' */ + ++LS->linenumber; + luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk"); +} + + +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) { + LS->L = L; + LS->lookahead.token = TK_EOS; /* no look-ahead token */ + LS->z = z; + LS->fs = NULL; + LS->linenumber = 1; + LS->lastline = 1; + LS->source = source; + next(LS); /* read first char */ + if (LS->current == '#') { + do { /* skip first line */ + next(LS); + } while (LS->current != '\n' && LS->current != EOZ); + } +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +/* use buffer to store names, literal strings and numbers */ + +/* extra space to allocate when growing buffer */ +#define EXTRABUFF 32 + +/* maximum number of chars that can be read without checking buffer size */ +#define MAXNOCHECK 5 + +#define checkbuffer(LS, len) \ + if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \ + luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF) + +#define save(LS, c, l) \ + (luaZ_buffer((LS)->buff)[l++] = cast(char, c)) +#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS)) + + +static size_t readname (LexState *LS) { + size_t l = 0; + checkbuffer(LS, l); + do { + checkbuffer(LS, l); + save_and_next(LS, l); + } while (isalnum(LS->current) || LS->current == '_'); + save(LS, '\0', l); + return l-1; +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) { + size_t l = 0; + checkbuffer(LS, l); + if (comma) save(LS, '.', l); + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + if (LS->current == '.') { + save_and_next(LS, l); + if (LS->current == '.') { + save_and_next(LS, l); + save(LS, '\0', l); + luaX_lexerror(LS, + "ambiguous syntax (decimal point x string concatenation)", + TK_NUMBER); + } + } + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + if (LS->current == 'e' || LS->current == 'E') { + save_and_next(LS, l); /* read `E' */ + if (LS->current == '+' || LS->current == '-') + save_and_next(LS, l); /* optional exponent sign */ + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + } + save(LS, '\0', l); + if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r)) + luaX_lexerror(LS, "malformed number", TK_NUMBER); +} + + +static void read_long_string (LexState *LS, SemInfo *seminfo) { + int cont = 0; + size_t l = 0; + checkbuffer(LS, l); + save(LS, '[', l); /* save first `[' */ + save_and_next(LS, l); /* pass the second `[' */ + if (LS->current == '\n') /* string starts with a newline? */ + inclinenumber(LS); /* skip it */ + for (;;) { + checkbuffer(LS, l); + switch (LS->current) { + case EOZ: + save(LS, '\0', l); + luaX_lexerror(LS, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case '[': + save_and_next(LS, l); + if (LS->current == '[') { + cont++; + save_and_next(LS, l); + } + continue; + case ']': + save_and_next(LS, l); + if (LS->current == ']') { + if (cont == 0) goto endloop; + cont--; + save_and_next(LS, l); + } + continue; + case '\n': + save(LS, '\n', l); + inclinenumber(LS); + if (!seminfo) l = 0; /* reset buffer to avoid wasting space */ + continue; + default: + save_and_next(LS, l); + } + } endloop: + save_and_next(LS, l); /* skip the second `]' */ + save(LS, '\0', l); + if (seminfo) + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5); +} + + +static void read_string (LexState *LS, int del, SemInfo *seminfo) { + size_t l = 0; + checkbuffer(LS, l); + save_and_next(LS, l); + while (LS->current != del) { + checkbuffer(LS, l); + switch (LS->current) { + case EOZ: + save(LS, '\0', l); + luaX_lexerror(LS, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + save(LS, '\0', l); + luaX_lexerror(LS, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': + next(LS); /* do not save the `\' */ + switch (LS->current) { + case 'a': save(LS, '\a', l); next(LS); break; + case 'b': save(LS, '\b', l); next(LS); break; + case 'f': save(LS, '\f', l); next(LS); break; + case 'n': save(LS, '\n', l); next(LS); break; + case 'r': save(LS, '\r', l); next(LS); break; + case 't': save(LS, '\t', l); next(LS); break; + case 'v': save(LS, '\v', l); next(LS); break; + case '\n': save(LS, '\n', l); inclinenumber(LS); break; + case EOZ: break; /* will raise an error next loop */ + default: { + if (!isdigit(LS->current)) + save_and_next(LS, l); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int c = 0; + int i = 0; + do { + c = 10*c + (LS->current-'0'); + next(LS); + } while (++i<3 && isdigit(LS->current)); + if (c > UCHAR_MAX) { + save(LS, '\0', l); + luaX_lexerror(LS, "escape sequence too large", TK_STRING); + } + save(LS, c, l); + } + } + } + break; + default: + save_and_next(LS, l); + } + } + save_and_next(LS, l); /* skip delimiter */ + save(LS, '\0', l); + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); +} + + +int luaX_lex (LexState *LS, SemInfo *seminfo) { + for (;;) { + switch (LS->current) { + + case '\n': { + inclinenumber(LS); + continue; + } + case '-': { + next(LS); + if (LS->current != '-') return '-'; + /* else is a comment */ + next(LS); + if (LS->current == '[' && (next(LS), LS->current == '[')) + read_long_string(LS, NULL); /* long comment */ + else /* short comment */ + while (LS->current != '\n' && LS->current != EOZ) + next(LS); + continue; + } + case '[': { + next(LS); + if (LS->current != '[') return '['; + else { + read_long_string(LS, seminfo); + return TK_STRING; + } + } + case '=': { + next(LS); + if (LS->current != '=') return '='; + else { next(LS); return TK_EQ; } + } + case '<': { + next(LS); + if (LS->current != '=') return '<'; + else { next(LS); return TK_LE; } + } + case '>': { + next(LS); + if (LS->current != '=') return '>'; + else { next(LS); return TK_GE; } + } + case '~': { + next(LS); + if (LS->current != '=') return '~'; + else { next(LS); return TK_NE; } + } + case '"': + case '\'': { + read_string(LS, LS->current, seminfo); + return TK_STRING; + } + case '.': { + next(LS); + if (LS->current == '.') { + next(LS); + if (LS->current == '.') { + next(LS); + return TK_DOTS; /* ... */ + } + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(LS->current)) return '.'; + else { + read_numeral(LS, 1, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(LS->current)) { + next(LS); + continue; + } + else if (isdigit(LS->current)) { + read_numeral(LS, 0, seminfo); + return TK_NUMBER; + } + else if (isalpha(LS->current) || LS->current == '_') { + /* identifier or reserved word */ + size_t l = readname(LS); + TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + seminfo->ts = ts; + return TK_NAME; + } + else { + int c = LS->current; + if (iscntrl(c)) + luaX_error(LS, "invalid control char", + luaO_pushfstring(LS->L, "char(%d)", c)); + next(LS); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + +#undef next diff --git a/build/premake/src/Src/Lua/llex.h b/build/premake/src/Src/Lua/llex.h new file mode 100644 index 0000000000..740e3f6b31 --- /dev/null +++ b/build/premake/src/Src/Lua/llex.h @@ -0,0 +1,75 @@ +/* +** $Id: llex.h,v 1.47 2003/02/28 17:19:47 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* 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_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_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +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; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + int nestlevel; /* level of nested non-terminals */ +} LexState; + + +void luaX_init (lua_State *L); +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); +int luaX_lex (LexState *LS, SemInfo *seminfo); +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); +void luaX_syntaxerror (LexState *ls, const char *s); +void luaX_errorline (LexState *ls, const char *s, const char *token, int line); +const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/build/premake/src/Src/Lua/llimits.h b/build/premake/src/Src/Lua/llimits.h new file mode 100644 index 0000000000..343c922612 --- /dev/null +++ b/build/premake/src/Src/Lua/llimits.h @@ -0,0 +1,185 @@ +/* +** $Id: llimits.h,v 1.52 2003/02/20 19:33:23 roberto Exp $ +** 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" + + +/* +** try to find number of bits in an integer +*/ +#ifndef BITS_INT +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define BITS_INT 16 +#else +#if INT_MAX > 2147483640L +/* machine has at least 32 bits */ +#define BITS_INT 32 +#else +#error "you must define BITS_INT with number of bits in an integer" +#endif +#endif +#endif + + +/* +** the following types define integer types for values that may not +** fit in a `small int' (16 bits), but may waste space in a +** `large long' (64 bits). The current definitions should work in +** any machine, but may not be optimal. +*/ + +/* an unsigned integer to hold hash values */ +typedef unsigned int lu_hash; +/* its signed equivalent */ +typedef int ls_hash; + +/* an unsigned integer big enough to count the total memory used by Lua; */ +/* it should be at least as large as size_t */ +typedef unsigned long lu_mem; + +#define MAX_LUMEM ULONG_MAX + + +/* an integer big enough to count the number of strings in use */ +typedef long ls_nstr; + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((lu_hash)(p)) + + + +/* type to ensure maximum alignment */ +#ifndef LUSER_ALIGNMENT_T +typedef union { double u; void *s; long l; } L_Umaxalign; +#else +typedef LUSER_ALIGNMENT_T L_Umaxalign; +#endif + + +/* result of `usual argument conversion' over lua_Number */ +#ifndef LUA_UACNUMBER +typedef double l_uacNumber; +#else +typedef LUA_UACNUMBER l_uacNumber; +#endif + + +#ifndef lua_assert +#define lua_assert(c) /* empty */ +#endif + + +#ifndef check_exp +#define check_exp(c,e) (e) +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef unsigned long Instruction; + + +/* maximum depth for calls (unsigned short) */ +#ifndef LUA_MAXCALLS +#define LUA_MAXCALLS 4096 +#endif + + +/* +** maximum depth for C calls (unsigned short): Not too big, or may +** overflow the C stack... +*/ + +#ifndef LUA_MAXCCALLS +#define LUA_MAXCCALLS 200 +#endif + + +/* maximum size for the C stack */ +#ifndef LUA_MAXCSTACK +#define LUA_MAXCSTACK 2048 +#endif + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + +/* maximum number of variables declared in a function */ +#ifndef MAXVARS +#define MAXVARS 200 /* arbitrary limit ( +#include + +#define lmathlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +/* +** If you want Lua to operate in degrees (instead of radians), +** define USE_DEGREES +*/ +#ifdef USE_DEGREES +#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) +#define TORAD(a) ((a)*RADIANS_PER_DEGREE) +#else +#define FROMRAD(a) (a) +#define TORAD(a) (a) +#endif + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_mod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushnumber(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_reg mathlib[] = { + {"abs", math_abs}, + {"sin", math_sin}, + {"cos", math_cos}, + {"tan", math_tan}, + {"asin", math_asin}, + {"acos", math_acos}, + {"atan", math_atan}, + {"atan2", math_atan2}, + {"ceil", math_ceil}, + {"floor", math_floor}, + {"mod", math_mod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"sqrt", math_sqrt}, + {"min", math_min}, + {"max", math_max}, + {"log", math_log}, + {"log10", math_log10}, + {"exp", math_exp}, + {"deg", math_deg}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); + lua_pushliteral(L, "pi"); + lua_pushnumber(L, PI); + lua_settable(L, -3); + lua_pushliteral(L, "__pow"); + lua_pushcfunction(L, math_pow); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/build/premake/src/Src/Lua/lmem.c b/build/premake/src/Src/Lua/lmem.c new file mode 100644 index 0000000000..f977770af0 --- /dev/null +++ b/build/premake/src/Src/Lua/lmem.c @@ -0,0 +1,91 @@ +/* +** $Id: lmem.c,v 1.61 2002/12/04 17:38:31 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#define lmem_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** definition for realloc function. It must assure that l_realloc(NULL, +** 0, x) allocates a new block (ANSI C assures that). (`os' is the old +** block size; some allocators may use that.) +*/ +#ifndef l_realloc +#define l_realloc(b,os,s) realloc(b,s) +#endif + +/* +** definition for free function. (`os' is the old block size; some +** allocators may use that.) +*/ +#ifndef l_free +#define l_free(b,os) free(b) +#endif + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + else if (*size >= limit/2) { /* cannot double it? */ + if (*size < limit - MINSIZEARRAY) /* try something smaller... */ + newsize = limit; /* still have at least MINSIZEARRAY free places */ + else luaG_runerror(L, errormsg); + } + newblock = luaM_realloc(L, block, + cast(lu_mem, *size)*cast(lu_mem, size_elems), + cast(lu_mem, newsize)*cast(lu_mem, size_elems)); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +/* +** generic allocation routine. +*/ +void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) { + lua_assert((oldsize == 0) == (block == NULL)); + if (size == 0) { + if (block != NULL) { + l_free(block, oldsize); + block = NULL; + } + else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */ + } + else if (size >= MAX_SIZET) + luaG_runerror(L, "memory allocation error: block too big"); + else { + block = l_realloc(block, oldsize, size); + if (block == NULL) { + if (L) + luaD_throw(L, LUA_ERRMEM); + else return NULL; /* error before creating state! */ + } + } + if (L) { + lua_assert(G(L) != NULL && G(L)->nblocks > 0); + G(L)->nblocks -= oldsize; + G(L)->nblocks += size; + } + return block; +} + diff --git a/build/premake/src/Src/Lua/lmem.h b/build/premake/src/Src/Lua/lmem.h new file mode 100644 index 0000000000..1bb4fde0b2 --- /dev/null +++ b/build/premake/src/Src/Lua/lmem.h @@ -0,0 +1,44 @@ +/* +** $Id: lmem.h,v 1.26 2002/05/01 20:40:42 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +void *luaM_realloc (lua_State *L, void *oldblock, lu_mem oldsize, lu_mem size); + +void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem, + int limit, const char *errormsg); + +#define luaM_free(L, b, s) luaM_realloc(L, (b), (s), 0) +#define luaM_freelem(L, b) luaM_realloc(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_realloc(L, (b), \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t)), 0) + +#define luaM_malloc(L, t) luaM_realloc(L, NULL, 0, (t)) +#define luaM_new(L, t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L, n,t) cast(t *, luaM_malloc(L, \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t)))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if (((nelems)+1) > (size)) \ + ((v)=cast(t *, luaM_growaux(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_realloc(L, v,cast(lu_mem, oldn)*cast(lu_mem, sizeof(t)), \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t))))) + + +#endif + diff --git a/build/premake/src/Src/Lua/loadlib.c b/build/premake/src/Src/Lua/loadlib.c new file mode 100644 index 0000000000..ac4d697a68 --- /dev/null +++ b/build/premake/src/Src/Lua/loadlib.c @@ -0,0 +1,205 @@ +/* +** $Id: loadlib.c,v 1.4 2003/04/07 20:11:53 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +* +* This Lua library exports a single function, called loadlib, which is +* called from Lua as loadlib(lib,init), where lib is the full name of the +* library to be loaded (including the complete path) and init is the name +* of a function to be called after the library is loaded. Typically, this +* function will register other functions, thus making the complete library +* available to Lua. The init function is *not* automatically called by +* loadlib. Instead, loadlib returns the init function as a Lua function +* that the client can call when it thinks is appropriate. In the case of +* errors, loadlib returns nil and two strings describing the error. +* The first string is supplied by the operating system; it should be +* informative and useful for error messages. The second string is "open", +* "init", or "absent" to identify the error and is meant to be used for +* making decisions without having to look into the first string (whose +* format is system-dependent). +* +* This module contains an implementation of loadlib for Unix systems that +* have dlfcn, an implementation for Windows, and a stub for other systems. +* See the list at the end of this file for some links to available +* implementations of dlfcn and interfaces to other native dynamic loaders +* on top of which loadlib could be implemented. +* +*/ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + + +#undef LOADLIB + + +#ifdef USE_DLOPEN +#define LOADLIB +/* +* This is an implementation of loadlib based on the dlfcn interface. +* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +* as an emulation layer on top of native functions. +*/ + +#include + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + void *lib=dlopen(path,RTLD_NOW); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) dlsym(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + /* else return appropriate error messages */ + lua_pushnil(L); + lua_pushstring(L,dlerror()); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) dlclose(lib); + return 3; +} + +#endif + + + +/* +** In Windows, default is to use dll; otherwise, default is not to use dll +*/ +#ifndef USE_DLL +#ifdef _WIN32 +#define USE_DLL 1 +#else +#define USE_DLL 0 +#endif +#endif + + +#if USE_DLL +#define LOADLIB +/* +* This is an implementation of loadlib for Windows using native functions. +*/ + +#include + +static void pusherror(lua_State *L) +{ + int error=GetLastError(); + char buffer[128]; + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, 0, buffer, sizeof(buffer), 0)) + lua_pushstring(L,buffer); + else + lua_pushfstring(L,"system error %d\n",error); +} + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + HINSTANCE lib=LoadLibrary(path); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + lua_pushnil(L); + pusherror(L); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) FreeLibrary(lib); + return 3; +} + +#endif + + + +#ifndef LOADLIB +/* Fallback for other systems */ + +/* +** Those systems support dlopen, so they should have defined USE_DLOPEN. +** The default (no)implementation gives them a special error message. +*/ +#ifdef linux +#define LOADLIB +#endif + +#ifdef sun +#define LOADLIB +#endif + +#ifdef sgi +#define LOADLIB +#endif + +#ifdef BSD +#define LOADLIB +#endif + +#ifdef _WIN32 +#define LOADLIB +#endif + +#ifdef LOADLIB +#undef LOADLIB +#define LOADLIB "`loadlib' not installed (check your Lua configuration)" +#else +#define LOADLIB "`loadlib' not supported" +#endif + +static int loadlib(lua_State *L) +{ + lua_pushnil(L); + lua_pushliteral(L,LOADLIB); + lua_pushliteral(L,"absent"); + return 3; +} +#endif + +LUALIB_API int luaopen_loadlib (lua_State *L) +{ + lua_register(L,"loadlib",loadlib); + return 0; +} + +/* +* Here are some links to available implementations of dlfcn and +* interfaces to other native dynamic loaders on top of which loadlib +* could be implemented. Please send contributions and corrections to us. +* +* AIX +* Starting with AIX 4.2, dlfcn is included in the base OS. +* There is also an emulation package available. +* http://www.faqs.org/faqs/aix-faq/part4/section-21.html +* +* HPUX +* HPUX 11 has dlfcn. For HPUX 10 use shl_*. +* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Macintosh, Windows +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Mac OS X/Darwin +* http://www.opendarwin.org/projects/dlcompat/ +* +* GLIB has wrapper code for BeOS, OS2, Unix and Windows +* http://cvs.gnome.org/lxr/source/glib/gmodule/ +* +*/ diff --git a/build/premake/src/Src/Lua/lobject.c b/build/premake/src/Src/Lua/lobject.c new file mode 100644 index 0000000000..9522b6e812 --- /dev/null +++ b/build/premake/src/Src/Lua/lobject.c @@ -0,0 +1,195 @@ +/* +** $Id: lobject.c,v 1.97 2003/04/03 13:35:34 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define lobject_c + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + +/* function to convert a string to a lua_Number */ +#ifndef lua_str2number +#define lua_str2number(s,p) strtod((s), (p)) +#endif + + +const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; + + +/* +** converts an integer to a "floating point byte", represented as +** (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm) +*/ +int luaO_int2fb (unsigned int x) { + int m = 0; /* mantissa */ + while (x >= (1<<3)) { + x = (x+1) >> 1; + m++; + } + return (m << 3) | cast(int, x); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_8[255] = { + 0, + 1,1, + 2,2,2,2, + 3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + if (x >= 0x00010000) { + if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24; + else return log_8[((x>>16) & 0xff) - 1]+16; + } + else { + if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8; + else if (x) return log_8[(x & 0xff) - 1]; + return -1; /* special `log' for 0 */ + } +} + + +int luaO_rawequalObj (const TObject *t1, const TObject *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return nvalue(t1) == nvalue(t2); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + lua_Number res = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* no conversion */ + while (isspace((unsigned char)(*endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + *result = res; + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': + pushstr(L, va_arg(argp, char *)); + break; + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': + setnvalue(L->top, cast(lua_Number, va_arg(argp, int))); + incr_top(L); + break; + case 'f': + setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber))); + incr_top(L); + break; + case '%': + pushstr(L, "%"); + break; + default: lua_assert(0); + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, L->top - L->base - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, int bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + int l; + source++; /* skip the `@' */ + bufflen -= sizeof(" `...' "); + l = strlen(source); + strcpy(out, ""); + if (l>bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + int len = strcspn(source, "\n"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/build/premake/src/Src/Lua/lobject.h b/build/premake/src/Src/Lua/lobject.h new file mode 100644 index 0000000000..321a7e06c1 --- /dev/null +++ b/build/premake/src/Src/Lua/lobject.h @@ -0,0 +1,336 @@ +/* +** $Id: lobject.h,v 1.159 2003/03/18 12:50:04 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + +#ifndef lobject_h +#define lobject_h + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define NUM_TAGS LUA_TTHREAD + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (NUM_TAGS+1) +#define LUA_TUPVAL (NUM_TAGS+2) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Lua values (or `tagged objects') +*/ +typedef struct lua_TObject { + int tt; + Value value; +} TObject; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* Macros to set values */ +#define setnvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); } + +#define chgnvalue(obj,x) \ + check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x)) + +#define setpvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); } + +#define setbvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); } + +#define setsvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); } + +#define setuvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); } + +#define setthvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); } + +#define setclvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); } + +#define sethvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); } + +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + + + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + + +#define setobj(obj1,obj2) \ + { const TObject *o2=(obj2); TObject *o1=(obj1); \ + checkconsistency(o2); \ + o1->tt=o2->tt; o1->value = o2->value; } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TObject *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + lu_hash hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(tsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TObject *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int lineDefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TObject *v; /* points to stack or to its own value */ + TObject value; /* the value (when closed) */ +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TObject upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + TObject g; /* global table for this closure */ + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef struct Node { + TObject i_key; + TObject i_val; + struct Node *next; /* for chaining */ +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + + +extern const TObject luaO_nilobject; + +int luaO_log2 (unsigned int x); +int luaO_int2fb (unsigned int x); +#define fb2int(x) (((x) & 7) << ((x) >> 3)) + +int luaO_rawequalObj (const TObject *t1, const TObject *t2); +int luaO_str2d (const char *s, lua_Number *result); + +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +void luaO_chunkid (char *out, const char *source, int len); + + +#endif diff --git a/build/premake/src/Src/Lua/lopcodes.c b/build/premake/src/Src/Lua/lopcodes.c new file mode 100644 index 0000000000..993e426d35 --- /dev/null +++ b/build/premake/src/Src/Lua/lopcodes.c @@ -0,0 +1,102 @@ +/* +** $Id: lopcodes.c,v 1.22 2002/12/04 17:38:31 roberto Exp $ +** extracted automatically from lopcodes.h by mkprint.lua +** DO NOT EDIT +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c + +#include "lua.h" + +#include "lobject.h" +#include "lopcodes.h" + + +#ifdef LUA_OPNAMES + +const char *const luaP_opnames[] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "POW", + "UNM", + "NOT", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "TFORLOOP", + "TFORPREP", + "SETLIST", + "SETLISTO", + "CLOSE", + "CLOSURE" +}; + +#endif + +#define opmode(t,b,bk,ck,sa,k,m) (((t)<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_A)) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then R(A) := R(B) else pc++ */ + +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 return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) =) R(A)*/ +OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_CLOSURE+1)) + + + +/*=========================================================================== + Notes: + (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (2) In OP_RETURN, if (B == 0) then return up to `top' + + (3) For comparisons, B specifies what conditions the test should accept. + + (4) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties +*/ +enum OpModeMask { + OpModeBreg = 2, /* B is a register */ + OpModeBrk, /* B is a register/constant */ + OpModeCrk, /* C is a register/constant */ + OpModesetA, /* instruction set register A */ + OpModeK, /* Bx is a constant */ + OpModeT /* operator is a test */ + +}; + + +extern const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define testOpMode(m, b) (luaP_opmodes[m] & (1 << (b))) + + +#ifdef LUA_OPNAMES +extern const char *const luaP_opnames[]; /* opcode names */ +#endif + + + +/* number of list items to accumulate before a SETLIST instruction */ +/* (must be a power of 2) */ +#define LFIELDS_PER_FLUSH 32 + + +#endif diff --git a/build/premake/src/Src/Lua/lparser.c b/build/premake/src/Src/Lua/lparser.c new file mode 100644 index 0000000000..99bd3020e7 --- /dev/null +++ b/build/premake/src/Src/Lua/lparser.c @@ -0,0 +1,1333 @@ +/* +** $Id: lparser.c,v 1.208a 2003/04/03 13:35:34 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" + + + + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + + +#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \ + luaX_syntaxerror(ls, "too many syntax levels"); +#define leavelevel(ls) ((ls)->nestlevel--) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + int nactvar; /* # active local variables outside the breakable structure */ + int upval; /* true if some variable in the block is an upvalue */ + int isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + + +static void next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */ +} + + +static void lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo); +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (!testnext(ls, c)) + error_expected(ls, c); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "`%s' expected (to close `%s' at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check_condition(ls, (ls->t.token == TK_NAME), " expected"); + ts = ls->t.seminfo.ts; + next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int luaI_registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, MAX_INT, ""); + f->locvars[fs->nlocvars].varname = varname; + return fs->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar += nvars; + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static void new_localvarstr (LexState *ls, const char *name, int n) { + new_localvar(ls, luaS_new(ls->L, name), n); +} + + +static void create_local (LexState *ls, const char *name) { + new_localvarstr(ls, name, 0); + adjustlocalvars(ls, 1); +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + for (i=0; inups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { + lua_assert(fs->f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues, + TString *, MAX_INT, ""); + fs->f->upvalues[f->nups] = name; + fs->upvalues[f->nups] = *v; + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + } + else { /* not found at current level; try upper one */ + singlevaraux(fs->prev, n, var, 0); + if (var->k == VGLOBAL) { + if (base) + var->info = luaK_stringK(fs, n); /* info points to global name */ + } + else { /* LOCAL or UPVAL */ + var->info = indexupvalue(fs, n, var); + var->k = VUPVAL; /* upvalue in this level */ + } + } + } +} + + +static TString *singlevar (LexState *ls, expdesc *var, int base) { + TString *varname = str_checkname(ls); + singlevaraux(ls->fs, varname, var, base); + return varname; +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (e->k == VCALL) { + extra++; /* includes call itself */ + if (extra <= 0) extra = 0; + else luaK_reserveregs(fs, extra-1); + luaK_setcallreturns(fs, e, extra); /* call provides the difference */ + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void code_params (LexState *ls, int nparams, int dots) { + FuncState *fs = ls->fs; + adjustlocalvars(ls, nparams); + luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters"); + fs->f->numparams = cast(lu_byte, fs->nactvar); + fs->f->is_vararg = cast(lu_byte, dots); + if (dots) + create_local(ls, "arg"); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + f->p[fs->np++] = func->f; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; if->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + Proto *f = luaF_newproto(ls->L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = ls->L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->h = luaH_new(ls->L, 0, 0); + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + lexstate.nestlevel = 0; + luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); + open_func(&lexstate, &funcstate); + next(&lexstate); /* read first token */ + chunk(&lexstate); + check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.nestlevel == 0); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void luaY_field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void luaY_index (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + check(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + if (ls->t.token == TK_NAME) { + luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); + cc->nh++; + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + luaY_index(ls, &key); + check(ls, '='); + luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key), + luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1); /* flush */ + cc->tostore = 0; /* no more items pending */ + fs->freereg = cc->t->info + 1; /* free registers */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (cc->v.k == VCALL) { + luaK_setcallreturns(fs, &cc->v, LUA_MULTRET); + luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1); + } + fs->freereg = cc->t->info + 1; /* free registers */ +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaX_checklimit(ls, cc->na, MAXARG_Bx, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + check(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + testnext(ls, ';'); /* compatibility only */ + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + int nparams = 0; + int dots = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_DOTS: dots = 1; next(ls); break; + case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; + default: luaX_syntaxerror(ls, " or `...' expected"); + } + } while (!dots && testnext(ls, ',')); + } + code_params(ls, nparams, dots); +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->lineDefined = line; + check(ls, '('); + if (needself) + create_local(ls, "self"); + parlist(ls); + check(ls, ')'); + chunk(ls); + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setcallreturns(fs, &args, LUA_MULTRET); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->info; /* base register for call */ + if (args.k == VCALL) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v, 1); + return; + } +#ifdef LUA_COMPATUPSYNTAX + case '%': { /* for compatibility only */ + TString *varname; + int line = ls->linenumber; + next(ls); /* skip `%' */ + varname = singlevar(ls, v, 1); + if (v->k != VUPVAL) + luaX_errorline(ls, "global upvalues are obsolete", + getstr(varname), line); + return; + } +#endif + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + luaY_field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + luaY_index(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | constructor | FUNCTION body + | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); + next(ls); /* must use `seminfo' before `next' */ + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + next(ls); /* must use `seminfo' before `next' */ + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + next(ls); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + next(ls); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + next(ls); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + break; + } + case TK_FUNCTION: { + next(ls); + body(ls, v, 0, ls->linenumber); + break; + } + default: { + primaryexp(ls, v); + break; + } + } +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MULT; + case '/': return OPR_DIV; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, /* arithmetic */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simplexep | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && cast(int, priority[op].left) > limit) { + expdesc v2; + BinOpr nextop; + next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, cast(int, priority[op].right)); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, -1); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.info == v->info) { /* conflict? */ + conflict = 1; + lh->v.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.aux == v->info) { /* conflict? */ + conflict = 1; + lh->v.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + check(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static void cond (LexState *ls, expdesc *v) { + /* cond -> exp */ + expr(ls, v); /* read condition */ + if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, v); + luaK_patchtohere(ls->fs, v->t); +} + + +/* +** The while statement optimizes its code by coding the condition +** after its body (and thus avoiding one jump in the loop). +*/ + +/* +** maximum size of expressions for optimizing `while' code +*/ +#ifndef MAXEXPWHILE +#define MAXEXPWHILE 100 +#endif + +/* +** the call `luaK_goiffalse' may grow the size of an expression by +** at most this: +*/ +#define EXTRAEXP 5 + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + Instruction codeexp[MAXEXPWHILE + EXTRAEXP]; + int lineexp; + int i; + int sizeexp; + FuncState *fs = ls->fs; + int whileinit, blockinit, expinit; + expdesc v; + BlockCnt bl; + next(ls); /* skip WHILE */ + whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */ + expinit = luaK_getlabel(fs); + expr(ls, &v); /* parse condition */ + if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ + lineexp = ls->linenumber; + luaK_goiffalse(fs, &v); + luaK_concat(fs, &v.f, fs->jpc); + fs->jpc = NO_JUMP; + sizeexp = fs->pc - expinit; /* size of expression code */ + if (sizeexp > MAXEXPWHILE) + luaX_syntaxerror(ls, "`while' condition too complex"); + for (i = 0; i < sizeexp; i++) /* save `exp' code */ + codeexp[i] = fs->f->code[expinit + i]; + fs->pc = expinit; /* remove `exp' code */ + enterblock(fs, &bl, 1); + check(ls, TK_DO); + blockinit = luaK_getlabel(fs); + block(ls); + luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ + /* move `exp' back to code */ + if (v.t != NO_JUMP) v.t += fs->pc - expinit; + if (v.f != NO_JUMP) v.f += fs->pc - expinit; + for (i=0; i REPEAT block UNTIL cond */ + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + expdesc v; + BlockCnt bl; + enterblock(fs, &bl, 1); + next(ls); + block(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + cond(ls, &v); + luaK_patchlist(fs, v.f, repeat_init); + leaveblock(fs); +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, nvars); /* scope for all variables */ + check(ls, TK_DO); + enterblock(fs, &bl, 1); /* loop block */ + prep = luaK_getlabel(fs); + block(ls); + luaK_patchtohere(fs, prep-1); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep); + leaveblock(fs); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] DO body */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvar(ls, varname, 0); + new_localvarstr(ls, "(for limit)", 1); + new_localvarstr(ls, "(for step)", 2); + check(ls, '='); + exp1(ls); /* initial value */ + check(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); + luaK_jump(fs); + forbody(ls, base, line, 3, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 DO body */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + new_localvarstr(ls, "(for generator)", nvars++); + new_localvarstr(ls, "(for state)", nvars++); + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + check(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, nvars, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP); + forbody(ls, base, line, nvars, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> fornum | forlist */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 0); /* block to control variable scope */ + next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, "`=' or `in' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); +} + + +static void test_then_block (LexState *ls, expdesc *v) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + next(ls); /* skip IF or ELSEIF */ + cond(ls, v); + check(ls, TK_THEN); + block(ls); /* `then' part */ +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + expdesc v; + int escapelist = NO_JUMP; + test_then_block(ls, &v); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, v.f); + test_then_block(ls, &v); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, v.f); + next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, v.f); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v, 1); + while (ls->t.token == '.') + luaY_field(ls, v); + if (ls->t.token == ':') { + needself = 1; + luaY_field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) { /* stat -> func */ + luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ + } + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (e.k == VCALL) { + luaK_setcallreturns(fs, &e, LUA_MULTRET); + if (nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static void breakstat (LexState *ls) { + /* stat -> BREAK [NAME] */ + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + next(ls); /* skip BREAK */ + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/build/premake/src/Src/Lua/lparser.h b/build/premake/src/Src/Lua/lparser.h new file mode 100644 index 0000000000..d6aaaf0e7d --- /dev/null +++ b/build/premake/src/Src/Lua/lparser.h @@ -0,0 +1,71 @@ +/* +** $Id: lparser.h,v 1.47 2003/02/11 10:46:24 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "ltable.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL /* info = result register */ +} expkind; + +typedef struct expdesc { + expkind k; + int info, aux; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + int nlocvars; /* number of elements in `locvars' */ + int nactvar; /* number of active local variables */ + expdesc upvalues[MAXUPVALUES]; /* upvalues */ + int actvar[MAXVARS]; /* declared-variable stack */ +} FuncState; + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff); + + +#endif diff --git a/build/premake/src/Src/Lua/lstate.c b/build/premake/src/Src/Lua/lstate.c new file mode 100644 index 0000000000..b593658def --- /dev/null +++ b/build/premake/src/Src/Lua/lstate.c @@ -0,0 +1,220 @@ +/* +** $Id: lstate.c,v 1.123 2003/04/03 13:35:34 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstate_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +/* +** macro to allow the inclusion of user information in Lua state +*/ +#ifndef LUA_USERSTATE +#define EXTRASPACE 0 +#else +union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;}; +#define EXTRASPACE (sizeof(union UEXTRASPACE)) +#endif + + + +/* +** you can change this function through the official API: +** call `lua_setpanicf' +*/ +static int default_panic (lua_State *L) { + UNUSED(L); + return 0; +} + + +static lua_State *mallocstate (lua_State *L) { + lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE); + if (block == NULL) return NULL; + else { + block += EXTRASPACE; + return cast(lua_State *, block); + } +} + + +static void freestate (lua_State *L, lua_State *L1) { + luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, + sizeof(lua_State) + EXTRASPACE); +} + + +static void stack_init (lua_State *L1, lua_State *L) { + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->ci->state = CI_C; /* not a Lua function */ + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TObject); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + /* create a new global state */ + global_State *g = luaM_new(NULL, global_State); + UNUSED(ud); + if (g == NULL) luaD_throw(L, LUA_ERRMEM); + L->l_G = g; + g->mainthread = L; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(defaultmeta(L)); + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = default_panic; + g->rootgc = NULL; + g->rootudata = NULL; + g->tmudata = NULL; + setnilvalue(gkey(g->dummynode)); + setnilvalue(gval(g->dummynode)); + g->dummynode->next = NULL; + g->nblocks = sizeof(lua_State) + sizeof(global_State); + stack_init(L, L); /* init stack */ + /* create default meta table with a dummy table, and then close the loop */ + defaultmeta(L)->tt = LUA_TTABLE; + sethvalue(defaultmeta(L), luaH_new(L, 0, 0)); + hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L)); + sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ + sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*G(L)->nblocks; +} + + +static void preinit_state (lua_State *L) { + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = L->hookinit = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = 0; + L->base_ci = L->ci = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + luaF_close(L, L->stack); /* close all upvalues for this thread */ + if (G(L)) { /* close global state */ + luaC_sweep(L, 1); /* collect all elements */ + lua_assert(G(L)->rootgc == NULL); + lua_assert(G(L)->rootudata == NULL); + luaS_freeall(L); + luaZ_freebuffer(L, &G(L)->buff); + } + freestack(L, L); + if (G(L)) { + lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State)); + luaM_freelem(NULL, G(L)); + } + freestate(NULL, L); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = mallocstate(L); + luaC_link(L, valtogco(L1), LUA_TTHREAD); + preinit_state(L1); + L1->l_G = L->l_G; + stack_init(L1, L); /* init stack */ + setobj2n(gt(L1), gt(L)); /* share table of globals */ + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + freestack(L, L1); + freestate(L, L1); +} + + +LUA_API lua_State *lua_open (void) { + lua_State *L = mallocstate(NULL); + if (L) { /* allocation OK? */ + L->tt = LUA_TTHREAD; + L->marked = 0; + L->next = L->gclist = NULL; + preinit_state(L); + L->l_G = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + } + lua_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + lua_lock(L); + L = G(L)->mainthread; /* only the main thread can be closed */ + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + close_state(L); +} + diff --git a/build/premake/src/Src/Lua/lstate.h b/build/premake/src/Src/Lua/lstate.h new file mode 100644 index 0000000000..5422f1b196 --- /dev/null +++ b/build/premake/src/Src/Lua/lstate.h @@ -0,0 +1,195 @@ +/* +** $Id: lstate.h,v 1.109 2003/02/27 11:52:30 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + +/* +** macros for thread synchronization inside Lua core machine: +** all accesses to the global state and to global objects are synchronized. +** Because threads can read the stack of other threads +** (when running garbage collection), +** a thread must also synchronize any write-access to its own stack. +** Unsynchronized accesses are allowed only when reading its own stack, +** or when reading immutable fields from global objects +** (such as string values and udata values). +*/ +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#endif + +#ifndef lua_unlock +#define lua_unlock(L) ((void) 0) +#endif + + +#ifndef lua_userstateopen +#define lua_userstateopen(l) +#endif + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* default meta table (both for tables and udata) */ +#define defaultmeta(L) (&G(L)->_defaultmeta) + +/* table of globals */ +#define gt(L) (&L->_gt) + +/* registry */ +#define registry(L) (&G(L)->_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + ls_nstr nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for called function */ + StkId top; /* top for this function */ + int state; /* bit fields; see below */ + union { + struct { /* for Lua functions */ + const Instruction *savedpc; + const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ + int tailcalls; /* number of tail calls lost under this entry */ + } l; + struct { /* for C functions */ + int dummy; /* just to avoid an empty struct */ + } c; + } u; +} CallInfo; + + +/* +** bit fields for `CallInfo.state' +*/ +#define CI_C (1<<0) /* 1 if function is a C function */ +/* 1 if (Lua) function has an active `luaV_execute' running it */ +#define CI_HASFRAME (1<<1) +/* 1 if Lua function is calling another Lua function (and therefore its + `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */ +#define CI_CALLING (1<<2) +#define CI_SAVEDPC (1<<3) /* 1 if `savedpc' is updated */ +#define CI_YIELD (1<<4) /* 1 if thread is suspended */ + + +#define ci_func(ci) (clvalue((ci)->base - 1)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + GCObject *rootgc; /* list of (almost) all collectable objects */ + GCObject *rootudata; /* (separated) list of all userdata */ + GCObject *tmudata; /* list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem nblocks; /* number of `bytes' currently allocated */ + lua_CFunction panic; /* to be called in unprotected errors */ + TObject _registry; + TObject _defaultmeta; + struct lua_State *mainthread; + Node dummynode[1]; /* common node array for all empty tables */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + int stacksize; + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + unsigned short size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + lu_byte hookmask; + lu_byte allowhook; + lu_byte hookinit; + int basehookcount; + int hookcount; + lua_Hook hook; + TObject _gt; /* table of globals */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define gcotots(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gcotou(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gcotocl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gcotoh(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gcotop(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gcotouv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gcototh(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any value into a GCObject */ +#define valtogco(v) (cast(GCObject *, (v))) + + +lua_State *luaE_newthread (lua_State *L); +void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/build/premake/src/Src/Lua/lstring.c b/build/premake/src/Src/Lua/lstring.c new file mode 100644 index 0000000000..8cbddbd218 --- /dev/null +++ b/build/premake/src/Src/Lua/lstring.c @@ -0,0 +1,102 @@ +/* +** $Id: lstring.c,v 1.78 2002/12/04 17:38:31 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_freeall (lua_State *L) { + lua_assert(G(L)->strt.nuse==0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); +} + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash = luaM_newvector(L, newsize, GCObject *); + stringtable *tb = &G(L)->strt; + int i; + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + lu_hash h = gcotots(p)->tsv.hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast(int, h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) { + TString *ts = cast(TString *, luaM_malloc(L, sizestring(l))); + stringtable *tb; + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = 0; + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = valtogco(ts); + tb->nuse++; + if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + lu_hash h = (lu_hash)l; /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = gcotots(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) + return ts; + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s) { + Udata *u; + u = cast(Udata *, luaM_malloc(L, sizeudata(s))); + u->uv.marked = (1<<1); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = hvalue(defaultmeta(L)); + /* chain it on udata list */ + u->uv.next = G(L)->rootudata; + G(L)->rootudata = valtogco(u); + return u; +} + diff --git a/build/premake/src/Src/Lua/lstring.h b/build/premake/src/Src/Lua/lstring.h new file mode 100644 index 0000000000..be5a1e3767 --- /dev/null +++ b/build/premake/src/Src/Lua/lstring.h @@ -0,0 +1,33 @@ +/* +** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lobject.h" +#include "lstate.h" + + + +#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ + (cast(lu_mem, l)+1)*sizeof(char)) + +#define sizeudata(l) (cast(lu_mem, sizeof(union Udata))+(l)) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) ((s)->tsv.marked |= (1<<4)) + +void luaS_resize (lua_State *L, int newsize); +Udata *luaS_newudata (lua_State *L, size_t s); +void luaS_freeall (lua_State *L); +TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/build/premake/src/Src/Lua/lstrlib.c b/build/premake/src/Src/Lua/lstrlib.c new file mode 100644 index 0000000000..8752e3aba3 --- /dev/null +++ b/build/premake/src/Src/Lua/lstrlib.c @@ -0,0 +1,770 @@ +/* +** $Id: lstrlib.c,v 1.98 2003/04/03 13:35:34 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#ifndef uchar +#define uchar(c) ((unsigned char)(c)) +#endif + + +typedef long sint32; /* a signed version for size_t */ + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushnumber(L, (lua_Number)l); + return 1; +} + + +static sint32 posrelat (sint32 pos, size_t len) { + /* relative string position: negative means back from end */ + return (pos>=0) ? pos : (sint32)len+pos+1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 start = posrelat(luaL_checklong(L, 2), l); + sint32 end = posrelat(luaL_optlong(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (sint32)l) end = (sint32)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); + if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */ + return 0; /* no answer */ + lua_pushnumber(L, uchar(s[pos-1])); + return 1; +} + + +static int str_char (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i=1; i<=n; i++) { + int c = luaL_checkint(L, i); + luaL_argcheck(L, uchar(c) == c, i, "invalid value"); + luaL_putchar(&b, uchar(c)); + } + luaL_pushresult(&b); + return 1; +} + + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 1; +} + + +static int str_dump (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_buffinit(L,&b); + if (!lua_dump(L, writer, &b)) + luaL_error(L, "unable to dump given function"); + luaL_pushresult(&b); + return 1; +} + + + +/* +** {====================================================== +** PATTERN MATCHING +** ======================================================= +*/ + +#ifndef MAX_CAPTURES +#define MAX_CAPTURES 32 /* arbitrary limit */ +#endif + + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + +typedef struct MatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end (`\0') of source string */ + lua_State *L; + int level; /* total number of captures (finished or unfinished) */ + struct { + const char *init; + sint32 len; + } capture[MAX_CAPTURES]; +} MatchState; + + +#define ESC '%' +#define SPECIALS "^$*+?.([%-" + + +static int check_capture (MatchState *ms, int l) { + l -= '1'; + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *luaI_classend (MatchState *ms, const char *p) { + switch (*p++) { + case ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with `%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing `]')"); + if (*(p++) == ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == ESC) { + p++; + if (match_class(c, *p)) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int luaI_singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case ESC: return match_class(c, *(p+1)); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + sint32 i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && luaI_singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && luaI_singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing `[' after `%%f' in pattern"); + ep = luaI_classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, *(p+1)); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = luaI_classend(ms, p); /* points to what is next */ + int m = ssrc_end && luaI_singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i) { + int l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + luaL_checkstack(ms->L, ms->level, "too many captures"); + if (ms->level == 0 && s) { /* no explicit captures? */ + lua_pushlstring(ms->L, s, e-s); /* return whole match */ + return 1; + } + else { /* return all captures */ + for (i=0; ilevel; i++) + push_onecapture(ms, i); + return ms->level; /* number of strings pushed */ + } +} + + +static int str_find (lua_State *L) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (sint32)l1; + if (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushnumber(L, (lua_Number)(s2-s+1)); + lua_pushnumber(L, (lua_Number)(s2-s+l2)); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ + lua_pushnumber(L, (lua_Number)(res-s)); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + } while (s1++L; + if (lua_isstring(L, 3)) { + const char *news = lua_tostring(L, 3); + size_t l = lua_strlen(L, 3); + size_t i; + for (i=0; i= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), + 3, "string or function expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_s(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_putchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* maximum size of each format specification (such as '%-099.99d') */ +#define MAX_FORMAT 20 + + +static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_putchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_putchar(b, '\\'); + luaL_putchar(b, *s); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_putchar(b, *s); + break; + } + } + s++; + } + luaL_putchar(b, '"'); +} + + +static const char *scanformat (lua_State *L, const char *strfrmt, + char *form, int *hasprecision) { + const char *p = strfrmt; + while (strchr("-+ #0", *p)) p++; /* skip flags */ + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + *hasprecision = 1; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ + luaL_error(L, "invalid format (too long)"); + form[0] = '%'; + strncpy(form+1, strfrmt, p-strfrmt+1); + form[p-strfrmt+2] = 0; + return p; +} + + +static int str_format (lua_State *L) { + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != '%') + luaL_putchar(&b, *strfrmt++); + else if (*++strfrmt == '%') + luaL_putchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + int hasprecision = 0; + if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') + return luaL_error(L, "obsolete option (d$) to `format'"); + arg++; + strfrmt = scanformat(L, strfrmt, form, &hasprecision); + switch (*strfrmt++) { + case 'c': case 'd': case 'i': { + sprintf(buff, form, luaL_checkint(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, luaL_checknumber(L, arg)); + break; + } + case 'q': { + luaI_addquoted(L, &b, arg); + continue; /* skip the `addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!hasprecision && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option to `format'"); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_reg strlib[] = { + {"len", str_len}, + {"sub", str_sub}, + {"lower", str_lower}, + {"upper", str_upper}, + {"char", str_char}, + {"rep", str_rep}, + {"byte", str_byte}, + {"format", str_format}, + {"dump", str_dump}, + {"find", str_find}, + {"gfind", gfind}, + {"gsub", str_gsub}, + {NULL, NULL} +}; + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); + return 1; +} + diff --git a/build/premake/src/Src/Lua/ltable.c b/build/premake/src/Src/Lua/ltable.c new file mode 100644 index 0000000000..0c64adb10a --- /dev/null +++ b/build/premake/src/Src/Lua/ltable.c @@ -0,0 +1,509 @@ +/* +** $Id: ltable.c,v 1.132 2003/04/03 13:35:34 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** In other words, there are collisions only when two elements have the +** same main position (i.e. the same hash values for that table size). +** Because of that, the load factor of these tables can be 100% without +** performance penalties. +*/ + +#include + +#define ltable_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if BITS_INT > 26 +#define MAXBITS 24 +#else +#define MAXBITS (BITS_INT-2) +#endif + +/* check whether `x' < 2^MAXBITS */ +#define toobig(x) ((((x)-1) >> MAXBITS) != 0) + + +/* function to convert a lua_Number to int (with any rounding method) */ +#ifndef lua_number2int +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast(int, sizeof(lua_Number)/sizeof(int)) + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + n += 1; /* normalize number (avoid -0) */ + lua_assert(sizeof(a) <= sizeof(n)); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, cast(lu_hash, a[0])); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +Node *luaH_mainposition (const Table *t, const TObject *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, tsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TObject *key) { + if (ttisnumber(key)) { + int k; + lua_number2int(k, (nvalue(key))); + if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning and end of a traversal are signalled by -1. +*/ +static int luaH_index (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 <= i && i <= t->sizearray) { /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + } + else { + const TObject *v = luaH_get(t, key); + if (v == &luaO_nilobject) + luaG_runerror(L, "invalid key for `next'"); + i = cast(int, (cast(const lu_byte *, v) - + cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node)); + return i + t->sizearray; /* hash elements are numbered after array ones */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = luaH_index(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast(lua_Number, i+1)); + setobj2s(key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(key, gkey(gnode(t, i))); + setobj2s(key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { + int i; + int a = nums[0]; /* number of elements smaller than 2^i */ + int na = a; /* number of elements to go to array part */ + int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */ + for (i = 1; a < *narray && *narray >= twoto(i-1); i++) { + if (nums[i] > 0) { + a += nums[i]; + if (a >= twoto(i-1)) { /* more than half elements in use? */ + n = i; + na = a; + } + } + } + lua_assert(na <= *narray && *narray <= ntotal); + *nhash = ntotal - na; + *narray = (n == -1) ? 0 : twoto(n); + lua_assert(na <= *narray && na >= *narray/2); +} + + +static void numuse (const Table *t, int *narray, int *nhash) { + int nums[MAXBITS+1]; + int i, lg; + int totaluse = 0; + /* count elements in array part */ + for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */ + int ttlg = twoto(lg); /* 2^lg */ + if (ttlg > t->sizearray) { + ttlg = t->sizearray; + if (i >= ttlg) break; + } + nums[lg] = 0; + for (; iarray[i])) { + nums[lg]++; + totaluse++; + } + } + } + for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */ + *narray = totaluse; /* all previous uses were in array part */ + /* count elements in hash part */ + i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + int k = arrayindex(gkey(n)); + if (k >= 0) { /* is `key' an appropriate array index? */ + nums[luaO_log2(k-1)+1]++; /* count as such */ + (*narray)++; + } + totaluse++; + } + } + computesizes(nums, totaluse, narray, nhash); +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TObject); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int lsize) { + int i; + int size = twoto(lsize); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + if (lsize == 0) { /* no elements to hash part? */ + t->node = G(L)->dummynode; /* use common `dummynode' */ + lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */ + lua_assert(ttisnil(gval(t->node))); + lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */ + } + else { + t->node = luaM_newvector(L, size, Node); + for (i=0; inode[i].next = NULL; + setnilvalue(gkey(gnode(t, i))); + setnilvalue(gval(gnode(t, i))); + } + } + t->lsizenode = cast(lu_byte, lsize); + t->firstfree = gnode(t, size-1); /* first free position to be used */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold; + Node temp[1]; + if (oldhsize) + nold = t->node; /* save old hash ... */ + else { /* old hash is `dummynode' */ + lua_assert(t->node == G(L)->dummynode); + temp[0] = t->node[0]; /* copy it to `temp' */ + nold = temp; + setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */ + setnilvalue(gval(G(L)->dummynode)); + lua_assert(G(L)->dummynode->next == NULL); + } + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + /* re-insert elements */ + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TObject); + } + /* re-insert elements in hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(luaH_set(L, t, gkey(old)), gval(old)); + } + if (oldhsize) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +static void rehash (lua_State *L, Table *t) { + int nasize, nhsize; + numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */ + resize(L, t, nasize, luaO_log2(nhsize)+1); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int lnhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, valtogco(t), LUA_TTABLE); + t->metatable = hvalue(defaultmeta(L)); + t->flags = cast(lu_byte, ~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = NULL; + setarrayvector(L, t, narray); + setnodevector(L, t, lnhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->lsizenode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TObject); + luaM_freelem(L, t); +} + + +#if 0 +/* +** try to remove an element from a hash table; cannot move any element +** (because gc can call `remove' during a table traversal) +*/ +void luaH_remove (Table *t, Node *e) { + Node *mp = luaH_mainposition(t, gkey(e)); + if (e != mp) { /* element not in its main position? */ + while (mp->next != e) mp = mp->next; /* find previous */ + mp->next = e->next; /* remove `e' from its list */ + } + else { + if (e->next != NULL) ?? + } + lua_assert(ttisnil(gval(node))); + setnilvalue(gkey(e)); /* clear node `e' */ + e->next = NULL; +} +#endif + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TObject *newkey (lua_State *L, Table *t, const TObject *key) { + TObject *val; + Node *mp = luaH_mainposition(t, key); + if (!ttisnil(gval(mp))) { /* main position is not free? */ + Node *othern = luaH_mainposition(t, gkey(mp)); /* `mp' of colliding node */ + Node *n = t->firstfree; /* get a free place */ + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (othern->next != mp) othern = othern->next; /* find previous */ + othern->next = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + mp->next = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + setobj2t(gkey(mp), key); /* write barrier */ + lua_assert(ttisnil(gval(mp))); + for (;;) { /* correct `firstfree' */ + if (ttisnil(gkey(t->firstfree))) + return gval(mp); /* OK; table still has a free place */ + else if (t->firstfree == t->node) break; /* cannot decrement from here */ + else (t->firstfree)--; + } + /* no more free places; must create one */ + setbvalue(gval(mp), 0); /* avoid new key being removed */ + rehash(L, t); /* grow table */ + val = cast(TObject *, luaH_get(t, key)); /* get new position */ + lua_assert(ttisboolean(val)); + setnilvalue(val); + return val; +} + + +/* +** generic search function +*/ +static const TObject *luaH_getany (Table *t, const TObject *key) { + if (ttisnil(key)) return &luaO_nilobject; + else { + Node *n = luaH_mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; + } +} + + +/* +** search function for integers +*/ +const TObject *luaH_getnum (Table *t, int key) { + if (1 <= key && key <= t->sizearray) + return &t->array[key-1]; + else { + lua_Number nk = cast(lua_Number, key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk) + return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TObject *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; +} + + +/* +** main search function +*/ +const TObject *luaH_get (Table *t, const TObject *key) { + switch (ttype(key)) { + case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_number2int(k, (nvalue(key))); + if (cast(lua_Number, k) == nvalue(key)) /* is an integer index? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: return luaH_getany(t, key); + } +} + + +TObject *luaH_set (lua_State *L, Table *t, const TObject *key) { + const TObject *p = luaH_get(t, key); + t->flags = 0; + if (p != &luaO_nilobject) + return cast(TObject *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && nvalue(key) != nvalue(key)) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TObject *luaH_setnum (lua_State *L, Table *t, int key) { + const TObject *p = luaH_getnum(t, key); + if (p != &luaO_nilobject) + return cast(TObject *, p); + else { + TObject k; + setnvalue(&k, cast(lua_Number, key)); + return newkey(L, t, &k); + } +} + diff --git a/build/premake/src/Src/Lua/ltable.h b/build/premake/src/Src/Lua/ltable.h new file mode 100644 index 0000000000..3d4d753c3c --- /dev/null +++ b/build/premake/src/Src/Lua/ltable.h @@ -0,0 +1,31 @@ +/* +** $Id: ltable.h,v 1.44 2003/03/18 12:50:04 roberto Exp $ +** 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 gkey(n) (&(n)->i_key) +#define gval(n) (&(n)->i_val) + + +const TObject *luaH_getnum (Table *t, int key); +TObject *luaH_setnum (lua_State *L, Table *t, int key); +const TObject *luaH_getstr (Table *t, TString *key); +const TObject *luaH_get (Table *t, const TObject *key); +TObject *luaH_set (lua_State *L, Table *t, const TObject *key); +Table *luaH_new (lua_State *L, int narray, int lnhash); +void luaH_free (lua_State *L, Table *t); +int luaH_next (lua_State *L, Table *t, StkId key); + +/* exported only for debugging */ +Node *luaH_mainposition (const Table *t, const TObject *key); + + +#endif diff --git a/build/premake/src/Src/Lua/ltablib.c b/build/premake/src/Src/Lua/ltablib.c new file mode 100644 index 0000000000..c9bb2d1b7e --- /dev/null +++ b/build/premake/src/Src/Lua/ltablib.c @@ -0,0 +1,250 @@ +/* +** $Id: ltablib.c,v 1.21 2003/04/03 13:35:34 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int luaB_foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i<=n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushnumber(L, (lua_Number)i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int luaB_foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + for (;;) { + if (lua_next(L, 1) == 0) + return 0; + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } +} + + +static int luaB_getn (lua_State *L) { + lua_pushnumber(L, (lua_Number)aux_getn(L, 1)); + return 1; +} + + +static int luaB_setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_setn(L, 1, luaL_checkint(L, 2)); + return 0; +} + + +static int luaB_tinsert (lua_State *L) { + int v = lua_gettop(L); /* number of arguments */ + int n = aux_getn(L, 1) + 1; + int pos; /* where to insert new element */ + if (v == 2) /* called with only 2 arguments */ + pos = n; /* insert new element at the end */ + else { + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > n) n = pos; /* `grow' array if necessary */ + v = 3; /* function may be called with more than 3 args */ + } + luaL_setn(L, 1, n); /* new size */ + while (--n >= pos) { /* move up elements */ + lua_rawgeti(L, 1, n); + lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ + } + lua_pushvalue(L, v); + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int luaB_tremove (lua_State *L) { + int n = aux_getn(L, 1); + int pos = luaL_optint(L, 2, n); + if (n <= 0) return 0; /* table is `empty' */ + luaL_setn(L, 1, n-1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j +#include +#include +#include +#include + +#define ltests_c + +#include "lua.h" + +#include "lapi.h" +#include "lauxlib.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lualib.h" + + + +/* +** The whole module only makes sense with LUA_DEBUG on +*/ +#ifdef LUA_DEBUG + + +#define lua_pushintegral(L,i) lua_pushnumber(L, cast(lua_Number, (i))) + + +static lua_State *lua_state = NULL; + +int islocked = 0; + + +#define func_at(L,k) (L->ci->base+(k) - 1) + + +static void setnameval (lua_State *L, const char *name, int val) { + lua_pushstring(L, name); + lua_pushintegral(L, val); + lua_settable(L, -3); +} + + +/* +** {====================================================================== +** Controlled version for realloc. +** ======================================================================= +*/ + +#define MARK 0x55 /* 01010101 (a nice pattern) */ + +#ifndef EXTERNMEMCHECK +/* full memory check */ +#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */ +#define MARKSIZE 16 /* size of marks after each block */ +#define blockhead(b) (cast(char *, b) - HEADER) +#define setsize(newblock, size) (*cast(size_t *, newblock) = size) +#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b)))) +#define fillmem(mem,size) memset(mem, -MARK, size) +#else +/* external memory check: don't do it twice */ +#define HEADER 0 +#define MARKSIZE 0 +#define blockhead(b) (b) +#define setsize(newblock, size) /* empty */ +#define checkblocksize(b,size) (1) +#define fillmem(mem,size) /* empty */ +#endif + +unsigned long memdebug_numblocks = 0; +unsigned long memdebug_total = 0; +unsigned long memdebug_maxmem = 0; +unsigned long memdebug_memlimit = ULONG_MAX; + + +static void *checkblock (void *block, size_t size) { + void *b = blockhead(block); + int i; + for (i=0;i 0); + if (size == 0) { + freeblock(block, oldsize); + return NULL; + } + else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) + return NULL; /* to test memory allocation errors */ + else { + void *newblock; + int i; + size_t realsize = HEADER+size+MARKSIZE; + size_t commonsize = (oldsize < size) ? oldsize : size; + if (realsize < size) return NULL; /* overflow! */ + newblock = malloc(realsize); /* alloc a new block */ + if (newblock == NULL) return NULL; + if (block) { + memcpy(cast(char *, newblock)+HEADER, block, commonsize); + freeblock(block, oldsize); /* erase (and check) old copy */ + } + /* initialize new part of the block with something `weird' */ + fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); + memdebug_total += size; + if (memdebug_total > memdebug_maxmem) + memdebug_maxmem = memdebug_total; + memdebug_numblocks++; + setsize(newblock, size); + for (i=0;icode[pc]; + OpCode o = GET_OPCODE(i); + const char *name = luaP_opnames[o]; + int line = getline(p, pc); + sprintf(buff, "(%4d) %4d - ", line, pc); + switch (getOpMode(o)) { + case iABC: + sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name, + GETARG_A(i), GETARG_B(i), GETARG_C(i)); + break; + case iABx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); + break; + case iAsBx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i)); + break; + } + return buff; +} + + +#if 0 +void luaI_printcode (Proto *pt, int size) { + int pc; + for (pc=0; pcl.p; + lua_newtable(L); + setnameval(L, "maxstack", p->maxstacksize); + setnameval(L, "numparams", p->numparams); + for (pc=0; pcsizecode; pc++) { + char buff[100]; + lua_pushintegral(L, pc+1); + lua_pushstring(L, buildop(p, pc, buff)); + lua_settable(L, -3); + } + return 1; +} + + +static int listk (lua_State *L) { + Proto *p; + int i; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(func_at(L, 1))->l.p; + lua_newtable(L); + for (i=0; isizek; i++) { + lua_pushintegral(L, i+1); + luaA_pushobject(L, p->k+i); + lua_settable(L, -3); + } + return 1; +} + + +static int listlocals (lua_State *L) { + Proto *p; + int pc = luaL_checkint(L, 2) - 1; + int i = 0; + const char *name; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(func_at(L, 1))->l.p; + while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) + lua_pushstring(L, name); + return i-1; +} + +/* }====================================================== */ + + + + +static int get_limits (lua_State *L) { + lua_newtable(L); + setnameval(L, "BITS_INT", BITS_INT); + setnameval(L, "LFPF", LFIELDS_PER_FLUSH); + setnameval(L, "MAXVARS", MAXVARS); + setnameval(L, "MAXPARAMS", MAXPARAMS); + setnameval(L, "MAXSTACK", MAXSTACK); + setnameval(L, "MAXUPVALUES", MAXUPVALUES); + return 1; +} + + +static int mem_query (lua_State *L) { + if (lua_isnone(L, 1)) { + lua_pushintegral(L, memdebug_total); + lua_pushintegral(L, memdebug_numblocks); + lua_pushintegral(L, memdebug_maxmem); + return 3; + } + else { + memdebug_memlimit = luaL_checkint(L, 1); + return 0; + } +} + + +static int hash_query (lua_State *L) { + if (lua_isnone(L, 2)) { + luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); + lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash); + } + else { + TObject *o = func_at(L, 1); + Table *t; + luaL_checktype(L, 2, LUA_TTABLE); + t = hvalue(func_at(L, 2)); + lua_pushintegral(L, luaH_mainposition(t, o) - t->node); + } + return 1; +} + + +static int stacklevel (lua_State *L) { + unsigned long a = 0; + lua_pushintegral(L, (int)(L->top - L->stack)); + lua_pushintegral(L, (int)(L->stack_last - L->stack)); + lua_pushintegral(L, (int)(L->ci - L->base_ci)); + lua_pushintegral(L, (int)(L->end_ci - L->base_ci)); + lua_pushintegral(L, (unsigned long)&a); + return 5; +} + + +static int table_query (lua_State *L) { + const Table *t; + int i = luaL_optint(L, 2, -1); + luaL_checktype(L, 1, LUA_TTABLE); + t = hvalue(func_at(L, 1)); + if (i == -1) { + lua_pushintegral(L, t->sizearray); + lua_pushintegral(L, sizenode(t)); + lua_pushintegral(L, t->firstfree - t->node); + } + else if (i < t->sizearray) { + lua_pushintegral(L, i); + luaA_pushobject(L, &t->array[i]); + lua_pushnil(L); + } + else if ((i -= t->sizearray) < sizenode(t)) { + if (!ttisnil(gval(gnode(t, i))) || + ttisnil(gkey(gnode(t, i))) || + ttisnumber(gkey(gnode(t, i)))) { + luaA_pushobject(L, gkey(gnode(t, i))); + } + else + lua_pushstring(L, ""); + luaA_pushobject(L, gval(gnode(t, i))); + if (t->node[i].next) + lua_pushintegral(L, t->node[i].next - t->node); + else + lua_pushnil(L); + } + return 3; +} + + +static int string_query (lua_State *L) { + stringtable *tb = &G(L)->strt; + int s = luaL_optint(L, 2, 0) - 1; + if (s==-1) { + lua_pushintegral(L ,tb->nuse); + lua_pushintegral(L ,tb->size); + return 2; + } + else if (s < tb->size) { + GCObject *ts; + int n = 0; + for (ts = tb->hash[s]; ts; ts = ts->gch.next) { + setsvalue2s(L->top, gcotots(ts)); + incr_top(L); + n++; + } + return n; + } + return 0; +} + + +static int tref (lua_State *L) { + int level = lua_gettop(L); + int lock = luaL_optint(L, 2, 1); + luaL_checkany(L, 1); + lua_pushvalue(L, 1); + lua_pushintegral(L, lua_ref(L, lock)); + assert(lua_gettop(L) == level+1); /* +1 for result */ + return 1; +} + +static int getref (lua_State *L) { + int level = lua_gettop(L); + lua_getref(L, luaL_checkint(L, 1)); + assert(lua_gettop(L) == level+1); + return 1; +} + +static int unref (lua_State *L) { + int level = lua_gettop(L); + lua_unref(L, luaL_checkint(L, 1)); + assert(lua_gettop(L) == level); + return 0; +} + +static int metatable (lua_State *L) { + luaL_checkany(L, 1); + if (lua_isnone(L, 2)) { + if (lua_getmetatable(L, 1) == 0) + lua_pushnil(L); + } + else { + lua_settop(L, 2); + luaL_checktype(L, 2, LUA_TTABLE); + lua_setmetatable(L, 1); + } + return 1; +} + + +static int upvalue (lua_State *L) { + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_isnone(L, 3)) { + const char *name = lua_getupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + return 2; + } + else { + const char *name = lua_setupvalue(L, 1, n); + lua_pushstring(L, name); + return 1; + } +} + + +static int newuserdata (lua_State *L) { + size_t size = luaL_checkint(L, 1); + char *p = cast(char *, lua_newuserdata(L, size)); + while (size--) *p++ = '\0'; + return 1; +} + + +static int pushuserdata (lua_State *L) { + lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1))); + return 1; +} + + +static int udataval (lua_State *L) { + lua_pushintegral(L, cast(int, lua_touserdata(L, 1))); + return 1; +} + + +static int doonnewstack (lua_State *L) { + lua_State *L1 = lua_newthread(L); + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + int status = luaL_loadbuffer(L1, s, l, s); + if (status == 0) + status = lua_pcall(L1, 0, 0, 0); + lua_pushintegral(L, status); + return 1; +} + + +static int s2d (lua_State *L) { + lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1))); + return 1; +} + +static int d2s (lua_State *L) { + double d = luaL_checknumber(L, 1); + lua_pushlstring(L, cast(char *, &d), sizeof(d)); + return 1; +} + + +static int newstate (lua_State *L) { + lua_State *L1 = lua_open(); + if (L1) { + lua_userstateopen(L1); /* init lock */ + lua_pushintegral(L, (unsigned long)L1); + } + else + lua_pushnil(L); + return 1; +} + + +static int loadlib (lua_State *L) { + static const luaL_reg libs[] = { + {"mathlibopen", luaopen_math}, + {"strlibopen", luaopen_string}, + {"iolibopen", luaopen_io}, + {"tablibopen", luaopen_table}, + {"dblibopen", luaopen_debug}, + {"baselibopen", luaopen_base}, + {NULL, NULL} + }; + lua_State *L1 = cast(lua_State *, + cast(unsigned long, luaL_checknumber(L, 1))); + lua_pushvalue(L1, LUA_GLOBALSINDEX); + luaL_openlib(L1, NULL, libs, 0); + return 0; +} + +static int closestate (lua_State *L) { + lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1))); + lua_close(L1); + lua_unlock(L); /* close cannot unlock that */ + return 0; +} + +static int doremote (lua_State *L) { + lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1))); + size_t lcode; + const char *code = luaL_checklstring(L, 2, &lcode); + int status; + lua_settop(L1, 0); + status = luaL_loadbuffer(L1, code, lcode, code); + if (status == 0) + status = lua_pcall(L1, 0, LUA_MULTRET, 0); + if (status != 0) { + lua_pushnil(L); + lua_pushintegral(L, status); + lua_pushstring(L, lua_tostring(L1, -1)); + return 3; + } + else { + int i = 0; + while (!lua_isnone(L1, ++i)) + lua_pushstring(L, lua_tostring(L1, i)); + lua_pop(L1, i-1); + return i-1; + } +} + + +static int log2_aux (lua_State *L) { + lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1))); + return 1; +} + +static int int2fb_aux (lua_State *L) { + int b = luaO_int2fb(luaL_checkint(L, 1)); + lua_pushintegral(L, b); + lua_pushintegral(L, fb2int(b)); + return 2; +} + + +static int test_do (lua_State *L) { + const char *p = luaL_checkstring(L, 1); + if (*p == '@') + lua_dofile(L, p+1); + else + lua_dostring(L, p); + return lua_gettop(L); +} + + + +/* +** {====================================================== +** function to test the API with C. It interprets a kind of assembler +** language with calls to the API, so the test can be driven by Lua code +** ======================================================= +*/ + +static const char *const delimits = " \t\n,;"; + +static void skip (const char **pc) { + while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; +} + +static int getnum_aux (lua_State *L, const char **pc) { + int res = 0; + int sig = 1; + skip(pc); + if (**pc == '.') { + res = cast(int, lua_tonumber(L, -1)); + lua_pop(L, 1); + (*pc)++; + return res; + } + else if (**pc == '-') { + sig = -1; + (*pc)++; + } + while (isdigit(cast(int, **pc))) res = res*10 + (*(*pc)++) - '0'; + return sig*res; +} + +static const char *getname_aux (char *buff, const char **pc) { + int i = 0; + skip(pc); + while (**pc != '\0' && !strchr(delimits, **pc)) + buff[i++] = *(*pc)++; + buff[i] = '\0'; + return buff; +} + + +#define EQ(s1) (strcmp(s1, inst) == 0) + +#define getnum (getnum_aux(L, &pc)) +#define getname (getname_aux(buff, &pc)) + + +static int testC (lua_State *L) { + char buff[30]; + const char *pc = luaL_checkstring(L, 1); + for (;;) { + const char *inst = getname; + if EQ("") return 0; + else if EQ("isnumber") { + lua_pushintegral(L, lua_isnumber(L, getnum)); + } + else if EQ("isstring") { + lua_pushintegral(L, lua_isstring(L, getnum)); + } + else if EQ("istable") { + lua_pushintegral(L, lua_istable(L, getnum)); + } + else if EQ("iscfunction") { + lua_pushintegral(L, lua_iscfunction(L, getnum)); + } + else if EQ("isfunction") { + lua_pushintegral(L, lua_isfunction(L, getnum)); + } + else if EQ("isuserdata") { + lua_pushintegral(L, lua_isuserdata(L, getnum)); + } + else if EQ("isudataval") { + lua_pushintegral(L, lua_islightuserdata(L, getnum)); + } + else if EQ("isnil") { + lua_pushintegral(L, lua_isnil(L, getnum)); + } + else if EQ("isnull") { + lua_pushintegral(L, lua_isnone(L, getnum)); + } + else if EQ("tonumber") { + lua_pushnumber(L, lua_tonumber(L, getnum)); + } + else if EQ("tostring") { + const char *s = lua_tostring(L, getnum); + lua_pushstring(L, s); + } + else if EQ("strlen") { + lua_pushintegral(L, lua_strlen(L, getnum)); + } + else if EQ("tocfunction") { + lua_pushcfunction(L, lua_tocfunction(L, getnum)); + } + else if EQ("return") { + return getnum; + } + else if EQ("gettop") { + lua_pushintegral(L, lua_gettop(L)); + } + else if EQ("settop") { + lua_settop(L, getnum); + } + else if EQ("pop") { + lua_pop(L, getnum); + } + else if EQ("pushnum") { + lua_pushintegral(L, getnum); + } + else if EQ("pushnil") { + lua_pushnil(L); + } + else if EQ("pushbool") { + lua_pushboolean(L, getnum); + } + else if EQ("tobool") { + lua_pushintegral(L, lua_toboolean(L, getnum)); + } + else if EQ("pushvalue") { + lua_pushvalue(L, getnum); + } + else if EQ("pushcclosure") { + lua_pushcclosure(L, testC, getnum); + } + else if EQ("pushupvalues") { + lua_pushupvalues(L); + } + else if EQ("remove") { + lua_remove(L, getnum); + } + else if EQ("insert") { + lua_insert(L, getnum); + } + else if EQ("replace") { + lua_replace(L, getnum); + } + else if EQ("gettable") { + lua_gettable(L, getnum); + } + else if EQ("settable") { + lua_settable(L, getnum); + } + else if EQ("next") { + lua_next(L, -2); + } + else if EQ("concat") { + lua_concat(L, getnum); + } + else if EQ("lessthan") { + int a = getnum; + lua_pushboolean(L, lua_lessthan(L, a, getnum)); + } + else if EQ("equal") { + int a = getnum; + lua_pushboolean(L, lua_equal(L, a, getnum)); + } + else if EQ("rawcall") { + int narg = getnum; + int nres = getnum; + lua_call(L, narg, nres); + } + else if EQ("call") { + int narg = getnum; + int nres = getnum; + lua_pcall(L, narg, nres, 0); + } + else if EQ("loadstring") { + size_t sl; + const char *s = luaL_checklstring(L, getnum, &sl); + luaL_loadbuffer(L, s, sl, s); + } + else if EQ("loadfile") { + luaL_loadfile(L, luaL_checkstring(L, getnum)); + } + else if EQ("setmetatable") { + lua_setmetatable(L, getnum); + } + else if EQ("getmetatable") { + if (lua_getmetatable(L, getnum) == 0) + lua_pushnil(L); + } + else if EQ("type") { + lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); + } + else if EQ("getn") { + int i = getnum; + lua_pushintegral(L, luaL_getn(L, i)); + } + else if EQ("setn") { + int i = getnum; + int n = cast(int, lua_tonumber(L, -1)); + luaL_setn(L, i, n); + lua_pop(L, 1); + } + else luaL_error(L, "unknown instruction %s", buff); + } + return 0; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** tests for yield inside hooks +** ======================================================= +*/ + +static void yieldf (lua_State *L, lua_Debug *ar) { + lua_yield(L, 0); +} + +static int setyhook (lua_State *L) { + if (lua_isnoneornil(L, 1)) + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + else { + const char *smask = luaL_checkstring(L, 1); + int count = luaL_optint(L, 2, 0); + int mask = 0; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + lua_sethook(L, yieldf, mask, count); + } + return 0; +} + + +static int coresume (lua_State *L) { + int status; + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + status = lua_resume(co, 0); + if (status != 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + return 1; + } +} + +/* }====================================================== */ + + + +static const struct luaL_reg tests_funcs[] = { + {"hash", hash_query}, + {"limits", get_limits}, + {"listcode", listcode}, + {"listk", listk}, + {"listlocals", listlocals}, + {"loadlib", loadlib}, + {"stacklevel", stacklevel}, + {"querystr", string_query}, + {"querytab", table_query}, + {"doit", test_do}, + {"testC", testC}, + {"ref", tref}, + {"getref", getref}, + {"unref", unref}, + {"d2s", d2s}, + {"s2d", s2d}, + {"metatable", metatable}, + {"upvalue", upvalue}, + {"newuserdata", newuserdata}, + {"pushuserdata", pushuserdata}, + {"udataval", udataval}, + {"doonnewstack", doonnewstack}, + {"newstate", newstate}, + {"closestate", closestate}, + {"doremote", doremote}, + {"log2", log2_aux}, + {"int2fb", int2fb_aux}, + {"totalmem", mem_query}, + {"resume", coresume}, + {"setyhook", setyhook}, + {NULL, NULL} +}; + + +static void fim (void) { + if (!islocked) + lua_close(lua_state); + lua_assert(memdebug_numblocks == 0); + lua_assert(memdebug_total == 0); +} + + +static int l_panic (lua_State *L) { + UNUSED(L); + fprintf(stderr, "unable to recover; exiting\n"); + return 0; +} + + +int luaB_opentests (lua_State *L) { + lua_atpanic(L, l_panic); + lua_userstateopen(L); /* init lock */ + lua_state = L; /* keep first state to be opened */ + luaL_openlib(L, "T", tests_funcs, 0); + atexit(fim); + return 0; +} + + +#undef main +int main (int argc, char *argv[]) { + char *limit = getenv("MEMLIMIT"); + if (limit) + memdebug_memlimit = strtoul(limit, NULL, 10); + l_main(argc, argv); + return 0; +} + +#endif diff --git a/build/premake/src/Src/Lua/ltm.c b/build/premake/src/Src/Lua/ltm.c new file mode 100644 index 0000000000..1b3e515e57 --- /dev/null +++ b/build/premake/src/Src/Lua/ltm.c @@ -0,0 +1,70 @@ +/* +** $Id: ltm.c,v 1.106 2003/04/03 13:35:34 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltm_c + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", + "__pow", "__unm", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { + const TObject *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast(lu_byte, 1u<tmname[event]; + switch (ttype(o)) { + case LUA_TTABLE: + return luaH_getstr(hvalue(o)->metatable, ename); + case LUA_TUSERDATA: + return luaH_getstr(uvalue(o)->uv.metatable, ename); + default: + return &luaO_nilobject; + } +} + diff --git a/build/premake/src/Src/Lua/ltm.h b/build/premake/src/Src/Lua/ltm.h new file mode 100644 index 0000000000..8eebfd3dc3 --- /dev/null +++ b/build/premake/src/Src/Lua/ltm.h @@ -0,0 +1,51 @@ +/* +** $Id: ltm.h,v 1.41 2002/11/14 11:51:50 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_POW, + TM_UNM, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) \ + (((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + + +const TObject *luaT_gettm (Table *events, TMS event, TString *ename); +const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event); +void luaT_init (lua_State *L); + +extern const char *const luaT_typenames[]; + +#endif diff --git a/build/premake/src/Src/Lua/lua.h b/build/premake/src/Src/Lua/lua.h new file mode 100644 index 0000000000..88b0191e9a --- /dev/null +++ b/build/premake/src/Src/Lua/lua.h @@ -0,0 +1,391 @@ +/* +** $Id: lua.h,v 1.175b 2003/03/18 12:31:39 roberto Exp $ +** Lua - An Extensible Extension Language +** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil +** http://www.lua.org mailto:info@lua.org +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#define LUA_VERSION "Lua 5.0.2" +#define LUA_COPYRIGHT "Copyright (C) 1994-2004 Tecgraf, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_GLOBALSINDEX (-10001) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* error codes for `lua_load' and `lua_pcall' */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Chunkwriter) (lua_State *L, const void* p, + size_t sz, void* ud); + + +/* +** 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 + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#ifdef LUA_USER_H +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +#ifndef LUA_NUMBER +typedef double lua_Number; +#else +typedef LUA_NUMBER lua_Number; +#endif + + +/* mark for all API functions */ +#ifndef LUA_API +#define LUA_API extern +#endif + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (void); +LUA_API void lua_close (lua_State *L); +LUA_API lua_State *lua_newthread (lua_State *L); + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int idx); +LUA_API void lua_pushvalue (lua_State *L, int idx); +LUA_API void lua_remove (lua_State *L, int idx); +LUA_API void lua_insert (lua_State *L, int idx); +LUA_API void lua_replace (lua_State *L, int idx); +LUA_API int lua_checkstack (lua_State *L, int sz); + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_isnumber (lua_State *L, int idx); +LUA_API int lua_isstring (lua_State *L, int idx); +LUA_API int lua_iscfunction (lua_State *L, int idx); +LUA_API int lua_isuserdata (lua_State *L, int idx); +LUA_API int lua_type (lua_State *L, int idx); +LUA_API const char *lua_typename (lua_State *L, int tp); + +LUA_API int lua_equal (lua_State *L, int idx1, int idx2); +LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2); +LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx); +LUA_API int lua_toboolean (lua_State *L, int idx); +LUA_API const char *lua_tostring (lua_State *L, int idx); +LUA_API size_t lua_strlen (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); + + +/* +** 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_pushlstring (lua_State *L, const char *s, size_t l); +LUA_API void 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); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_gettable (lua_State *L, int idx); +LUA_API void lua_rawget (lua_State *L, int idx); +LUA_API void lua_rawgeti (lua_State *L, int idx, int n); +LUA_API void lua_newtable (lua_State *L); +LUA_API void *lua_newuserdata (lua_State *L, size_t sz); +LUA_API int lua_getmetatable (lua_State *L, int objindex); +LUA_API void lua_getfenv (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_settable (lua_State *L, int idx); +LUA_API void lua_rawset (lua_State *L, int idx); +LUA_API void lua_rawseti (lua_State *L, int idx, int n); +LUA_API int lua_setmetatable (lua_State *L, int objindex); +LUA_API int lua_setfenv (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void lua_call (lua_State *L, int nargs, int nresults); +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt, + const char *chunkname); + +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int lua_yield (lua_State *L, int nresults); +LUA_API int lua_resume (lua_State *L, int narg); + +/* +** garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ + +LUA_API const char *lua_version (void); + +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); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_boxpointer(L,u) \ + (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) + +#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i))) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) \ + (lua_pushstring(L, n), \ + lua_pushcfunction(L, f), \ + lua_settable(L, LUA_GLOBALSINDEX)) + +#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_isnone(L,n) (lua_type(L,n) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L,n) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + + + +/* +** compatibility macros and functions +*/ + + +LUA_API int lua_pushupvalues (lua_State *L); + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +#define lua_setglobal(L,s) \ + (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX)) + +#define lua_getglobal(L,s) \ + (lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX)) + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, ref) + + + +/* +** {====================================================================== +** useful definitions for Lua kernel and libraries +** ======================================================================= +*/ + +/* formats for Lua numbers */ +#ifndef LUA_NUMBER_SCAN +#define LUA_NUMBER_SCAN "%lf" +#endif + +#ifndef LUA_NUMBER_FMT +#define LUA_NUMBER_FMT "%.14g" +#endif + +/* }====================================================================== */ + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 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 */ + +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 int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2004 Tecgraf, PUC-Rio. All rights reserved. +* +* 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/build/premake/src/Src/Lua/luadebug.h b/build/premake/src/Src/Lua/luadebug.h new file mode 100644 index 0000000000..a244e72438 --- /dev/null +++ b/build/premake/src/Src/Lua/luadebug.h @@ -0,0 +1,46 @@ +/* +** $Id: luadebug.h,v 1.1 2003/01/24 16:26:17 jason379 Exp $ +** Debugging API +** See Copyright Notice in lua.h +*/ + + +#ifndef luadebug_h +#define luadebug_h + + +#include "lua.h" + +typedef struct lua_Debug lua_Debug; /* activation record */ +typedef struct lua_Localvar lua_Localvar; + +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 lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); +LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + const char *event; /* `call', `return' */ + int currentline; /* (l) */ + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `tag method', `local', `field' */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ + const char *source; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct lua_TObject *_func; /* active function */ +}; + + +#endif diff --git a/build/premake/src/Src/Lua/lualib.h b/build/premake/src/Src/Lua/lualib.h new file mode 100644 index 0000000000..e22c4c3063 --- /dev/null +++ b/build/premake/src/Src/Lua/lualib.h @@ -0,0 +1,56 @@ +/* +** $Id: lualib.h,v 1.28 2003/03/18 12:24:26 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int luaopen_base (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int luaopen_table (lua_State *L); + +#define LUA_IOLIBNAME "io" +#define LUA_OSLIBNAME "os" +LUALIB_API int luaopen_io (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int luaopen_string (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int luaopen_math (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int luaopen_debug (lua_State *L); + + +LUALIB_API int luaopen_loadlib (lua_State *L); + + +/* to help testing the libraries */ +#ifndef lua_assert +#define lua_assert(c) /* empty */ +#endif + + +/* compatibility code */ +#define lua_baselibopen luaopen_base +#define lua_tablibopen luaopen_table +#define lua_iolibopen luaopen_io +#define lua_strlibopen luaopen_string +#define lua_mathlibopen luaopen_math +#define lua_dblibopen luaopen_debug + +#endif diff --git a/build/premake/src/Src/Lua/lundump.c b/build/premake/src/Src/Lua/lundump.c new file mode 100644 index 0000000000..151a8507cc --- /dev/null +++ b/build/premake/src/Src/Lua/lundump.c @@ -0,0 +1,286 @@ +/* +** $Id: lundump.c,v 1.49 2003/04/07 20:34:20 lhf Exp $ +** load pre-compiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define lundump_c + +#include "lua.h" + +#include "ldebug.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +#define LoadByte (lu_byte) ezgetc + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + int swap; + const char* name; +} LoadState; + +static void unexpectedEOZ (LoadState* S) +{ + luaG_runerror(S->L,"unexpected end of file in %s",S->name); +} + +static int ezgetc (LoadState* S) +{ + int c=zgetc(S->Z); + if (c==EOZ) unexpectedEOZ(S); + return c; +} + +static void ezread (LoadState* S, void* b, int n) +{ + int r=luaZ_read(S->Z,b,n); + if (r!=0) unexpectedEOZ(S); +} + +static void LoadBlock (LoadState* S, void* b, size_t size) +{ + if (S->swap) + { + char* p=(char*) b+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(S); + } + else + ezread(S,b,size); +} + +static void LoadVector (LoadState* S, void* b, int m, size_t size) +{ + if (S->swap) + { + char* q=(char*) b; + while (m--) + { + char* p=q+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(S); + q+=size; + } + } + else + ezread(S,b,m*size); +} + +static int LoadInt (LoadState* S) +{ + int x; + LoadBlock(S,&x,sizeof(x)); + if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name); + return x; +} + +static size_t LoadSize (LoadState* S) +{ + size_t x; + LoadBlock(S,&x,sizeof(x)); + return x; +} + +static lua_Number LoadNumber (LoadState* S) +{ + lua_Number x; + LoadBlock(S,&x,sizeof(x)); + return x; +} + +static TString* LoadString (LoadState* S) +{ + size_t size=LoadSize(S); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + ezread(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode (LoadState* S, Proto* f) +{ + int size=LoadInt(S); + f->code=luaM_newvector(S->L,size,Instruction); + f->sizecode=size; + LoadVector(S,f->code,size,sizeof(*f->code)); +} + +static void LoadLocals (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } +} + +static void LoadLines (LoadState* S, Proto* f) +{ + int size=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,size,int); + f->sizelineinfo=size; + LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo)); +} + +static void LoadUpvalues (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + if (n!=0 && n!=f->nups) + luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d", + S->name,n,f->nups); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; iupvalues[i]=LoadString(S); +} + +static Proto* LoadFunction (LoadState* S, TString* p); + +static void LoadConstants (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TObject); + f->sizek=n; + for (i=0; ik[i]; + int t=LoadByte(S); + switch (t) + { + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(o,LoadString(S)); + break; + case LUA_TNIL: + setnilvalue(o); + break; + default: + luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=LoadFunction(S,f->source); +} + +static Proto* LoadFunction (LoadState* S, TString* p) +{ + Proto* f=luaF_newproto(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->lineDefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadLines(S,f); + LoadLocals(S,f); + LoadUpvalues(S,f); + LoadConstants(S,f); + LoadCode(S,f); +#ifndef TRUST_BINARIES + if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name); +#endif + return f; +} + +static void LoadSignature (LoadState* S) +{ + const char* s=LUA_SIGNATURE; + while (*s!=0 && ezgetc(S)==*s) + ++s; + if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name); +} + +static void TestSize (LoadState* S, int s, const char* what) +{ + int r=LoadByte(S); + if (r!=s) + luaG_runerror(S->L,"virtual machine mismatch in %s: " + "size of %s is %d but read %d",S->name,what,s,r); +} + +#define TESTSIZE(s,w) TestSize(S,s,w) +#define V(v) v/16,v%16 + +static void LoadHeader (LoadState* S) +{ + int version; + lua_Number x,tx=TEST_NUMBER; + LoadSignature(S); + version=LoadByte(S); + if (version>VERSION) + luaG_runerror(S->L,"%s too new: " + "read version %d.%d; expected at most %d.%d", + S->name,V(version),V(VERSION)); + if (versionL,"%s too old: " + "read version %d.%d; expected at least %d.%d", + S->name,V(version),V(VERSION0)); + S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */ + TESTSIZE(sizeof(int),"int"); + TESTSIZE(sizeof(size_t), "size_t"); + TESTSIZE(sizeof(Instruction), "Instruction"); + TESTSIZE(SIZE_OP, "OP"); + TESTSIZE(SIZE_A, "A"); + TESTSIZE(SIZE_B, "B"); + TESTSIZE(SIZE_C, "C"); + TESTSIZE(sizeof(lua_Number), "number"); + x=LoadNumber(S); + if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */ + luaG_runerror(S->L,"unknown number format in %s",S->name); +} + +static Proto* LoadChunk (LoadState* S) +{ + LoadHeader(S); + return LoadFunction(S,NULL); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff) +{ + LoadState S; + const char* s=zname(Z); + if (*s=='@' || *s=='=') + S.name=s+1; + else if (*s==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=s; + S.L=L; + S.Z=Z; + S.b=buff; + return LoadChunk(&S); +} + +/* +** find byte order +*/ +int luaU_endianness (void) +{ + int x=1; + return *(char*)&x; +} diff --git a/build/premake/src/Src/Lua/lundump.h b/build/premake/src/Src/Lua/lundump.h new file mode 100644 index 0000000000..c7e6959b30 --- /dev/null +++ b/build/premake/src/Src/Lua/lundump.h @@ -0,0 +1,34 @@ +/* +** $Id: lundump.h,v 1.30 2003/04/07 20:34:20 lhf Exp $ +** load pre-compiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff); + +/* find byte order; from lundump.c */ +int luaU_endianness (void); + +/* dump one chunk; from ldump.c */ +void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data); + +/* print one chunk; from print.c */ +void luaU_print (const Proto* Main); + +/* definitions for headers of binary files */ +#define LUA_SIGNATURE "\033Lua" /* binary files start with "Lua" */ +#define VERSION 0x50 /* last format change was in 5.0 */ +#define VERSION0 0x50 /* last major change was in 5.0 */ + +/* a multiple of PI for testing native format */ +/* multiplying by 1E7 gives non-trivial integer values */ +#define TEST_NUMBER ((lua_Number)3.14159265358979323846E7) + +#endif diff --git a/build/premake/src/Src/Lua/lvm.c b/build/premake/src/Src/Lua/lvm.c new file mode 100644 index 0000000000..94e2802d86 --- /dev/null +++ b/build/premake/src/Src/Lua/lvm.c @@ -0,0 +1,781 @@ +/* +** $Id: lvm.c,v 1.284b 2003/04/03 13:35:34 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +/* needed only when `lua_number2str' uses `sprintf' */ +#include + +#define lvm_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* function to convert a lua_Number to a string */ +#ifndef lua_number2str +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#endif + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TObject *luaV_tonumber (const TObject *obj, TObject *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ + lua_number2str(s, nvalue(obj)); + setsvalue2s(obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L) { + lu_byte mask = L->hookmask; + if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */ + if (L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + return; + } + } + if (mask & LUA_MASKLINE) { + CallInfo *ci = L->ci; + Proto *p = ci_func(ci)->l.p; + int newline = getline(p, pcRel(*ci->u.l.pc, p)); + if (!L->hookinit) { + luaG_inithooks(L); + return; + } + lua_assert(ci->state & CI_HASFRAME); + if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ + ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ + /* calls linehook when enters a new line or jumps back (loop) */ + if (*ci->u.l.pc <= ci->u.l.savedpc || + newline != getline(p, pcRel(ci->u.l.savedpc, p))) { + luaD_callhook(L, LUA_HOOKLINE, newline); + ci = L->ci; /* previous call may reallocate `ci' */ + } + ci->u.l.savedpc = *ci->u.l.pc; + } +} + + +static void callTMres (lua_State *L, const TObject *f, + const TObject *p1, const TObject *p2) { + setobj2s(L->top, f); /* push function */ + setobj2s(L->top+1, p1); /* 1st argument */ + setobj2s(L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */ + L->top += 3; + luaD_call(L, L->top - 3, 1); + L->top--; /* result will be in L->top */ +} + + + +static void callTM (lua_State *L, const TObject *f, + const TObject *p1, const TObject *p2, const TObject *p3) { + setobj2s(L->top, f); /* push function */ + setobj2s(L->top+1, p1); /* 1st argument */ + setobj2s(L->top+2, p2); /* 2nd argument */ + setobj2s(L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */ + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +static const TObject *luaV_index (lua_State *L, const TObject *t, + TObject *key, int loop) { + const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); + if (tm == NULL) return &luaO_nilobject; /* no TM */ + if (ttisfunction(tm)) { + callTMres(L, tm, t, key); + return L->top; + } + else return luaV_gettable(L, tm, key, loop); +} + +static const TObject *luaV_getnotable (lua_State *L, const TObject *t, + TObject *key, int loop) { + const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, tm, t, key); + return L->top; + } + else return luaV_gettable(L, tm, key, loop); +} + + +/* +** Function to index a table. +** Receives the table at `t' and the key at `key'. +** leaves the result at `res'. +*/ +const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key, + int loop) { + if (loop > MAXTAGLOOP) + luaG_runerror(L, "loop in gettable"); + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TObject *v = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(v)) return v; + else return luaV_index(L, t, key, loop+1); + } + else return luaV_getnotable(L, t, key, loop+1); +} + + +/* +** Receives table at `t', key at `key' and value at `val'. +*/ +void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) { + const TObject *tm; + int loop = 0; + do { + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(oldval, val); /* write barrier */ + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + t = tm; /* else repeat with `tm' */ + } while (++loop <= MAXTAGLOOP); + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, + StkId res, TMS event) { + ptrdiff_t result = savestack(L, res); + const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (!ttisfunction(tm)) return 0; + callTMres(L, tm, p1, p2); + res = restorestack(L, result); /* previous call may change stack */ + setobjs2s(res, L->top); + return 1; +} + + +static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TObject *tm1 = fasttm(L, mt1, event); + const TObject *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2, + TMS event) { + const TObject *tm1 = luaT_gettmbyobj(L, p1, event); + const TObject *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int luaV_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return nvalue(l) < nvalue(r); + else if (ttisstring(l)) + return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return nvalue(l) <= nvalue(r); + else if (ttisstring(l)) + return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) { + const TObject *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return nvalue(t1) == nvalue(t2); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!tostring(L, top-2) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */ + /* at least two string values; get as many as possible */ + lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) + + cast(lu_mem, tsvalue(top-2)->tsv.len); + char *buffer; + int i; + while (n < total && tostring(L, top-n-1)) { /* collect total length */ + tl += tsvalue(top-n-1)->tsv.len; + n++; + } + if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow"); + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->tsv.len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, + const TObject *rb, const TObject *rc, TMS op) { + TObject tempb, tempc; + const TObject *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + switch (op) { + case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; + case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; + case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; + case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; + case TM_POW: { + const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]); + ptrdiff_t res = savestack(L, ra); + if (!ttisfunction(f)) + luaG_runerror(L, "`__pow' (`^' operator) is not a function"); + callTMres(L, f, b, c); + ra = restorestack(L, res); /* previous call may change stack */ + setobjs2s(ra, L->top); + break; + } + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) return 0; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define XRA(i) (L->base+GETARG_A(i)) +#define RB(i) (base+GETARG_B(i)) +#define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK) +#define RC(i) (base+GETARG_C(i)) +#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK) +#define KBx(i) (k+GETARG_Bx(i)) + + +#define dojump(pc, i) ((pc) += (i)) + + +StkId luaV_execute (lua_State *L) { + LClosure *cl; + TObject *k; + const Instruction *pc; + callentry: /* entry point when calling new functions */ + if (L->hookmask & LUA_MASKCALL) { + L->ci->u.l.pc = &pc; + luaD_callhook(L, LUA_HOOKCALL, -1); + } + retentry: /* entry point when returning to old functions */ + L->ci->u.l.pc = &pc; + lua_assert(L->ci->state == CI_SAVEDPC || + L->ci->state == (CI_SAVEDPC | CI_CALLING)); + L->ci->state = CI_HASFRAME; /* activate frame */ + pc = L->ci->u.l.savedpc; + cl = &clvalue(L->base - 1)->l; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId base, ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L); + if (L->ci->state & CI_YIELD) { /* did hook yield? */ + L->ci->u.l.savedpc = pc - 1; + L->ci->state = CI_YIELD | CI_SAVEDPC; + return NULL; + } + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + base = L->base; + ra = RA(i); + lua_assert(L->ci->state & CI_HASFRAME); + lua_assert(base == L->ci->base); + lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); + lua_assert(L->top == L->ci->top || + GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(ra, RB(i)); + break; + } + case OP_LOADK: { + setobj2s(ra, KBx(i)); + break; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + break; + } + case OP_LOADNIL: { + TObject *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + break; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(ra, cl->upvals[b]->v); + break; + } + case OP_GETGLOBAL: { + TObject *rb = KBx(i); + const TObject *v; + lua_assert(ttisstring(rb) && ttistable(&cl->g)); + v = luaH_getstr(hvalue(&cl->g), tsvalue(rb)); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0)); + break; + } + case OP_GETTABLE: { + StkId rb = RB(i); + TObject *rc = RKC(i); + if (ttistable(rb)) { + const TObject *v = luaH_get(hvalue(rb), rc); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); + } + else + setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); + break; + } + case OP_SETGLOBAL: { + lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); + luaV_settable(L, &cl->g, KBx(i), ra); + break; + } + case OP_SETUPVAL: { + int b = GETARG_B(i); + setobj(cl->upvals[b]->v, ra); /* write barrier */ + break; + } + case OP_SETTABLE: { + luaV_settable(L, ra, RKB(i), RKC(i)); + break; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + b = fb2int(b); + sethvalue(ra, luaH_new(L, b, GETARG_C(i))); + luaC_checkGC(L); + break; + } + case OP_SELF: { + StkId rb = RB(i); + TObject *rc = RKC(i); + runtime_check(L, ttisstring(rc)); + setobjs2s(ra+1, rb); + if (ttistable(rb)) { + const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc)); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); + } + else + setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); + break; + } + case OP_ADD: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) + nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_ADD); + break; + } + case OP_SUB: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) - nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_SUB); + break; + } + case OP_MUL: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) * nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_MUL); + break; + } + case OP_DIV: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) / nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_DIV); + break; + } + case OP_POW: { + Arith(L, ra, RKB(i), RKC(i), TM_POW); + break; + } + case OP_UNM: { + const TObject *rb = RB(i); + TObject temp; + if (tonumber(rb, &temp)) { + setnvalue(ra, -nvalue(rb)); + } + else { + setnilvalue(&temp); + if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) + luaG_aritherror(L, RB(i), &temp); + } + break; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + break; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ + base = L->base; + setobjs2s(RA(i), base+b); + luaC_checkGC(L); + break; + } + case OP_JMP: { + dojump(pc, GETARG_sBx(i)); + break; + } + case OP_EQ: { + if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_LT: { + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_LE: { + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_TEST: { + TObject *rb = RB(i); + if (l_isfalse(rb) == GETARG_C(i)) pc++; + else { + setobjs2s(ra, rb); + dojump(pc, GETARG_sBx(*pc) + 1); + } + break; + } + case OP_CALL: + case OP_TAILCALL: { + StkId firstResult; + int b = GETARG_B(i); + int nresults; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + nresults = GETARG_C(i) - 1; + firstResult = luaD_precall(L, ra); + if (firstResult) { + if (firstResult > L->top) { /* yield? */ + lua_assert(L->ci->state == (CI_C | CI_YIELD)); + (L->ci - 1)->u.l.savedpc = pc; + (L->ci - 1)->state = CI_SAVEDPC; + return NULL; + } + /* it was a C function (`precall' called it); adjust results */ + luaD_poscall(L, nresults, firstResult); + if (nresults >= 0) L->top = L->ci->top; + } + else { /* it is a Lua function */ + if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ + (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ + (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); + } + else { /* tail call: put new frame in place of previous one */ + int aux; + base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ + ra = RA(i); + if (L->openupval) luaF_close(L, base); + for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ + setobjs2s(base+aux-1, ra+aux); + (L->ci - 1)->top = L->top = base+aux; /* correct top */ + lua_assert(L->ci->state & CI_SAVEDPC); + (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; + (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ + (L->ci - 1)->state = CI_SAVEDPC; + L->ci--; /* remove new frame */ + L->base = L->ci->base; + } + goto callentry; + } + break; + } + case OP_RETURN: { + CallInfo *ci = L->ci - 1; /* previous function frame */ + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + lua_assert(L->ci->state & CI_HASFRAME); + if (L->openupval) luaF_close(L, base); + L->ci->state = CI_SAVEDPC; /* deactivate current function */ + L->ci->u.l.savedpc = pc; + /* previous function was running `here'? */ + if (!(ci->state & CI_CALLING)) { + lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc); + return ra; /* no: return */ + } + else { /* yes: continue its execution */ + int nresults; + lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC)); + lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); + nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; + luaD_poscall(L, nresults, ra); + if (nresults >= 0) L->top = L->ci->top; + goto retentry; + } + } + case OP_FORLOOP: { + lua_Number step, idx, limit; + const TObject *plimit = ra+1; + const TObject *pstep = ra+2; + if (!ttisnumber(ra)) + luaG_runerror(L, "`for' initial value must be a number"); + if (!tonumber(plimit, ra+1)) + luaG_runerror(L, "`for' limit must be a number"); + if (!tonumber(pstep, ra+2)) + luaG_runerror(L, "`for' step must be a number"); + step = nvalue(pstep); + idx = nvalue(ra) + step; /* increment index */ + limit = nvalue(plimit); + if (step > 0 ? idx <= limit : idx >= limit) { + dojump(pc, GETARG_sBx(i)); /* jump back */ + chgnvalue(ra, idx); /* update index */ + } + break; + } + case OP_TFORLOOP: { + int nvar = GETARG_C(i) + 1; + StkId cb = ra + nvar + 2; /* call base */ + setobjs2s(cb, ra); + setobjs2s(cb+1, ra+1); + setobjs2s(cb+2, ra+2); + L->top = cb+3; /* func. + 2 args (state and index) */ + luaD_call(L, cb, nvar); + L->top = L->ci->top; + ra = XRA(i) + 2; /* final position of first result */ + cb = ra + nvar; + do { /* move results to proper positions */ + nvar--; + setobjs2s(ra+nvar, cb+nvar); + } while (nvar > 0); + if (ttisnil(ra)) /* break loop? */ + pc++; /* skip jump (break loop) */ + else + dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ + break; + } + case OP_TFORPREP: { /* for compatibility only */ + if (ttistable(ra)) { + setobjs2s(ra+1, ra); + setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next"))); + } + dojump(pc, GETARG_sBx(i)); + break; + } + case OP_SETLIST: + case OP_SETLISTO: { + int bc; + int n; + Table *h; + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + bc = GETARG_Bx(i); + if (GET_OPCODE(i) == OP_SETLIST) + n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; + else { + n = L->top - ra - 1; + L->top = L->ci->top; + } + bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ + for (; n > 0; n--) + setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */ + break; + } + case OP_CLOSE: { + luaF_close(L, ra); + break; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, &cl->g); + ncl->l.p = p; + for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(ra, ncl); + luaC_checkGC(L); + break; + } + } + } +} + + diff --git a/build/premake/src/Src/Lua/lvm.h b/build/premake/src/Src/Lua/lvm.h new file mode 100644 index 0000000000..19cce200b6 --- /dev/null +++ b/build/premake/src/Src/Lua/lvm.h @@ -0,0 +1,35 @@ +/* +** $Id: lvm.h,v 1.47 2002/11/14 16:16:21 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); +int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); +const TObject *luaV_tonumber (const TObject *obj, TObject *n); +int luaV_tostring (lua_State *L, StkId obj); +const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key, + int loop); +void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val); +StkId luaV_execute (lua_State *L); +void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/build/premake/src/Src/Lua/lzio.c b/build/premake/src/Src/Lua/lzio.c new file mode 100644 index 0000000000..3aeca1c588 --- /dev/null +++ b/build/premake/src/Src/Lua/lzio.c @@ -0,0 +1,81 @@ +/* +** $Id: lzio.c,v 1.24 2003/03/20 16:00:56 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + const char *buff = z->reader(NULL, z->data, &size); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + int c = luaZ_fill(z); + if (c == EOZ) return c; + z->n++; + z->p--; + } + return char2int(*z->p); +} + + +void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) { + z->reader = reader; + z->data = data; + z->name = name; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return n; /* return number of missing bytes */ + else { + ++z->n; /* filbuf removed first byte; put back it */ + --z->p; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char); + buff->buffsize = n; + } + return buff->buffer; +} + + diff --git a/build/premake/src/Src/Lua/lzio.h b/build/premake/src/Src/Lua/lzio.h new file mode 100644 index 0000000000..5e73615cc0 --- /dev/null +++ b/build/premake/src/Src/Lua/lzio.h @@ -0,0 +1,64 @@ +/* +** $Id: lzio.h,v 1.15 2003/03/20 16:00:56 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +#define zname(z) ((z)->name) + +void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name); +size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +int luaZ_lookahead (ZIO *z); + + + +typedef struct Mbuffer { + char *buffer; + size_t buffsize; +} Mbuffer; + + +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_buffer(buff) ((buff)->buffer) + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Chunkreader reader; + void* data; /* additional data */ + const char *name; +}; + + +int luaZ_fill (ZIO *z); + +#endif diff --git a/build/premake/src/Src/Makefile b/build/premake/src/Src/Makefile new file mode 100644 index 0000000000..52156f24af --- /dev/null +++ b/build/premake/src/Src/Makefile @@ -0,0 +1,375 @@ +# C Console Executable Makefile autogenerated by premake +# Don't edit this file! Instead edit `premake.lua` then rerun `make` + +ifndef CONFIG + CONFIG=Debug +endif + +ifeq ($(CONFIG),Debug) + BINDIR := ../bin + LIBDIR := .. + OBJDIR := obj/Debug + OUTDIR := ../bin + CPPFLAGS := -MD -D "_CRT_SECURE_NO_DEPRECATE" + CFLAGS += $(CPPFLAGS) -g + CXXFLAGS := $(CFLAGS) + LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -lm + LDDEPS := + TARGET := premake +endif + +ifeq ($(CONFIG),Release) + BINDIR := ../bin + LIBDIR := .. + OBJDIR := obj/Release + OUTDIR := ../bin + CPPFLAGS := -MD -D "_CRT_SECURE_NO_DEPRECATE" + CFLAGS += $(CPPFLAGS) -Os + CXXFLAGS := $(CFLAGS) + LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s -lm + LDDEPS := + TARGET := premake +endif + +OBJECTS := \ + $(OBJDIR)/sharpdev.o \ + $(OBJDIR)/vs2005.o \ + $(OBJDIR)/io.o \ + $(OBJDIR)/sharpdev_cs.o \ + $(OBJDIR)/script.o \ + $(OBJDIR)/platform_posix.o \ + $(OBJDIR)/arg.o \ + $(OBJDIR)/vs6_cpp.o \ + $(OBJDIR)/util.o \ + $(OBJDIR)/vs6.o \ + $(OBJDIR)/gnu_helpers.o \ + $(OBJDIR)/os.o \ + $(OBJDIR)/vs2005_cs.o \ + $(OBJDIR)/gnu.o \ + $(OBJDIR)/gnu_cpp.o \ + $(OBJDIR)/gnu_cs.o \ + $(OBJDIR)/platform_windows.o \ + $(OBJDIR)/project.o \ + $(OBJDIR)/vs2002_cs.o \ + $(OBJDIR)/clean.o \ + $(OBJDIR)/premake.o \ + $(OBJDIR)/vs.o \ + $(OBJDIR)/path.o \ + $(OBJDIR)/vs2002.o \ + $(OBJDIR)/lauxlib.o \ + $(OBJDIR)/ldebug.o \ + $(OBJDIR)/ltablib.o \ + $(OBJDIR)/liolib.o \ + $(OBJDIR)/lstrlib.o \ + $(OBJDIR)/ldo.o \ + $(OBJDIR)/ltests.o \ + $(OBJDIR)/ldump.o \ + $(OBJDIR)/lundump.o \ + $(OBJDIR)/ldblib.o \ + $(OBJDIR)/lmem.o \ + $(OBJDIR)/lmathlib.o \ + $(OBJDIR)/lstate.o \ + $(OBJDIR)/ltm.o \ + $(OBJDIR)/lvm.o \ + $(OBJDIR)/ltable.o \ + $(OBJDIR)/llex.o \ + $(OBJDIR)/lgc.o \ + $(OBJDIR)/loadlib.o \ + $(OBJDIR)/lfunc.o \ + $(OBJDIR)/lparser.o \ + $(OBJDIR)/lopcodes.o \ + $(OBJDIR)/lbaselib.o \ + $(OBJDIR)/lzio.o \ + $(OBJDIR)/lobject.o \ + $(OBJDIR)/lstring.o \ + $(OBJDIR)/lapi.o \ + $(OBJDIR)/lcode.o \ + +CMD := $(subst \,\\,$(ComSpec)$(COMSPEC)) +ifeq (,$(CMD)) + CMD_MKBINDIR := mkdir -p $(BINDIR) + CMD_MKLIBDIR := mkdir -p $(LIBDIR) + CMD_MKOUTDIR := mkdir -p $(OUTDIR) + CMD_MKOBJDIR := mkdir -p $(OBJDIR) +else + CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR)) + CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR)) + CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR)) + CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR)) +endif + +.PHONY: clean + +$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES) + @echo Linking Premake + -@$(CMD_MKBINDIR) + -@$(CMD_MKLIBDIR) + -@$(CMD_MKOUTDIR) + @$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(RESOURCES) + +clean: + @echo Cleaning Premake + -@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) + +$(OBJDIR)/sharpdev.o: sharpdev.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs2005.o: vs2005.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/io.o: io.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/sharpdev_cs.o: sharpdev_cs.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/script.o: script.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/platform_posix.o: platform_posix.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/arg.o: arg.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs6_cpp.o: vs6_cpp.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/util.o: util.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs6.o: vs6.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/gnu_helpers.o: gnu_helpers.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/os.o: os.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs2005_cs.o: vs2005_cs.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/gnu.o: gnu.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/gnu_cpp.o: gnu_cpp.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/gnu_cs.o: gnu_cs.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/platform_windows.o: platform_windows.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/project.o: project.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs2002_cs.o: vs2002_cs.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/clean.o: clean.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/premake.o: premake.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs.o: vs.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/path.o: path.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/vs2002.o: vs2002.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lauxlib.o: Lua/lauxlib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ldebug.o: Lua/ldebug.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ltablib.o: Lua/ltablib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/liolib.o: Lua/liolib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lstrlib.o: Lua/lstrlib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ldo.o: Lua/ldo.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ltests.o: Lua/ltests.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ldump.o: Lua/ldump.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lundump.o: Lua/lundump.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ldblib.o: Lua/ldblib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lmem.o: Lua/lmem.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lmathlib.o: Lua/lmathlib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lstate.o: Lua/lstate.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ltm.o: Lua/ltm.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lvm.o: Lua/lvm.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/ltable.o: Lua/ltable.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/llex.o: Lua/llex.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lgc.o: Lua/lgc.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/loadlib.o: Lua/loadlib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lfunc.o: Lua/lfunc.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lparser.o: Lua/lparser.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lopcodes.o: Lua/lopcodes.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lbaselib.o: Lua/lbaselib.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lzio.o: Lua/lzio.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lobject.o: Lua/lobject.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lstring.o: Lua/lstring.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lapi.o: Lua/lapi.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +$(OBJDIR)/lcode.o: Lua/lcode.c + -@$(CMD_MKOBJDIR) + @echo $(notdir $<) + @$(CC) $(CFLAGS) -o $@ -c $< + +-include $(OBJECTS:%.o=%.d) + diff --git a/build/premake/src/Src/Premake.dsp b/build/premake/src/Src/Premake.dsp new file mode 100644 index 0000000000..63ecd65c84 --- /dev/null +++ b/build/premake/src/Src/Premake.dsp @@ -0,0 +1,449 @@ +# Microsoft Developer Studio Project File - Name="Premake" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Premake - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Premake.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Premake.mak" CFG="Premake - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Premake - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Premake - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Premake - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "../bin" +# PROP BASE Intermediate_Dir "obj/Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../bin" +# PROP Intermediate_Dir "obj/Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GR /GX /O1 /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GR /GX /O1 /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 m.lib /nologo /entry:"mainCRTStartup" /subsystem:console /machine:I386 /out:"../bin/premake" /libpath:".." +# ADD LINK32 m.lib /nologo /entry:"mainCRTStartup" /subsystem:console /machine:I386 /out:"../bin/premake" /libpath:".." + +!ELSEIF "$(CFG)" == "Premake - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "../bin" +# PROP BASE Intermediate_Dir "obj/Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../bin" +# PROP Intermediate_Dir "obj/Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 m.lib /nologo /entry:"mainCRTStartup" /subsystem:console /incremental:yes /debug /machine:I386 /out:"../bin/premake" /pdbtype:sept /libpath:".." +# ADD LINK32 m.lib /nologo /entry:"mainCRTStartup" /subsystem:console /incremental:yes /debug /machine:I386 /out:"../bin/premake" /pdbtype:sept /libpath:".." + +!ENDIF + +# Begin Target + +# Name "Premake - Win32 Release" +# Name "Premake - Win32 Debug" +# Begin Group "Lua" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=Lua/lauxlib.h +# End Source File +# Begin Source File + +SOURCE=Lua/ldebug.h +# End Source File +# Begin Source File + +SOURCE=Lua/lualib.h +# End Source File +# Begin Source File + +SOURCE=Lua/ldo.h +# End Source File +# Begin Source File + +SOURCE=Lua/lundump.h +# End Source File +# Begin Source File + +SOURCE=Lua/lmem.h +# End Source File +# Begin Source File + +SOURCE=Lua/lstate.h +# End Source File +# Begin Source File + +SOURCE=Lua/ltm.h +# End Source File +# Begin Source File + +SOURCE=Lua/lvm.h +# End Source File +# Begin Source File + +SOURCE=Lua/ltable.h +# End Source File +# Begin Source File + +SOURCE=Lua/llex.h +# End Source File +# Begin Source File + +SOURCE=Lua/lgc.h +# End Source File +# Begin Source File + +SOURCE=Lua/lfunc.h +# End Source File +# Begin Source File + +SOURCE=Lua/lopcodes.h +# End Source File +# Begin Source File + +SOURCE=Lua/lparser.h +# End Source File +# Begin Source File + +SOURCE=Lua/llimits.h +# End Source File +# Begin Source File + +SOURCE=Lua/lzio.h +# End Source File +# Begin Source File + +SOURCE=Lua/lua.h +# End Source File +# Begin Source File + +SOURCE=Lua/lobject.h +# End Source File +# Begin Source File + +SOURCE=Lua/lstring.h +# End Source File +# Begin Source File + +SOURCE=Lua/lapi.h +# End Source File +# Begin Source File + +SOURCE=Lua/lcode.h +# End Source File +# Begin Source File + +SOURCE=Lua/luadebug.h +# End Source File +# Begin Source File + +SOURCE=Lua/lauxlib.c +# End Source File +# Begin Source File + +SOURCE=Lua/ldebug.c +# End Source File +# Begin Source File + +SOURCE=Lua/ltablib.c +# End Source File +# Begin Source File + +SOURCE=Lua/liolib.c +# End Source File +# Begin Source File + +SOURCE=Lua/lstrlib.c +# End Source File +# Begin Source File + +SOURCE=Lua/ldo.c +# End Source File +# Begin Source File + +SOURCE=Lua/ltests.c +# End Source File +# Begin Source File + +SOURCE=Lua/ldump.c +# End Source File +# Begin Source File + +SOURCE=Lua/lundump.c +# End Source File +# Begin Source File + +SOURCE=Lua/ldblib.c +# End Source File +# Begin Source File + +SOURCE=Lua/lmem.c +# End Source File +# Begin Source File + +SOURCE=Lua/lmathlib.c +# End Source File +# Begin Source File + +SOURCE=Lua/lstate.c +# End Source File +# Begin Source File + +SOURCE=Lua/ltm.c +# End Source File +# Begin Source File + +SOURCE=Lua/lvm.c +# End Source File +# Begin Source File + +SOURCE=Lua/ltable.c +# End Source File +# Begin Source File + +SOURCE=Lua/llex.c +# End Source File +# Begin Source File + +SOURCE=Lua/lgc.c +# End Source File +# Begin Source File + +SOURCE=Lua/loadlib.c +# End Source File +# Begin Source File + +SOURCE=Lua/lfunc.c +# End Source File +# Begin Source File + +SOURCE=Lua/lparser.c +# End Source File +# Begin Source File + +SOURCE=Lua/lopcodes.c +# End Source File +# Begin Source File + +SOURCE=Lua/lbaselib.c +# End Source File +# Begin Source File + +SOURCE=Lua/lzio.c +# End Source File +# Begin Source File + +SOURCE=Lua/lobject.c +# End Source File +# Begin Source File + +SOURCE=Lua/lstring.c +# End Source File +# Begin Source File + +SOURCE=Lua/lapi.c +# End Source File +# Begin Source File + +SOURCE=Lua/lcode.c +# End Source File +# End Group +# Begin Source File + +SOURCE=path.h +# End Source File +# Begin Source File + +SOURCE=vs2002.h +# End Source File +# Begin Source File + +SOURCE=vs2005.h +# End Source File +# Begin Source File + +SOURCE=script.h +# End Source File +# Begin Source File + +SOURCE=io.h +# End Source File +# Begin Source File + +SOURCE=arg.h +# End Source File +# Begin Source File + +SOURCE=sharpdev.h +# End Source File +# Begin Source File + +SOURCE=util.h +# End Source File +# Begin Source File + +SOURCE=vs6.h +# End Source File +# Begin Source File + +SOURCE=os.h +# End Source File +# Begin Source File + +SOURCE=platform.h +# End Source File +# Begin Source File + +SOURCE=gnu.h +# End Source File +# Begin Source File + +SOURCE=project.h +# End Source File +# Begin Source File + +SOURCE=premake.h +# End Source File +# Begin Source File + +SOURCE=vs.h +# End Source File +# Begin Source File + +SOURCE=sharpdev.c +# End Source File +# Begin Source File + +SOURCE=vs2005.c +# End Source File +# Begin Source File + +SOURCE=io.c +# End Source File +# Begin Source File + +SOURCE=sharpdev_cs.c +# End Source File +# Begin Source File + +SOURCE=script.c +# End Source File +# Begin Source File + +SOURCE=platform_posix.c +# End Source File +# Begin Source File + +SOURCE=arg.c +# End Source File +# Begin Source File + +SOURCE=vs6_cpp.c +# End Source File +# Begin Source File + +SOURCE=util.c +# End Source File +# Begin Source File + +SOURCE=vs6.c +# End Source File +# Begin Source File + +SOURCE=gnu_helpers.c +# End Source File +# Begin Source File + +SOURCE=os.c +# End Source File +# Begin Source File + +SOURCE=vs2005_cs.c +# End Source File +# Begin Source File + +SOURCE=gnu.c +# End Source File +# Begin Source File + +SOURCE=gnu_cpp.c +# End Source File +# Begin Source File + +SOURCE=gnu_cs.c +# End Source File +# Begin Source File + +SOURCE=platform_windows.c +# End Source File +# Begin Source File + +SOURCE=project.c +# End Source File +# Begin Source File + +SOURCE=vs2002_cs.c +# End Source File +# Begin Source File + +SOURCE=clean.c +# End Source File +# Begin Source File + +SOURCE=premake.c +# End Source File +# Begin Source File + +SOURCE=vs.c +# End Source File +# Begin Source File + +SOURCE=path.c +# End Source File +# Begin Source File + +SOURCE=vs2002.c +# End Source File +# End Target +# End Project diff --git a/build/premake/src/Src/Premake.vcproj b/build/premake/src/Src/Premake.vcproj new file mode 100644 index 0000000000..a24472667a --- /dev/null +++ b/build/premake/src/Src/Premake.vcproj @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/premake/src/Src/arg.c b/build/premake/src/Src/arg.c new file mode 100644 index 0000000000..1e43e888e2 --- /dev/null +++ b/build/premake/src/Src/arg.c @@ -0,0 +1,66 @@ +/********************************************************************** + * Premake - arg.c + * Command-line argument handling. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include "premake.h" +#include "arg.h" + + +static int my_argc; +static char** my_argv; +static int my_next; + + + +void arg_set(int argc, char** argv) +{ + my_argc = argc; + my_argv = argv; + my_next = 1; +} + + + +void arg_reset() +{ + my_next = 1; +} + + + +const char* arg_getflag() +{ + if (my_next == my_argc) + return NULL; + + return my_argv[my_next++]; +} + + + +const char* arg_getflagarg() +{ + if (my_next == my_argc) + return NULL; + + if (strncmp(my_argv[my_next], "--", 2) == 0) + return NULL; + + return my_argv[my_next++]; +} diff --git a/build/premake/src/Src/arg.h b/build/premake/src/Src/arg.h new file mode 100644 index 0000000000..cdde05d022 --- /dev/null +++ b/build/premake/src/Src/arg.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Premake - arg.h + * Command-line argument handling. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +const char* arg_getflag(); +const char* arg_getflagarg(); +void arg_reset(); +void arg_set(int argc, char** argv); diff --git a/build/premake/src/Src/clean.c b/build/premake/src/Src/clean.c new file mode 100644 index 0000000000..6903fd1e2f --- /dev/null +++ b/build/premake/src/Src/clean.c @@ -0,0 +1,151 @@ +/********************************************************************** + * Premake - clean.c + * The cleanup target. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" + +static char buffer[8192]; + + +int clean() +{ + int i, j; + + puts("Removing all project and intermediate files..."); + + /* VS.NET 200x */ + io_remove(path_join(prj_get_path(), prj_get_name(), "sln")); + io_remove(path_join(prj_get_path(), prj_get_name(), "suo")); + + /* VS6 */ + io_remove(path_join(prj_get_path(), prj_get_name(), "ncb")); + io_remove(path_join(prj_get_path(), prj_get_name(), "dsw")); + io_remove(path_join(prj_get_path(), prj_get_name(), "opt")); + + /* GNU */ + io_remove(path_join(prj_get_path(), "Makefile", "")); + + /* SharpDevelop */ + io_remove(path_join(prj_get_path(), prj_get_name(), "cmbx")); + + /* MonoDevelop */ + io_remove(path_join(prj_get_path(), prj_get_name(), "mdsx")); + io_remove(path_join(prj_get_path(), "make", "sh")); + + for (i = 0; i < prj_get_numpackages(); ++i) + { + char cwd[8192]; + MaskHandle mask; + + prj_select_package(i); + + strcpy(cwd, io_getcwd()); + io_chdir(prj_get_pkgpath()); + + for (j = 0; j < prj_get_numconfigs(); ++j) + { + prj_select_config(j); + + /* POSIX shared lib */ + strcpy(buffer, prj_get_prefix() != NULL ? prj_get_prefix() : "lib"); + strcat(buffer, path_getbasename(prj_get_target())); + strcat(buffer, "."); + strcat(buffer, prj_get_extension() != NULL ? prj_get_extension() : "so"); + io_remove(path_join(prj_get_outdir(), buffer, "")); + + /* POSIX executable */ + strcpy(buffer, prj_get_prefix() != NULL ? prj_get_prefix() : ""); + strcat(buffer, path_getbasename(prj_get_target())); + io_remove(path_join(prj_get_outdir(), buffer, "")); + + /* Windows executable */ + io_remove(path_join(prj_get_outdir(), buffer, "exe")); + + /* .NET assembly manifest */ + io_remove(path_join(prj_get_outdir(), buffer, "exe.manifest")); + + /* DLL or assembly */ + io_remove(path_join(prj_get_outdir(), buffer, "dll")); + + /* Windows static library */ + io_remove(path_join(prj_get_outdir(), buffer, "lib")); + + /* Visual Studio symbol file */ + io_remove(path_join(prj_get_outdir(), buffer, "pdb")); + + /* Visual Studio incremental link file */ + io_remove(path_join(prj_get_outdir(), buffer, "ilk")); + + /* Visual Studio VSHOST */ + io_remove(path_join(prj_get_outdir(), buffer, "vshost.exe")); + + /* Windows DLL exports library */ + io_remove(path_join(prj_get_libdir(), buffer, "lib")); + io_remove(path_join(prj_get_libdir(), buffer, "exp")); + + /* Mono debugger symbols */ + io_remove(path_join(prj_get_outdir(), buffer, "mdb")); + + /* All */ + io_rmdir(".", prj_get_objdir()); + } + + /* VS.NET 2005 */ + strcpy(g_buffer, path_join(".", prj_get_pkgname(), "vcproj.*.user")); + mask = io_mask_open(g_buffer); + while (io_mask_getnext(mask)) + io_remove(io_mask_getname(mask)); + io_mask_close(mask); + + strcpy(g_buffer, path_join(".", prj_get_pkgname(), "csproj.*.user")); + mask = io_mask_open(g_buffer); + while (io_mask_getnext(mask)) + io_remove(io_mask_getname(mask)); + io_mask_close(mask); + + /* VS.NET 200x */ + io_remove(path_join(".", prj_get_pkgname(), "csproj")); + io_remove(path_join(".", prj_get_pkgname(), "csproj.user")); + io_remove(path_join(".", prj_get_pkgname(), "csproj.webinfo")); + io_remove(path_join(".", prj_get_pkgname(), "vcproj")); + + /* VS6 */ + io_remove(path_join(".", prj_get_pkgname(), "dsp")); + io_remove(path_join(".", prj_get_pkgname(), "plg")); + + /* GNU */ + io_remove(path_join(".", "Makefile", "")); + io_remove(path_join(".", prj_get_pkgname(), "mak")); + + /* SharpDevelop */ + io_remove(path_join(".", prj_get_pkgname(), "prjx")); + + /* MonoDevelop */ + io_remove(path_join(".", prj_get_pkgname(), "cmbx")); + io_remove(path_join(".", "Makefile", prj_get_pkgname())); + io_remove(path_join(".", prj_get_pkgname(), "pidb")); + + /* All */ + if (prj_get_pkgobjdir() != NULL) + io_rmdir(".", prj_get_pkgobjdir()); + + io_chdir(cwd); + } + + return 1; +} diff --git a/build/premake/src/Src/gnu.c b/build/premake/src/Src/gnu.c new file mode 100644 index 0000000000..89b666dc3a --- /dev/null +++ b/build/premake/src/Src/gnu.c @@ -0,0 +1,198 @@ +/********************************************************************** + * Premake - gnu.c + * The GNU makefile target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "arg.h" +#include "gnu.h" + +static int writeRootMakefile(); +static const char* listInterPackageDeps(const char* name); + + +int gnu_generate() +{ + int i; + + puts("Generating GNU makefiles:"); + + if (!writeRootMakefile()) + return 0; + + for (i = 0; i < prj_get_numpackages(); ++i) + { + int result; + + prj_select_package(i); + + printf("...%s\n", prj_get_pkgname()); + + if (prj_is_lang("c#")) + { + result = gnu_cs(); + } + else if (prj_is_lang("c++") || prj_is_lang("c")) + { + result = gnu_cpp(); + } + else + { + printf("** Error: unrecognized language '%s'\n", prj_get_language()); + return 0; + } + + if (!result) + return 0; + } + + return 1; +} + + + +static int writeRootMakefile() +{ + const char* arg; + int i; + + if (!io_openfile(path_join(prj_get_path(), "Makefile", ""))) + return 0; + + /* Print the file header, showing the possible build configurations */ + io_print("# Makefile autogenerated by premake\n"); + io_print("# Don't edit this file! Instead edit `premake.lua` then rerun `make`\n"); + io_print("# Options:\n"); + io_print("# CONFIG=["); + prj_select_package(0); + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + if (i > 0) + io_print("|"); + io_print(prj_get_cfgname()); + } + io_print("]\n\n"); + + /* Set a default build config if none specified */ + prj_select_config(0); + io_print("ifndef CONFIG\n"); + io_print(" CONFIG=%s\n", prj_get_cfgname()); + io_print("endif\n\n"); + io_print("export CONFIG\n\n"); + + /* List all of the available make targets */ + io_print(".PHONY: all clean"); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + io_print(" %s", prj_get_pkgname()); + } + io_print("\n\n"); + + /* Make rules */ + io_print("all:"); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + io_print(" %s", prj_get_pkgname()); + } + io_print("\n\n"); + + /* Target to regenerate the makefiles when the premake scripts change */ + strcpy(g_buffer, path_build(prj_get_path(), ".")); + io_print("Makefile: %s", path_combine(g_buffer, prj_get_script())); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + if (!matches(prj_get_script(), prj_get_pkgscript())) + { + strcpy(g_buffer, path_build(prj_get_path(), ".")); + io_print(" %s", path_combine(g_buffer, prj_get_pkgscript())); + } + } + io_print("\n"); + io_print("\t@echo ==== Regenerating Makefiles ====\n"); + io_print("\t@premake --file $^"); + arg_reset(); + arg = arg_getflag(); + while (arg != NULL) + { + if (matches(arg, "--file")) + { + arg_getflagarg(); + } + else + { + io_print(" %s", arg); + } + arg = arg_getflag(); + } + io_print("\n\n"); + + /* Individual package targets */ + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + prj_select_config(0); + + io_print("%s:", prj_get_pkgname()); + print_list(prj_get_links(), " ", "", "", listInterPackageDeps); + io_print("\n"); + + io_print("\t@echo ==== Building %s ====\n", prj_get_pkgname()); + io_print("\t@$(MAKE) "); + io_print("--no-print-directory -C %s", path_build(prj_get_path(), prj_get_pkgpath())); + if (!gnu_pkgOwnsPath()) + io_print(" -f %s.%s", prj_get_pkgname(), DOT_MAKE); + io_print("\n\n"); + } + + io_print("clean:\n"); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + + io_print("\t@$(MAKE) "); + io_print("--no-print-directory -C %s", path_build(prj_get_path(), prj_get_pkgpath())); + if (!gnu_pkgOwnsPath()) + io_print(" -f %s.%s", prj_get_pkgname(), DOT_MAKE); + io_print(" clean\n"); + } + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Checks if a package link matches the name of a sibling package. This + * is used to generate a Makefile dependency on the sibling. + ***********************************************************************/ + +static const char* listInterPackageDeps(const char* name) +{ + int i; + for (i = 0; i < prj_get_numpackages(); ++i) + { + if (matches(name, prj_get_pkgname_for(i))) + return name; + } + return NULL; +} + + diff --git a/build/premake/src/Src/gnu.h b/build/premake/src/Src/gnu.h new file mode 100644 index 0000000000..61266cf67d --- /dev/null +++ b/build/premake/src/Src/gnu.h @@ -0,0 +1,26 @@ +/********************************************************************** + * Premake - gnu.h + * The GNU makefile target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#define DOT_MAKE "make" + +int gnu_generate(); + +int gnu_cpp(); +int gnu_cs(); + +/* Helpers */ +int gnu_pkgOwnsPath(); diff --git a/build/premake/src/Src/gnu_cpp.c b/build/premake/src/Src/gnu_cpp.c new file mode 100644 index 0000000000..e7cace81fc --- /dev/null +++ b/build/premake/src/Src/gnu_cpp.c @@ -0,0 +1,418 @@ +/********************************************************************** + * Premake - gnu_cpp.c + * The GNU C/C++ makefile target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "gnu.h" +#include "os.h" + +static const char* filterLinks(const char* name); +static const char* listCppSources(const char* name); +static const char* listRcSources(const char* name); +static const char* listCppTargets(const char* name); +static const char* listRcTargets(const char* name); +static const char* listLinkerDeps(const char* name); + + +int gnu_cpp() +{ + int i; + + const char* prefix = (g_verbose) ? "" : "@"; + + /* Open package makefile and write the header */ + if (gnu_pkgOwnsPath()) + strcpy(g_buffer, path_join(prj_get_pkgpath(), "Makefile", "")); + else + strcpy(g_buffer, path_join(prj_get_pkgpath(), prj_get_pkgname(), DOT_MAKE)); + io_openfile(g_buffer); + + io_print("# %s ", prj_is_lang("c++") ? "C++" : "C"); + + if (prj_is_kind("exe")) + io_print("Console Executable"); + else if (prj_is_kind("winexe")) + io_print("Windowed Executable"); + else if (prj_is_kind("dll")) + io_print("Shared Library"); + else if (prj_is_kind("lib")) + io_print("Static Library"); + + io_print(" Makefile autogenerated by premake\n"); + io_print("# Don't edit this file! Instead edit `premake.lua` then rerun `make`\n\n"); + + /* Set a default configuration */ + prj_select_config(0); + io_print("ifndef CONFIG\n"); + io_print(" CONFIG=%s\n", prj_get_cfgname()); + io_print("endif\n\n"); + + /* Process the build configurations */ + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + + io_print("ifeq ($(CONFIG),%s)\n", prj_get_cfgname()); + + io_print(" BINDIR := %s\n", prj_get_bindir()); + io_print(" LIBDIR := %s\n", prj_get_libdir()); + io_print(" OBJDIR := %s\n", prj_get_objdir()); + io_print(" OUTDIR := %s\n", prj_get_outdir()); + + /* Write preprocessor flags - how to generate dependencies for DMC? */ + io_print(" CPPFLAGS :="); + if (!matches(g_cc, "dmc")) + io_print(" -MD"); + print_list(prj_get_defines(), " -D \"", "\"", "", NULL); + print_list(prj_get_incpaths(), " -I \"", "\"", "", NULL); + io_print("\n"); + + /* Write C flags */ + io_print(" CFLAGS += $(CPPFLAGS)"); + if (prj_is_kind("dll") && !os_is("windows")) + io_print(" -fPIC"); + if (!prj_has_flag("no-symbols")) + io_print(" -g"); + if (prj_has_flag("optimize-size")) + io_print(" -Os"); + if (prj_has_flag("optimize-speed")) + io_print(" -O3"); + if (prj_has_flag("optimize") && !prj_has_flag("optimize-size") && !prj_has_flag("optimize-speed")) + io_print(" -O2"); + if (prj_has_flag("extra-warnings")) + io_print(" -Wall"); + if (prj_has_flag("fatal-warnings")) + io_print(" -Werror"); + if (prj_has_flag("no-frame-pointer")) + io_print(" -fomit-frame-pointer"); + print_list(prj_get_buildoptions(), " ", "", "", NULL); + io_print("\n"); + + /* Write C++ flags */ + io_print(" CXXFLAGS := $(CFLAGS)"); + if (prj_has_flag("no-exceptions")) + io_print(" --no-exceptions"); + if (prj_has_flag("no-rtti")) + io_print(" --no-rtti"); + io_print("\n"); + + /* Write linker flags */ + io_print(" LDFLAGS += -L$(BINDIR) -L$(LIBDIR)"); + if (prj_is_kind("dll") && (g_cc == NULL || matches(g_cc, "gcc"))) + io_print(" -shared"); + if (prj_has_flag("no-symbols")) + io_print(" -s"); + if (os_is("macosx") && prj_has_flag("dylib")) + io_print(" -dynamiclib -flat_namespace"); + print_list(prj_get_linkoptions(), " ", "", "", NULL); + print_list(prj_get_libpaths(), " -L \"", "\"", "", NULL); + print_list(prj_get_links(), " ", "", "", filterLinks); + io_print("\n"); + + /* Build a list of libraries this target depends on */ + io_print(" LDDEPS :="); + print_list(prj_get_links(), " ", "", "", listLinkerDeps); + io_print("\n"); + + /* Build the target name */ + io_print(" TARGET := %s\n", path_getname(prj_get_target())); + if (os_is("macosx") && prj_is_kind("winexe")) + io_print(" MACAPP := %s.app/Contents\n", path_getname(prj_get_target())); + + /* Build command */ + io_print(" BLDCMD = "); + if (prj_is_kind("lib")) + io_print("ar -cr $(OUTDIR)/$(TARGET) $(OBJECTS); ranlib $(OUTDIR)/$(TARGET)"); + else + io_print("$(%s) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES)", prj_is_lang("c") ? "CC" : "CXX"); + io_print("\n"); + + io_print("endif\n\n"); + } + + /* Write out the list of object file targets for all C/C++ sources */ + io_print("OBJECTS := \\\n"); + print_list(prj_get_files(), "\t$(OBJDIR)/", " \\\n", "", listCppSources); + io_print("\n"); + + /* Write out the list of resource files for windows targets */ + if (os_is("windows")) + { + io_print("RESOURCES := \\\n"); + print_list(prj_get_files(), "\t$(OBJDIR)/", " \\\n", "", listRcSources); + io_print("\n"); + } + + io_print("CMD := $(subst \\,\\\\,$(ComSpec)$(COMSPEC))\n"); + io_print("ifeq (,$(CMD))\n"); + io_print(" CMD_MKBINDIR := mkdir -p $(BINDIR)\n"); + io_print(" CMD_MKLIBDIR := mkdir -p $(LIBDIR)\n"); + io_print(" CMD_MKOUTDIR := mkdir -p $(OUTDIR)\n"); + io_print(" CMD_MKOBJDIR := mkdir -p $(OBJDIR)\n"); + io_print("else\n"); + io_print(" CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\\\,$(BINDIR)) mkdir $(subst /,\\\\,$(BINDIR))\n"); + io_print(" CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\\\,$(LIBDIR)) mkdir $(subst /,\\\\,$(LIBDIR))\n"); + io_print(" CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\\\,$(OUTDIR)) mkdir $(subst /,\\\\,$(OUTDIR))\n"); + io_print(" CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\\\,$(OBJDIR)) mkdir $(subst /,\\\\,$(OBJDIR))\n"); + io_print("endif\n"); + io_print("\n"); + + io_print(".PHONY: clean\n"); + io_print("\n"); + + /* Write the main build target */ + if (os_is("macosx") && prj_is_kind("winexe")) + { + io_print("all: $(OUTDIR)/$(MACAPP)/PkgInfo $(OUTDIR)/$(MACAPP)/Info.plist $(OUTDIR)/$(MACAPP)/MacOS/$(TARGET)\n\n"); + io_print("$(OUTDIR)/$(MACAPP)/MacOS/$(TARGET)"); + } + else + { + io_print("$(OUTDIR)/$(TARGET)"); + } + + io_print(": $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"); + if (!g_verbose) + io_print("\t@echo Linking %s\n", prj_get_pkgname()); + io_print("\t-%s$(CMD_MKBINDIR)\n", prefix); + io_print("\t-%s$(CMD_MKLIBDIR)\n", prefix); + io_print("\t-%s$(CMD_MKOUTDIR)\n", prefix); + if (os_is("macosx") && prj_is_kind("winexe")) + io_print("\t-%sif [ ! -d $(OUTDIR)/$(MACAPP)/MacOS ]; then mkdir -p $(OUTDIR)/$(MACAPP)/MacOS; fi\n", prefix); + io_print("\t%s$(BLDCMD)\n\n", prefix); + +/* + if (prj_is_kind("lib")) + { + io_print("\t%sar -cr $@ $^\n", prefix); + io_print("\t%sranlib $@\n", prefix); + } + else + { + io_print("\t%s$(%s) -o $@ $(OBJECTS) $(LDFLAGS) $(RESOURCES)\n", prefix, prj_is_lang("c") ? "CC" : "CXX"); + } + io_print("\n"); +*/ + + if (os_is("macosx") && prj_is_kind("winexe")) + { + io_print("$(OUTDIR)/$(MACAPP)/PkgInfo:\n\n"); + io_print("$(OUTDIR)/$(MACAPP)/Info.plist:\n\n"); + } + + /* Write the "clean" target */ + io_print("clean:\n"); + io_print("\t@echo Cleaning %s\n", prj_get_pkgname()); + if (os_is("macosx") && prj_is_kind("winexe")) + { + io_print("\t-%srm -rf $(OUTDIR)/$(TARGET).app $(OBJDIR)\n", prefix); + } + else + { + io_print("\t-%srm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)\n", prefix); + } + io_print("\n"); + + /* Write static patterns for each source file. Note that in earlier + * versions I used pattern rules instead of listing each file. It worked + * fine but made it more difficult to test and also required the use of + * VPATH which I didn't like. This new approach of listing each file + * helps testing and opens the way for per-file configurations */ + print_list(prj_get_files(), "", "\n", "", listCppTargets); + + if (os_is("windows")) + print_list(prj_get_files(), "", "", "", listRcTargets); + + /* Include the automatically generated dependency lists */ + io_print("-include $(OBJECTS:%%.o=%%.d)\n\n"); + + io_closefile(); + return 1; +} + + + +/************************************************************************ + * Checks each entry in the list of package links. If the entry refers + * to a sibling package, returns the path to that package's output + ***********************************************************************/ + +static const char* filterLinks(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + const char* lang = prj_get_language_for(i); + if (matches(lang, "c++") || matches(lang, "c")) + { + return prj_get_target_for(i); + } + else + { + return NULL; + } + } + else + { + strcpy(g_buffer, "-l"); + strcat(g_buffer, name); + return g_buffer; + } +} + + +/************************************************************************ + * Checks each source code file and filters out everything that is + * not a C or C++ file + ***********************************************************************/ + +static const char* listCppSources(const char* name) +{ + if (is_cpp(name)) + { + strcpy(g_buffer, path_getbasename(name)); + strcat(g_buffer, ".o"); + return g_buffer; + } + + return NULL; +} + + +/************************************************************************ + * Checks each source code file and filters out everything that is + * not a windows resource file + ***********************************************************************/ + +static const char* listRcSources(const char* name) +{ + const char* ext = path_getextension(name); + if (matches(ext, ".rc")) + { + strcpy(g_buffer, path_getbasename(name)); + strcat(g_buffer, ".res"); + return g_buffer; + } + + return NULL; +} + + +/************************************************************************ + * Creates the makefile build rules for all source code files + ***********************************************************************/ + +static const char* listCppTargets(const char* name) +{ + if (is_cpp(name)) + { + const char* ext = path_getextension(name); + + sprintf(g_buffer, "$(OBJDIR)/%s.o: %s\n", path_getbasename(name), name); + strcat(g_buffer, "\t-"); + if (!g_verbose) + strcat(g_buffer, "@"); + strcat(g_buffer, "$(CMD_MKOBJDIR)\n"); + + if (!g_verbose) + strcat(g_buffer, "\t@echo $(notdir $<)\n"); + + strcat(g_buffer, "\t"); + if (!g_verbose) + strcat(g_buffer, "@"); + if (matches(g_cc, "dmc")) + { + /* Digital Mars compiler build step */ + /* FIXME: How to handle assembly files with DMC? */ + if (matches(ext, ".c")) + strcat(g_buffer, "dmc $(CFLAGS) -o $@ -c $<\n"); + else if (!matches(ext, ".s")) + strcat(g_buffer, "dmc -cpp -Ae -Ar -mn $(CXXFLAGS) -o $@ -c $<\n"); + } + else + { + /* GNU GCC compiler build step */ + if (matches(ext, ".s")) + strcat(g_buffer, "$(CC) -x assembler-with-cpp $(CPPFLAGS) -o $@ -c $<\n"); + else if (matches(ext, ".c")) + strcat(g_buffer, "$(CC) $(CFLAGS) -MF $(OBJDIR)/$($(OBJDIR)/$(= 0) + { + return prj_get_target_for(i); + } + + return NULL; +} diff --git a/build/premake/src/Src/gnu_cs.c b/build/premake/src/Src/gnu_cs.c new file mode 100644 index 0000000000..b980470570 --- /dev/null +++ b/build/premake/src/Src/gnu_cs.c @@ -0,0 +1,576 @@ +/********************************************************************** + * Premake - gnu_cs.c + * The GNU C# makefile target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "gnu.h" +#include "os.h" + +static char buffer[8192]; + +static const char* assignCodeFiles(const char* name); +static const char* assignEmbeddedFiles(const char* name); +static const char* assignContentFiles(const char* name); + +static const char* listCodeFiles(const char* name); +static const char* listEmbeddedFiles(const char* name); +static const char* listLinkedFiles(const char* name); +static const char* listContentFiles(const char* name); +static const char* listContentTargets(const char* name); +static const char* listContentRules(const char* name); +static const char* listCopyLocalFiles(const char* name); +static const char* listCopyLocalRules(const char* name); + +static const char* listNonSiblingRefs(const char* name); +static const char* listSiblingRefs(const char* name); +static const char* listReferenceDeps(const char* name); +static const char* listResourceBuildSteps(const char* name); + + +int gnu_cs() +{ + const char* kind; + const char* extension; + const char* csc; + const char* resgen; + int i; + + /* Figure out what I'm building */ + kind = prj_get_kind(); + if (prj_is_kind("dll") || prj_is_kind("aspnet")) + { + extension = ".dll"; + kind = "library"; + } + else if (prj_is_kind("winexe") || prj_is_kind("exe")) + { + extension = ".exe"; + } + else + { + printf("** Error: unknown package type '%s'\n", kind); + return 0; + } + + /* Figure out what I'm building it with */ + if (g_dotnet == NULL) + { + if (os_is("windows")) + { + csc = "csc"; + resgen = "resgen"; + } + else + { + csc = "mcs"; + resgen = "resgen"; + } + } + else if (matches(g_dotnet, "ms")) + { + csc = "csc"; + resgen = "resgen"; + } + else if (matches(g_dotnet, "pnet")) + { + csc = "cscc"; + resgen = "resgen"; + } + else if (matches(g_dotnet, "mono")) + { + csc = "mcs"; + resgen = "resgen"; + } + else if (matches(g_dotnet, "mono2")) + { + csc = "gmcs"; + resgen = "resgen"; + } + else + { + printf("** Error: unknown .NET runtime '%s'\n", g_dotnet); + return 0; + } + + /* Open package makefile and write the header */ + if (gnu_pkgOwnsPath()) + strcpy(buffer, path_join(prj_get_pkgpath(), "Makefile", "")); + else + strcpy(buffer, path_join(prj_get_pkgpath(), prj_get_pkgname(), DOT_MAKE)); + io_openfile(buffer); + + io_print("# C# "); + if (prj_is_kind("exe")) + io_print("Console Executable"); + else if (prj_is_kind("winexe")) + io_print("Windowed Executable"); + else if (prj_is_kind("dll")) + io_print("Shared Library"); + else if (prj_is_kind("lib")) + io_print("Static Library"); + else if (prj_is_kind("aspnet")) + io_print("ASP.NET"); + + io_print(" Makefile autogenerated by premake\n"); + io_print("# Don't edit this file! Instead edit `premake.lua` then rerun `make`\n\n"); + + /* Set a default configuration */ + prj_select_config(0); + io_print("ifndef CONFIG\n"); + io_print(" CONFIG=%s\n", prj_get_cfgname()); + io_print("endif\n\n"); + + /* Specify the build tools */ + io_print("CSC := %s\n", csc); + io_print("RESGEN := %s\n", resgen); + io_print("\n"); + + /* Where to put compiled resources */ + io_print("OBJDIR := %s\n\n", prj_get_objdir()); + + /* Process the build configurations */ + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + + io_print("ifeq ($(CONFIG),%s)\n", prj_get_cfgname()); + io_print(" BINDIR := %s\n", prj_get_bindir()); + io_print(" OUTDIR := %s\n", prj_get_outdir()); + + io_print(" FLAGS += /t:%s", kind); + if (!prj_has_flag("no-symbols")) + { + io_print(" /debug"); + } + if (prj_has_flag("optimize") || prj_has_flag("optimize-size") || prj_has_flag("optimize-speed")) + { + /* Mono doesn't support the optimize flag */ + if (!matches(csc, "mcs")) + io_print(" /o"); + } + if (prj_has_flag("unsafe")) + { + io_print(" /unsafe"); + } + if (prj_has_flag("fatal-warnings")) + { + io_print(" /warnaserror"); + } + + print_list(prj_get_defines(), " /d:", "", "", NULL); + + /* VS.NET doesn't allow per-config link paths */ + prj_select_config(0); + print_list(prj_get_libpaths(), " /lib:\"", "\"", "", NULL); + print_list(prj_get_links(), " /r:", "", "", listNonSiblingRefs); + prj_select_config(i); + print_list(prj_get_links(), " /r:", "", "", listSiblingRefs); + io_print("\n"); + + /* List any sibling packages as dependencies for make */ + prj_select_config(i); + io_print(" DEPS :="); + print_list(prj_get_links(), " ", " ", "", listReferenceDeps); + io_print("\n"); + + /* VS.NET doesn't allow per-config target names */ + prj_select_config(0); + io_print(" TARGET := %s\n", path_getname(prj_get_target())); + io_print("endif\n\n"); + } + + /* Sort out the files by build action...start by assigning build actions + * to well-known file extensions...these don't write anything to the file */ + print_list(prj_get_files(), "", "", "", assignCodeFiles); + print_list(prj_get_files(), "", "", "", assignEmbeddedFiles); + print_list(prj_get_files(), "", "", "", assignContentFiles); + + /* Sort out the files by build action */ + io_print("SOURCES := \\\n"); + print_list(prj_get_files(), "\t", " \\\n", "", listCodeFiles); + io_print("\n"); + + io_print("EMBEDDEDFILES := \\\n"); + print_list(prj_get_files(), "\t", " \\\n", "", listEmbeddedFiles); + io_print("\n"); + + io_print("EMBEDDEDCOMMAND := \\\n"); + print_list(prj_get_files(), "\t/resource:", " \\\n", "", listEmbeddedFiles); + io_print("\n"); + + io_print("LINKEDFILES := \\\n"); + print_list(prj_get_files(), "\t", " \\\n", "", listLinkedFiles); + io_print("\n"); + + io_print("LINKEDCOMMAND := \\\n"); + print_list(prj_get_files(), "\t/linkresource:", " \\\n", "", listLinkedFiles); + io_print("\n"); + + io_print("CONTENTFILES := \\\n"); + print_list(prj_get_files(), "\t", " \\\n", "", listContentFiles); + io_print("\n"); + + io_print("COPYLOCALFILES := \\\n"); + print_list(prj_get_links(), "\t", " \\\n", "", listCopyLocalFiles); + io_print("\n"); + + io_print("COMPILECOMMAND := $(SOURCES) $(EMBEDDEDCOMMAND) $(LINKEDCOMMAND)\n\n"); + + io_print("CMD := $(subst \\,\\\\,$(ComSpec)$(COMSPEC))\n"); + io_print("ifeq (,$(CMD))\n"); + io_print(" CMD_MKOUTDIR := mkdir -p $(OUTDIR)\n"); + io_print("else\n"); + io_print(" CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\\\,$(OUTDIR)) mkdir $(subst /,\\\\,$(OUTDIR))\n"); + io_print("endif\n"); + io_print("\n"); + + /* Build targets: add all content files as dependencies so the copy + * rules will get fired when they change */ + io_print(".PHONY: clean\n\n"); + io_print("all: \\\n"); + io_print("\t$(OUTDIR)/$(TARGET) \\\n"); + print_list(prj_get_files(), "\t", " \\\n", "", listContentTargets); + io_print("\n"); + + /* The main build target */ + io_print("$(OUTDIR)/$(TARGET): $(SOURCES) $(EMBEDDEDFILES) $(LINKEDFILES) $(COPYLOCALFILES) $(DEPS)\n"); + io_print("\t-@$(CMD_MKOUTDIR)\n"); + io_print("\t@$(CSC) /nologo /out:$@ /lib:$(BINDIR) $(FLAGS) $(COMPILECOMMAND)\n\n"); + + /* Write rules to copy content files */ + print_list(prj_get_files(), "", "", "", listContentRules); + + /* Write rules to copy local assemblies */ + print_list(prj_get_links(), "", "", "", listCopyLocalRules); + + /* The clean target */ + io_print("clean:\n"); + io_print("\t@echo Cleaning %s\n", prj_get_pkgname()); + io_print("\t-@rm -f $(OUTDIR)/$(TARGET)\n"); + io_print("\t-@rm -fR $(OBJDIR)\n"); + print_list(prj_get_files(), "\t-@rm -f ", "\n", "", listContentTargets); + io_print("\n"); + + /* Resource build targets */ + print_list(prj_get_files(), "", "", "", listResourceBuildSteps); + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Visual Studio .NET automatically adds some extra information + * to resource names. Simulate that here. + ***********************************************************************/ + +static const char* makeVsNetCompatName(const char* name) +{ + char* ptr; + + if (matches(path_getextension(name), ".resx")) + { + /* The compiled .resources file goes into objdir */ + strcpy(buffer, prj_get_objdir()); + strcat(buffer, "/"); + + /* Prepend the default namespace (slashes will get translated below) */ + strcat(buffer, path_getbasename(prj_get_target())); + strcat(buffer, "."); + + /* ...followed by the path to the file */ + if (!matches(path_getdir(name), "")) + { + strcat(buffer, path_getdir(name)); + strcat(buffer, "."); + } + + /* ...finish up with the file name */ + strcat(buffer, path_getbasename(name)); + strcat(buffer, ".resources"); + + /* Convert any slashes in the name to dots */ + for (ptr = buffer + strlen(prj_get_objdir()) + 1; *ptr != '\0'; ++ptr) + { + if (*ptr == '/') + *ptr = '.'; + } + + return buffer; + } + else + { + return name; + } +} + + +/************************************************************************ + * Assign default build actions to files without one + ***********************************************************************/ + +static const char* assignCodeFiles(const char* name) +{ + const char* ext = path_getextension(name); + prj_select_file(name); + if (prj_is_buildaction(NULL) && matches(ext, ".cs")) + prj_set_buildaction("Code"); + return NULL; +} + +static const char* assignEmbeddedFiles(const char* name) +{ + const char* ext = path_getextension(name); + prj_select_file(name); + if (prj_is_buildaction(NULL) && matches(ext, ".resx")) + prj_set_buildaction("EmbeddedResource"); + return NULL; +} + +static const char* assignContentFiles(const char* name) +{ + const char* ext = path_getextension(name); + prj_select_file(name); + if (prj_is_buildaction(NULL) && (matches(ext, ".asax") || matches(ext, ".aspx"))) + prj_set_buildaction("Content"); + return NULL; +} + + +/************************************************************************ + * Checks to see if a given assembly exists on one of the listed link + * paths. If so, returns the relative path to the assembly. + ***********************************************************************/ + +static const char* findLocalAssembly(const char* name) +{ + const char** paths; + const char* result = NULL; + + /* Lib paths are relative to package directory. Have to make package + * directory current for io_fileexists() to work */ + strcpy(buffer, io_getcwd()); + io_chdir(prj_get_pkgpath()); + + paths = prj_get_libpaths(); + while (*paths != NULL) + { + const char* path = path_join(*paths, name, "dll"); + if (io_fileexists(path)) + { + result = path; + break; + } + ++paths; + } + + io_chdir(buffer); + return result; +} + + +/************************************************************************ + * Returns lists of files for each build action + ***********************************************************************/ + +static const char* listCodeFiles(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("Code")) + { + /* Csc needs backslashes, which GNU make doesn't like */ + const char* src = path_translate(name, NULL); + char* dst = buffer; + while (*src) + { + if (*src == '\\') + { + *(dst++) = '\\'; + *(dst++) = '\\'; + } + else + { + *(dst++) = *src; + } + src++; + } + *dst ='\0'; + return buffer; + } + else + { + return NULL; + } +} + +static const char* listEmbeddedFiles(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("EmbeddedResource")) + return makeVsNetCompatName(name); + else + return NULL; +} + +static const char* listLinkedFiles(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("LinkedResource")) + return makeVsNetCompatName(name); + else + return NULL; +} + +static const char* listContentFiles(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("Content")) + return name; + else + return NULL; +} + +static const char* listCopyLocalFiles(const char* name) +{ + const char* path = findLocalAssembly(name); + if (path != NULL) + { + sprintf(buffer, "$(BINDIR)/%s.dll", name); + return buffer; + } + return NULL; +} + + +/************************************************************************ + * Checks to see if a reference is to a sibling package. If so, + * returns the binary target name of the package. + ***********************************************************************/ + +static const char* listNonSiblingRefs(const char* name) +{ + int i = prj_find_package(name); + if (i < 0) + { + return path_join("", name, "dll"); + } + return NULL; +} + + +static const char* listSiblingRefs(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + if (matches(prj_get_language_for(i), "c#")) + { + return prj_get_target_for(i); + } + } + return NULL; +} + + +/************************************************************************ + * This is called by the code that builds the list of dependencies for + * the link step. It looks for sibling projects, and then returns the + * full path to that target's output. So if an executable package + * depends on a library package, the library filename will be listed + * as a dependency + ***********************************************************************/ + +static const char* listReferenceDeps(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + return prj_get_target_for(i); + } + + return NULL; +} + + +/************************************************************************ + * Write out content files as make dependencies + ***********************************************************************/ + +static const char* listContentTargets(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("LinkedResource") || prj_is_buildaction("Content")) + { + sprintf(buffer, "$(BINDIR)/%s", path_getname(name)); + return buffer; + } + else + { + return NULL; + } +} + + +/************************************************************************ + * Write out rules to move files to output directory + ***********************************************************************/ + +static const char* listContentRules(const char* name) +{ + prj_select_file(name); + if (prj_is_buildaction("LinkedResource") || prj_is_buildaction("Content")) + { + sprintf(buffer, "$(BINDIR)/%s: %s\n\t-@cp -fR $^ $@\n\n", path_getname(name), name); + return buffer; + } + return NULL; +} + +static const char* listCopyLocalRules(const char* name) +{ + const char* path = findLocalAssembly(name); + if (path != NULL) + { + sprintf(buffer, "$(BINDIR)/%s.dll: %s\n\t@echo Copying %s.dll\n\t-@cp $^ $@\n\n", name, path, name); + return buffer; + } + return NULL; +} + + + +/************************************************************************ + * Write out resource compilation rules + ***********************************************************************/ + +static const char* listResourceBuildSteps(const char* name) +{ + if (matches(path_getextension(name), ".resx")) + { + makeVsNetCompatName(name); + strcat(buffer, ": "); + strcat(buffer, name); + strcat(buffer, "\n\t-@if [ ! -d $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"); + strcat(buffer, "\n\t$(RESGEN) $^ $@\n\n"); + return buffer; + } + else + { + return NULL; + } +} diff --git a/build/premake/src/Src/gnu_helpers.c b/build/premake/src/Src/gnu_helpers.c new file mode 100644 index 0000000000..8af4156b8f --- /dev/null +++ b/build/premake/src/Src/gnu_helpers.c @@ -0,0 +1,40 @@ +/********************************************************************** + * Premake - gnu_helpers.c + * The GNU makefile target + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include "premake.h" +#include + + +int gnu_pkgOwnsPath() +{ + int i; + + if (path_compare(prj_get_pkgpath(), prj_get_path())) + return 0; + + for (i = 0; i < prj_get_numpackages(); ++i) + { + if (prj_get_package() != prj_get_package_for(i)) + { + if (path_compare(prj_get_pkgpath(), prj_get_pkgpath_for(i))) + return 0; + } + } + + return 1; +} + diff --git a/build/premake/src/Src/io.c b/build/premake/src/Src/io.c new file mode 100644 index 0000000000..72406c1adf --- /dev/null +++ b/build/premake/src/Src/io.c @@ -0,0 +1,184 @@ +/********************************************************************** + * Premake - io.c + * File and directory I/O routines. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include +#include "io.h" +#include "path.h" +#include "platform.h" + +static char buffer[8192]; +static FILE* file; + + +int io_chdir(const char* path) +{ + return platform_chdir(path); +} + +int io_closefile() +{ + fclose(file); + return 1; +} + + +int io_copyfile(const char* src, const char* dest) +{ + return platform_copyfile(src, dest); +} + + +int io_fileexists(const char* path) +{ + struct stat buf; + if (stat(path, &buf) == 0) + { + if (buf.st_mode & S_IFDIR) + return 0; + else + return 1; + } + else + { + return 0; + } +} + + +const char* io_findlib(const char* name) +{ + if (platform_findlib(name, buffer, 8192)) + return buffer; + else + return NULL; +} + + +const char* io_getcwd() +{ + platform_getcwd(buffer, 8192); + return buffer; +} + + +int io_mask_close(MaskHandle data) +{ + return platform_mask_close(data); +} + + +const char* io_mask_getname(MaskHandle data) +{ + return platform_mask_getname(data); +} + + +int io_mask_getnext(MaskHandle data) +{ + return platform_mask_getnext(data); +} + + +int io_mask_isfile(MaskHandle data) +{ + return platform_mask_isfile(data); +} + + +MaskHandle io_mask_open(const char* mask) +{ + return platform_mask_open(mask); +} + + +int io_mkdir(const char* path) +{ + /* Remember the current directory */ + char cwd[8192]; + platform_getcwd(cwd, 8192); + + /* Split the path and check each part in turn */ + strcpy(buffer, path); + path = buffer; + + while (path != NULL) + { + char* ptr = strchr(path, '/'); + if (ptr != NULL) + *ptr = '\0'; + + platform_mkdir(path); + platform_chdir(path); + + path = (ptr != NULL) ? ptr + 1 : NULL; + } + + /* Restore the original working directory */ + platform_chdir(cwd); + return 1; +} + + +int io_openfile(const char* path) +{ + /* Make sure that all parts of the path exist */ + io_mkdir(path_getdir(path)); + + /* Now I can open the file */ + file = fopen(path, "w"); + if (file == NULL) + { + printf("** Unable to open file '%s' for writing\n", path); + return 0; + } + else + { + return 1; + } +} + + +void io_print(const char* format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(file, format, args); + va_end(args); +} + + +int io_remove(const char* path) +{ + return platform_remove(path); +} + + +int io_rmdir(const char* path, const char* dir) +{ + strcpy(buffer, path); + if (strlen(buffer) > 0) + strcat(buffer, "/"); + strcat(buffer, dir); + path_translateInPlace(buffer, NULL); + return platform_rmdir(buffer); +} + + + diff --git a/build/premake/src/Src/io.h b/build/premake/src/Src/io.h new file mode 100644 index 0000000000..3c5e21507a --- /dev/null +++ b/build/premake/src/Src/io.h @@ -0,0 +1,36 @@ +/********************************************************************** + * Premake - io.h + * File and directory I/O routines. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +struct PlatformMaskData; +typedef struct PlatformMaskData* MaskHandle; + +int io_chdir(const char* path); +int io_closefile(); +int io_copyfile(const char* src, const char* dst); +int io_fileexists(const char* path); +const char* io_findlib(const char* name); +const char* io_getcwd(); +int io_mask_close(MaskHandle data); +const char* io_mask_getname(MaskHandle data); +int io_mask_getnext(MaskHandle data); +int io_mask_isfile(MaskHandle data); +MaskHandle io_mask_open(const char* mask); +int io_openfile(const char* path); +void io_print(const char* format, ...); +int io_remove(const char* path); +int io_rmdir(const char* path, const char* dir); + diff --git a/build/premake/src/Src/os.c b/build/premake/src/Src/os.c new file mode 100644 index 0000000000..ca44d9670b --- /dev/null +++ b/build/premake/src/Src/os.c @@ -0,0 +1,72 @@ +/********************************************************************** + * Premake - os.c + * Manage the list of supported OSes. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include "util.h" +#include "os.h" + +static const char* os; + + +/* Determine the current operating system. I'm not sure how to + * consistently detect the Windows platform, but since that is the + * most common I use it as a default */ +void os_detect() +{ +#if defined(__linux__) + os = "linux"; +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + os = "bsd"; +#elif defined(__APPLE__) && defined(__MACH__) + os = "macosx"; +#else + os = "windows"; +#endif +} + + +/* Retrieve the identification string */ +const char* os_get() +{ + return os; +} + + +/* Does this identifier match the selected OS? */ +int os_is(const char* name) +{ + return matches(name, os); +} + + +/* Does this symbol represent a valid OS identifier string? */ +int os_set(const char* name) +{ + if (matches(name, "bsd") || + matches(name, "linux") || + matches(name, "macosx") || + matches(name, "windows")) + { + os = name; + return 1; + } + else + { + return 0; + } +} + diff --git a/build/premake/src/Src/os.h b/build/premake/src/Src/os.h new file mode 100644 index 0000000000..f122f9a504 --- /dev/null +++ b/build/premake/src/Src/os.h @@ -0,0 +1,33 @@ +/********************************************************************** + * Premake - os.h + * Manage the list of supported OSes. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +/* Determine the current OS. I'm not sure how to reliably detect Windows + * but since it is the most command I use is as the default */ +#if defined(__linux__) +#define PLATFORM_POSIX 1 +#elif defined(__FreeBSD) || defined(__NetBSD__) || defined(__OpenBSD__) +#define PLATFORM_POSIX 1 +#elif defined(__APPLE__) && defined(__MACH__) +#define PLATFORM_POSIX 1 +#else +#define PLATFORM_WINDOWS 1 +#endif + +void os_detect(); +const char* os_get(); +int os_is(const char* name); +int os_set(const char* name); diff --git a/build/premake/src/Src/path.c b/build/premake/src/Src/path.c new file mode 100644 index 0000000000..5c8da681af --- /dev/null +++ b/build/premake/src/Src/path.c @@ -0,0 +1,306 @@ +/********************************************************************** + * Premake - path.c + * Path handling routines. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "os.h" +#include "platform.h" + +static char working[8192]; +static char forpart[8192]; + + +/************************************************************************ + * Return the full path from a relative path. Contains some extra + * logic to handle the case where the directory doesn't exist + ***********************************************************************/ + +const char* path_absolute(const char* path) +{ + char relative[8192]; + char* ptr; + + strcpy(relative, path); + if (strlen(relative) == 0) + strcpy(relative, "."); + path_translateInPlace(relative, "posix"); + + /* If the directory is already absolute I don't have to do anything */ + if (platform_isAbsolutePath(relative)) + return path; + + /* Figure out where I am currently */ + platform_getcwd(working, 8192); + path_translateInPlace(working, "posix"); + + /* Split the target path and add it in piece by piece */ + ptr = relative; + while (ptr != NULL) + { + char* end = strchr(ptr, '/'); + if (end != NULL) + *end = '\0'; + + if (matches(ptr, "..")) + { + char* sep = strrchr(working, '/'); + if (sep != NULL) + *sep = '\0'; + } + else if (!matches(ptr, ".")) + { + strcat(working, "/"); + strcat(working, ptr); + } + + ptr = (end != NULL) ? end + 1 : NULL; + } + + return working; +} + + +/************************************************************************ + * Build a path to get from `from` to `to` + ***********************************************************************/ + +const char* path_build(const char* from, const char* to) +{ + char fromFull[8192]; + char toFull[8192]; + int start, i; + + /* Retrieve the full path to both locations */ + strcpy(fromFull, path_absolute(from)); + strcpy(toFull, path_absolute(to)); + + /* Append a separator to both */ + strcat(fromFull, "/"); + strcat(toFull, "/"); + + /* Trim off the common directories from the front */ + start = 0; + i = 0; + while (fromFull[i] != '\0' && toFull[i] != '\0' && fromFull[i] == toFull[i]) + { + if (fromFull[i] == '/') + start = i + 1; + i++; + } + + if (fromFull[i] == '\0' && toFull[i] == '\0') + return "."; + + /* Build the connecting path */ + if (strlen(fromFull) - start > 0) + { + strcpy(working, "../"); + for (i = start; fromFull[i] != '\0'; ++i) + { + if (fromFull[i] == '/' && fromFull[i + 1] != '\0') + strcat(working, "../"); + } + } + else + { + strcpy(working, ""); + } + + if (strlen(toFull) - start > 0) + { + strcat(working, toFull + start); + } + + /* Remove the trailing slash */ + working[strlen(working) - 1] = '\0'; + + /* Make sure I return something */ + if (strlen(working) == 0) + strcpy(working, "."); + + return working; +} + + +/************************************************************************ + * Merges two paths + ***********************************************************************/ + +const char* path_combine(const char* path0, const char* path1) +{ + strcpy(working, ""); + + if (!matches(path0, ".") && !matches(path0, "./")) + strcat(working, path0); + + path_translateInPlace(working, "posix"); + + if (!matches(path1, "") && !matches(path1, ".") && !matches(path1, "./")) + { + if (strlen(working) > 0 && working[strlen(working) - 1] != '/') + strcat(working, "/"); + strcat(working, path1); + } + + path_translateInPlace(working, "posix"); + return working; +} + + +/************************************************************************ + * Compare two paths for equality, regardless of path structure. + ***********************************************************************/ + +int path_compare(const char* path0, const char* path1) +{ + char abs0[8192]; + char abs1[8192]; + + strcpy(abs0, path_absolute(path0)); + strcpy(abs1, path_absolute(path1)); + return matches(abs0, abs1); +} + + +/************************************************************************ + * Retrieve the portions of a path + ***********************************************************************/ + +char path_getseparator(const char* type) +{ + if (type == NULL) + type = os_get(); + + if (matches(type, "windows")) + return '\\'; + else + return '/'; +} + +const char* path_getbasename(const char* path) +{ + const char* name = path_getname(path); + char* ptr = strrchr(name, '.'); + if (ptr != NULL) + *ptr = '\0'; + return name; +} + +const char* path_getextension(const char* path) +{ + const char* ptr = strrchr(path, '.'); + return ptr; +} + +const char* path_getdir(const char* path) +{ + char* ptr; + + if (path != NULL) + { + /* Convert path to neutral separators */ + strcpy(forpart, path); + path_translateInPlace(forpart, "posix"); + + /* Now split at last separator */ + ptr = strrchr(forpart, '/'); + if (ptr != NULL) + { + *ptr = '\0'; + return forpart; + } + } + + return ""; +} + +const char* path_getname(const char* path) +{ + char* ptr; + + if (path == NULL) + return NULL; + + strcpy(forpart, path); + path_translateInPlace(forpart, "posix"); + + ptr = strrchr(forpart, '/'); + ptr = (ptr != NULL) ? ++ptr : forpart; + return ptr; +} + + +/************************************************************************ + * Build a path from a directory, a file name, and a file extension + ***********************************************************************/ + +const char* path_join(const char* dir, const char* name, const char* ext) +{ + if (dir != NULL) + strcpy(working, dir); + else + strcpy(working, ""); + + if (strlen(working) > 0) + strcat(working, "/"); + + strcat(working, name); + + if (ext != NULL && strlen(ext) > 0) + { + strcat(working, "."); + strcat(working, ext); + } + + return working; +} + + +/************************************************************************ + * Swap one file extension for another + ***********************************************************************/ + +const char* path_swapextension(const char* path, const char* from, const char* to) +{ + strcpy(working, path); + working[strlen(path) - strlen(from)] = '\0'; + strcat(working, to); + return working; +} + + +/************************************************************************ + * Translate the separators used in a path + ***********************************************************************/ + +const char* path_translate(const char* path, const char* type) +{ + strcpy(working, path); + path_translateInPlace(working, type); + return working; +} + +void path_translateInPlace(char* buffer, const char* type) +{ + char* ptr; + for (ptr = buffer; *ptr != '\0'; ++ptr) + { + if (*ptr == '\\' || *ptr == '/') + *ptr = path_getseparator(type); + } +} diff --git a/build/premake/src/Src/path.h b/build/premake/src/Src/path.h new file mode 100644 index 0000000000..718996995d --- /dev/null +++ b/build/premake/src/Src/path.h @@ -0,0 +1,31 @@ +/********************************************************************** + * Premake - path.h + * Path handling routines. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +const char* path_absolute(const char* path); +const char* path_build(const char* from, const char* to); +const char* path_combine(const char* path0, const char* path1); +int path_compare(const char* path0, const char* path1); +const char* path_getbasename(const char* path); +const char* path_getextension(const char* path); +const char* path_getdir(const char* path); +const char* path_getname(const char* path); +char path_getseparator(const char* type); +const char* path_join(const char* dir, const char* name, const char* ext); +const char* path_normalize(const char* path); +const char* path_swapextension(const char* path, const char* from, const char* to); +const char* path_translate(const char* path, const char* type); +void path_translateInPlace(char* buffer, const char* type); diff --git a/build/premake/src/Src/platform.h b/build/premake/src/Src/platform.h new file mode 100644 index 0000000000..74a9cedb8a --- /dev/null +++ b/build/premake/src/Src/platform.h @@ -0,0 +1,31 @@ +/********************************************************************** + * Premake - platform.h + * Platform-specific functions. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int platform_chdir(const char* path); +int platform_copyfile(const char* src, const char* dest); +int platform_findlib(const char* name, char* buffer, int len); +int platform_getcwd(char* buffer, int len); +void platform_getuuid(char* uuid); +int platform_isAbsolutePath(const char* path); +int platform_mask_close(MaskHandle data); +const char* platform_mask_getname(MaskHandle data); +int platform_mask_getnext(MaskHandle data); +int platform_mask_isfile(MaskHandle data); +MaskHandle platform_mask_open(const char* mask); +int platform_mkdir(const char* path); +int platform_remove(const char* path); +int platform_rmdir(const char* path); diff --git a/build/premake/src/Src/platform_posix.c b/build/premake/src/Src/platform_posix.c new file mode 100644 index 0000000000..b2b3d14c26 --- /dev/null +++ b/build/premake/src/Src/platform_posix.c @@ -0,0 +1,218 @@ +/********************************************************************** + * Premake - platform_posix.h + * Windows-specific functions. + * + * Copyright (c) 2002-2005 Jason Perkins. + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include "os.h" +#if defined(PLATFORM_POSIX) + +#include +#include +#include +#include +#include +#include +#include +#include +#include "io.h" +#include "path.h" +#include "util.h" + +static char buffer[8192]; + +struct PlatformMaskData +{ + DIR* handle; + struct dirent* entry; + char* mask; +}; + + +int platform_chdir(const char* path) +{ + return !chdir(path); +} + + +int platform_copyfile(const char* src, const char* dest) +{ + sprintf(buffer, "cp %s %s", src, dest); + return (system(buffer) == 0); +} + + +static int findLibHelper(const char* lib, const char* path) +{ + struct stat sb; + + sprintf(buffer, "%s/lib%s.so", path, lib); + if (stat(buffer, &sb) == 0 && !S_ISDIR(sb.st_mode)) return 1; + + sprintf(buffer, "%s/%s.so", path, lib); + if (stat(buffer, &sb) == 0 && !S_ISDIR(sb.st_mode)) return 1; + + sprintf(buffer, "%s/%s", path, lib); + if (stat(buffer, &sb) == 0 && !S_ISDIR(sb.st_mode)) return 1; + + return 0; +} + +int platform_findlib(const char* name, char* buffer, int len) +{ + FILE* file; + + if (findLibHelper(name, "/usr/lib")) + { + strcpy(buffer, "/usr/lib"); + return 1; + } + + file = fopen("/etc/ld.so.conf", "rt"); + if (file == NULL) + return 0; + + while (!feof(file)) + { + /* Read a line and trim off any trailing whitespace */ + char linebuffer[4096]; + char* ptr; + + fgets(buffer, 4096, file); + ptr = &buffer[strlen(buffer) - 1]; + while (isspace(*ptr)) + *(ptr--) = '\0'; + + if (findLibHelper(name, buffer)) + { + fclose(file); + return 1; + } + } + + fclose(file); + return 0; +} + + +int platform_getcwd(char* buffer, int len) +{ + return (getcwd(buffer, len) == 0); +} + + +void platform_getuuid(char* uuid) +{ + FILE* rnd = fopen("/dev/random", "rb"); + fread(uuid, 16, 1, rnd); + fclose(rnd); +} + + +char platform_getseparator() +{ + return '/'; +} + + +int platform_isAbsolutePath(const char* path) +{ + return (path[0] == '/'); +} + + +int platform_mask_close(MaskHandle data) +{ + if (data->handle != NULL) + closedir(data->handle); + free(data->mask); + free(data); + return 1; +} + + +const char* platform_mask_getname(MaskHandle data) +{ + strcpy(buffer, path_getdir(data->mask)); + if (strlen(buffer) > 0) + strcat(buffer, "/"); + strcat(buffer, data->entry->d_name); + return buffer; +} + + +int platform_mask_getnext(MaskHandle data) +{ + const char* mask = path_getname(data->mask); + + if (data->handle == NULL) + return 0; + + data->entry = readdir(data->handle); + while (data->entry != NULL) + { + if (fnmatch(mask, data->entry->d_name, 0) == 0) + return 1; + data->entry = readdir(data->handle); + } + return 0; +} + + +int platform_mask_isfile(MaskHandle data) +{ + struct stat info; + if (stat(platform_mask_getname(data), &info) == 0) + { + return S_ISREG(info.st_mode); + } + return 0; +} + + +MaskHandle platform_mask_open(const char* mask) +{ + const char* path = path_getdir(mask); + if (strlen(path) == 0) + path = "."; + + MaskHandle data = ALLOCT(struct PlatformMaskData); + data->handle = opendir(path); + data->mask = (char*)malloc(strlen(mask) + 1); + strcpy(data->mask, mask); + return data; +} + + +int platform_mkdir(const char* path) +{ + return (mkdir(path, 0) == 0); +} + + +int platform_remove(const char* path) +{ + unlink(path); + return 1; +} + + +int platform_rmdir(const char* path) +{ + strcpy(buffer, "rm -rf "); + strcat(buffer, path); + return (system(buffer) == 0); +} + +#endif diff --git a/build/premake/src/Src/platform_windows.c b/build/premake/src/Src/platform_windows.c new file mode 100644 index 0000000000..a7e87f82e7 --- /dev/null +++ b/build/premake/src/Src/platform_windows.c @@ -0,0 +1,201 @@ +/********************************************************************** + * Premake - platform_windows.h + * Windows-specific functions. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include "os.h" +#if defined(PLATFORM_WINDOWS) + +#include +#include "io.h" +#include "path.h" +#include "util.h" +#include "platform.h" + +#define WIN32_LEAN_AND_MEAN +#include + +static char buffer[8192]; + +struct PlatformMaskData +{ + char* maskPath; + HANDLE handle; + WIN32_FIND_DATA entry; + int isFirst; +}; + +static int (__stdcall *CoCreateGuid)(char*) = NULL; +static BOOL (__stdcall *GetUserName_)(LPTSTR,LPDWORD) = NULL; + + +int platform_chdir(const char* path) +{ + return SetCurrentDirectory(path); +} + + +int platform_copyfile(const char* src, const char* dest) +{ + return CopyFile(src, dest, FALSE); +} + + +int platform_findlib(const char* name, char* buffer, int len) +{ + HMODULE hDll = LoadLibrary(name); + if (hDll != NULL) + { + GetModuleFileName(hDll, buffer, len); + strcpy(buffer, path_getdir(buffer)); + FreeLibrary(hDll); + return 1; + } + else + { + return 0; + } +} + +int platform_getcwd(char* buffer, int len) +{ + GetCurrentDirectory(len, buffer); + return 1; +} + + +void platform_getuuid(char* uuid) +{ + if (CoCreateGuid == NULL) + { + HMODULE hOleDll = LoadLibrary("OLE32.DLL"); + *((void**)&CoCreateGuid) = GetProcAddress(hOleDll, "CoCreateGuid"); + } + CoCreateGuid((char*)uuid); +} + + +int platform_isAbsolutePath(const char* path) +{ + return (path[0] == '/' || path[0] == '\\' || (strlen(path) > 1 && path[1] == ':')); +} + + +int platform_mask_close(MaskHandle data) +{ + if (data->handle != INVALID_HANDLE_VALUE) + FindClose(data->handle); + free(data->maskPath); + free(data); + return 1; +} + + +const char* platform_mask_getname(MaskHandle data) +{ + strcpy(buffer, data->maskPath); + if (strlen(buffer) > 0) + strcat(buffer, "/"); + strcat(buffer, data->entry.cFileName); + return buffer; +} + + +int platform_mask_getnext(MaskHandle data) +{ + if (data->handle == INVALID_HANDLE_VALUE) + return 0; + + if (data->isFirst) + { + data->isFirst = 0; + return 1; + } + else + { + return FindNextFile(data->handle, &data->entry); + } +} + + +int platform_mask_isfile(MaskHandle data) +{ + return (data->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; +} + + +MaskHandle platform_mask_open(const char* mask) +{ + const char* path = path_getdir(mask); + + MaskHandle data = ALLOCT(struct PlatformMaskData); + data->handle = FindFirstFile(mask, &data->entry); + data->maskPath = (char*)malloc(strlen(path) + 1); + strcpy(data->maskPath, path); + data->isFirst = 1; + return data; +} + + +int platform_mkdir(const char* path) +{ + return CreateDirectory(path, NULL); +} + + +int platform_remove(const char* path) +{ + DeleteFile(path); + return 1; +} + + +int platform_rmdir(const char* path) +{ + WIN32_FIND_DATA data; + HANDLE hDir; + + char* buffer = (char*)malloc(strlen(path) + 6); + strcpy(buffer, path); + strcat(buffer, "\\*.*"); + hDir = FindFirstFile(buffer, &data); + if (hDir == INVALID_HANDLE_VALUE) + return 0; + free(buffer); + + do + { + if (strcmp(data.cFileName, ".") == 0) continue; + if (strcmp(data.cFileName, "..") == 0) continue; + + buffer = (char*)malloc(strlen(path) + strlen(data.cFileName) + 2); + strcpy(buffer, path); + strcat(buffer, "\\"); + strcat(buffer, data.cFileName); + + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + platform_rmdir(buffer); + else + DeleteFile(buffer); + + free(buffer); + } while (FindNextFile(hDir, &data)); + FindClose(hDir); + + RemoveDirectory(path); + return 1; +} + +#endif diff --git a/build/premake/src/Src/premake.c b/build/premake/src/Src/premake.c new file mode 100644 index 0000000000..383f0abee4 --- /dev/null +++ b/build/premake/src/Src/premake.c @@ -0,0 +1,313 @@ +/********************************************************************** + * Premake - premake.c + * The program entry point. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include "premake.h" +#include "arg.h" +#include "os.h" +#include "script.h" +#include "Lua/lua.h" + +#include "gnu.h" +#include "sharpdev.h" +#include "vs6.h" +#include "vs2002.h" +#include "vs2005.h" + +const char* DEFAULT = "premake.lua"; +const char* VERSION = "3.1"; +const char* COPYRIGHT = "Copyright (C) 2002-2006 Jason Perkins and the Premake Project"; +const char* HELP_MSG = "Type 'premake --help' for help"; + +const char* g_filename; +const char* g_cc; +const char* g_dotnet; +int g_verbose; +int g_hasScript; + +static int preprocess(); +static int postprocess(); +static void showUsage(); + +int clean(); + + +/********************************************************************** + * Program entry point + **********************************************************************/ + +int main(int argc, char** argv) +{ + /* If no args are specified... */ + if (argc == 1) + { + puts(HELP_MSG); + return 1; + } + + /* Set defaults */ + os_detect(); + g_filename = DEFAULT; + g_cc = NULL; + g_dotnet = NULL; + g_verbose = 0; + + /* Process any options that will effect script processing */ + arg_set(argc, argv); + if (!preprocess()) + return 1; + + /* chdir() to the directory containing the project script, so that + * relative paths may be used in the script */ + io_chdir(path_getdir(g_filename)); + + /* Now run the script */ + g_hasScript = script_run(g_filename); + if (g_hasScript < 0) + { + puts("** Script failed to run, ending."); + return 1; + } + + /* Process any options that depend on the script output */ + arg_reset(); + if (!postprocess()) + return 1; + + /* All done */ + if (g_hasScript) + script_close(); + prj_close(); + return 0; +} + + +/********************************************************************** + * Command-line processing that is done before the script is run + **********************************************************************/ + +static int preprocess() +{ + const char* flag = arg_getflag(); + while (flag != NULL) + { + if (matches(flag, "--file")) + { + g_filename = arg_getflagarg(); + if (g_filename == NULL) + { + puts("** Usage: --file filename"); + puts(HELP_MSG); + return 1; + } + } + else if (matches(flag, "--os")) + { + const char* os = arg_getflagarg(); + if (os == NULL || !os_set(os)) + { + puts("** Usage: --os osname"); + puts(HELP_MSG); + return 1; + } + } + else if (matches(flag, "--version")) + { + printf("premake (Premake Build Script Generator) %s\n", VERSION); + } + + flag = arg_getflag(); + } + + return 1; +} + + +/********************************************************************** + * Command-line processing that happens after the script has run + **********************************************************************/ + +static int postprocess() +{ + int noScriptWarning = 0; + + const char* flag = arg_getflag(); + while (flag != NULL) + { + if (g_hasScript && !script_export()) + return 0; + + if (matches(flag, "--help")) + { + showUsage(); + } + else if (matches(flag, "--version")) + { + /* ignore quietly */ + } + else if (matches(flag, "--file")) + { + arg_getflagarg(); + } + else + { + if (!g_hasScript) + { + if (!noScriptWarning) + { + puts("** No Premake script found!"); + noScriptWarning = 1; + } + } + else + { + script_docommand(flag); + } + } + + flag = arg_getflag(); + } + + return 1; +} + + +/********************************************************************** + * Default command handler + **********************************************************************/ + +int onCommand(const char* cmd, const char* arg) +{ + if (matches(cmd, "target")) + { + if (matches(arg, "gnu")) + { + return gnu_generate(); + } + else if (matches(arg, "monodev") || matches(arg, "md")) + { + return sharpdev_generate("monodev"); + } + else if (matches(arg, "sharpdev") || matches(arg, "sd")) + { + return sharpdev_generate("sharpdev"); + } + else if (matches(arg, "vs6")) + { + return vs6_generate(); + } + else if (matches(arg, "vs2002") || matches(arg, "vs7")) + { + return vs2002_generate(2002); + } + else if (matches(arg, "vs2003")) + { + return vs2002_generate(2003); + } + else if (matches(arg, "vs2005")) + { + return vs2005_generate(); + } + else + { + printf("** Unrecognized target '%s'\n", arg); + return 0; + } + } + + else if (matches(cmd, "clean")) + { + return clean(); + } + + else if (matches(cmd, "cc")) + { + g_cc = arg; + } + else if (matches(cmd, "dotnet")) + { + g_dotnet = arg; + } + else if (matches(cmd, "verbose")) + { + g_verbose = 1; + } + + return 1; +} + + +/********************************************************************** + * Help message text + **********************************************************************/ + +void showUsage() +{ + int i; + + printf("Premake %s, a build script generator\n", VERSION); + puts(COPYRIGHT); + printf("%s %s\n", LUA_VERSION, LUA_COPYRIGHT); + puts(""); + puts(" --file name Process the specified premake script file"); + puts(""); + puts(" --clean Remove all binaries and build scripts"); + puts(" --verbose Generate verbose makefiles (where applicable)"); + puts(""); + puts(" --cc name Choose a C/C++ compiler, if supported by target; one of:"); + puts(" gcc GNU gcc compiler"); + puts(" dmc Digital Mars C/C+ compiler (experimental)"); + puts(""); + puts(" --dotnet name Choose a .NET compiler set, if supported by target; one of:"); + puts(" ms Microsoft (csc)"); + puts(" mono Mono (mcs)"); + puts(" mono2 Mono .NET 2.0 (gmcs)"); + puts(" pnet Portable.NET (cscc)"); + puts(""); + puts(" --os name Generate files for different operating system; one of:"); + puts(" bsd OpenBSD, NetBSD, or FreeBSD"); + puts(" linux Linux"); + puts(" macosx MacOS X"); + puts(" windows Microsoft Windows"); + puts(""); + puts(" --target name Generate input files for the specified toolset; one of:"); + puts(" gnu GNU Makefile for POSIX, MinGW, and Cygwin"); + puts(" monodev MonoDevelop"); + puts(" sharpdev ICSharpCode SharpDevelop"); + puts(" vs6 Microsoft Visual Studio 6"); + puts(" vs2002 Microsoft Visual Studio 2002"); + puts(" vs2003 Microsoft Visual Studio 2003"); + puts(" vs2005 Microsoft Visual Studio 2005 (includes Express editions)"); + puts(""); + puts(" --help Display this information"); + puts(" --version Display version information"); + puts(""); + + if (project != NULL && prj_get_numoptions() > 0) + { + puts("This premake configuration also supports the following custom options:"); + puts(""); + + for (i = 0; i < prj_get_numoptions(); ++i) + { + prj_select_option(i); + printf(" --%-15s %s\n", prj_get_optname(), prj_get_optdesc()); + } + } + + puts(""); +} diff --git a/build/premake/src/Src/premake.h b/build/premake/src/Src/premake.h new file mode 100644 index 0000000000..56c0fd910f --- /dev/null +++ b/build/premake/src/Src/premake.h @@ -0,0 +1,31 @@ +/********************************************************************** + * Premake - premake.h + * Application globals and functions. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include "io.h" +#include "path.h" +#include "project.h" +#include "util.h" + +extern const char* VERSION; +extern const char* COPYRIGHT; +extern const char* HELP_MSG; + +extern const char* g_cc; +extern const char* g_dotnet; +extern int g_verbose; + +int onCommand(const char* cmd, const char* arg); diff --git a/build/premake/src/Src/premake.lua b/build/premake/src/Src/premake.lua new file mode 100644 index 0000000000..ed9aa7daeb --- /dev/null +++ b/build/premake/src/Src/premake.lua @@ -0,0 +1,42 @@ +package.name = "Premake" +package.language = "c" +package.kind = "exe" +package.target = "premake" + +-- Build Flags + + package.buildflags = + { + "no-64bit-checks", + "static-runtime" + } + + package.config["Release"].buildflags = + { + "no-symbols", + "optimize-size", + "no-frame-pointers" + } + + +-- Defined Symbols + + package.defines = + { + "_CRT_SECURE_NO_DEPRECATE" -- avoid VS2005 warnings + } + + +-- Libraries + + if (OS == "linux") then + package.links = { "m" } + end + + +-- Files + + package.files = + { + matchrecursive("*.h", "*.c") + } diff --git a/build/premake/src/Src/project.c b/build/premake/src/Src/project.c new file mode 100644 index 0000000000..6bcd9c64cc --- /dev/null +++ b/build/premake/src/Src/project.c @@ -0,0 +1,758 @@ +/********************************************************************** + * Premake - project.c + * An interface around the project data. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "os.h" + +Project* project = NULL; + +static Package* my_pkg = NULL; +static PkgConfig* my_cfg = NULL; +static FileConfig* my_fcfg = NULL; +static Option* my_opt = NULL; + +static char buffer[8192]; + + +/************************************************************************ + * Project lifecycle routines + ***********************************************************************/ + +void prj_open() +{ + if (project != NULL) + prj_close(); + project = ALLOCT(Project); +} + + +void prj_close() +{ + int i, j; + + if (project != NULL) + { + for (i = 0; i < prj_get_numpackages(); ++i) + { + Package* package = project->packages[i]; + + for (j = 0; j < prj_get_numconfigs(); ++j) + { + PkgConfig* config = package->configs[j]; + free((void*)config->buildopts); + free((void*)config->defines); + free((void*)config->files); + free((void*)config->flags); + free((void*)config->incpaths); + free((void*)config->libpaths); + free((void*)config->linkopts); + free((void*)config->links); + prj_freelist((void**)config->fileconfigs); + } + + prj_freelist((void**)package->configs); + if (package->data != NULL) + free(package->data); + } + + prj_freelist((void**)project->options); + prj_freelist((void**)project->configs); + prj_freelist((void**)project->packages); + free(project); + project = NULL; + } +} + + +/************************************************************************ + * Locate a package by name + ***********************************************************************/ + +int prj_find_package(const char* name) +{ + int i; + for (i = 0; i < prj_get_numpackages(); ++i) + { + if (matches(name, project->packages[i]->name)) + return i; + } + return -1; +} + + +/************************************************************************ + * Retrieve the active configuration for the given package + ***********************************************************************/ + +PkgConfig* prj_get_config_for(int i) +{ + int j; + for (j = 0; j < prj_get_numconfigs(); ++j) + { + if (my_pkg->configs[j] == my_cfg) + return project->packages[i]->configs[j]; + } + return NULL; +} + + +/************************************************************************ + * Get/set a file build action + ***********************************************************************/ + +const char* prj_get_buildaction() +{ + return my_fcfg->buildaction; +} + +int prj_is_buildaction(const char* action) +{ + return matches(my_fcfg->buildaction, action); +} + +void prj_set_buildaction(const char* action) +{ + my_fcfg->buildaction = action; +} + + +/************************************************************************ + * Get/set generator-specific data + ***********************************************************************/ + +void* prj_get_data() +{ + return prj_get_data_for(my_pkg->index); +} + +void* prj_get_data_for(int i) +{ + return project->packages[i]->data; +} + +void prj_set_data(void* data) +{ + my_pkg->data = data; +} + + +/************************************************************************ + * Return the list of defines for the current object + ***********************************************************************/ + +int prj_get_numdefines() +{ + return prj_getlistsize((void**)prj_get_defines()); +} + +const char** prj_get_defines() +{ + return my_cfg->defines; +} + + +/************************************************************************ + * Query the object directories + ***********************************************************************/ + +const char* prj_get_bindir() +{ + return path_build(my_pkg->path, my_cfg->prjConfig->bindir); +} + +const char* prj_get_bindir_for(int i) +{ + Package* pkg = prj_get_package(i); + PkgConfig* cfg = prj_get_config_for(i); + + strcpy(buffer, path_build(pkg->path, cfg->prjConfig->bindir)); + return buffer; +} + +const char* prj_get_libdir() +{ + return path_build(my_pkg->path, my_cfg->prjConfig->libdir); +} + +const char* prj_get_libdir_for(int i) +{ + Package* pkg = prj_get_package(i); + PkgConfig* cfg = prj_get_config_for(i); + + strcpy(buffer, path_build(pkg->path, cfg->prjConfig->libdir)); + return buffer; +} + +const char* prj_get_objdir() +{ + if (my_cfg->objdir != NULL) + return my_cfg->objdir; + else + return path_combine(my_pkg->objdir, my_cfg->prjConfig->name); +} + +const char* prj_get_pkgobjdir() +{ + if (my_cfg->objdir == NULL) + return my_pkg->objdir; + else + return NULL; +} + +const char* prj_get_outdir() +{ + return prj_get_outdir_for(my_pkg->index); +} + +const char* prj_get_outdir_for(int i) +{ + const char* targetdir; + + Package* pkg = prj_get_package_for(i); + PkgConfig* cfg = prj_get_config_for(i); + + if (matches(cfg->kind, "lib")) + strcpy(buffer, prj_get_libdir_for(i)); + else + strcpy(buffer, prj_get_bindir_for(i)); + + targetdir = path_getdir(cfg->target); + if (strlen(targetdir) > 0) + { + strcat(buffer, "/"); + strcat(buffer, targetdir); + } + + return buffer; +} + +const char* prj_get_nasmpath() +{ + strcpy(buffer, path_build(my_pkg->path, my_cfg->prjConfig->nasmpath)); + return buffer; +} + +const char* prj_get_trimprefix() +{ + return my_cfg->trimprefix; +} + +/************************************************************************ + * Custom target decorations + ***********************************************************************/ + +const char* prj_get_prefix() +{ + return my_cfg->prefix; +} + +const char* prj_get_extension() +{ + return my_cfg->extension; +} + + +/************************************************************************ + * Return the files associated with the active object + ***********************************************************************/ + +const char** prj_get_files() +{ + return my_cfg->files; +} + +int prj_has_file(const char* name) +{ + const char** ptr = my_cfg->files; + while (*ptr != NULL) + { + if (matches(*ptr, name)) + return 1; + ptr++; + } + + return 0; +} + +const char* prj_find_filetype(const char* extension) +{ + const char** ptr = my_cfg->files; + while (*ptr != NULL) + { + if (matches(path_getextension(*ptr), extension)) + return *ptr; + ptr++; + } + + return NULL; +} + + +/************************************************************************ + * Query the build flags + ***********************************************************************/ + +int prj_has_flag(const char* flag) +{ + return prj_has_flag_for(my_pkg->index, flag); +} + +int prj_has_flag_for(int i, const char* flag) +{ + PkgConfig* cfg = prj_get_config_for(i); + const char** ptr = cfg->flags; + while (*ptr != NULL) + { + if (matches(*ptr, flag)) + return 1; + ptr++; + } + + return 0; +} + +int prj_get_numbuildoptions() +{ + return prj_getlistsize((void**)prj_get_buildoptions()); +} + +const char** prj_get_buildoptions() +{ + return my_cfg->buildopts; +} + +int prj_get_numlinkoptions() +{ + return prj_getlistsize((void**)prj_get_linkoptions()); +} + +const char** prj_get_linkoptions() +{ + return my_cfg->linkopts; +} + + +/************************************************************************ + * Query the target kind of the current object + ***********************************************************************/ + +const char* prj_get_kind() +{ + return my_cfg->kind; +} + +int prj_is_kind(const char* kind) +{ + return matches(my_cfg->kind, kind); +} + + +/************************************************************************ + * Return the list of include paths for the current object + ***********************************************************************/ + +int prj_get_numincpaths() +{ + return prj_getlistsize((void**)prj_get_incpaths()); +} + +const char** prj_get_incpaths() +{ + return my_cfg->incpaths; +} + + +/************************************************************************ + * Query the language of the current object + ***********************************************************************/ + +const char* prj_get_language() +{ + return my_pkg->lang; +} + +const char* prj_get_language_for(int i) +{ + return project->packages[i]->lang; +} + +int prj_is_lang(const char* lang) +{ + return matches(my_pkg->lang, lang); +} + + +/************************************************************************ + * Return the list of linker paths for the current object + ***********************************************************************/ + +const char** prj_get_libpaths() +{ + return my_cfg->libpaths; +} + + +/************************************************************************ + * Return the list of links for the current object + ***********************************************************************/ + +int prj_get_numlinks() +{ + return prj_getlistsize((void**)prj_get_links()); +} + +const char** prj_get_links() +{ + return my_cfg->links; +} + + +/************************************************************************ + * Return the name of the active object + ***********************************************************************/ + +const char* prj_get_name() +{ + return project->name; +} + +const char* prj_get_cfgname() +{ + return my_cfg->prjConfig->name; +} + +const char* prj_get_pkgname() +{ + return my_pkg->name; +} + +const char* prj_get_pkgname_for(int i) +{ + return project->packages[i]->name; +} + + +/************************************************************************ + * Return the total number of configurations in the project + ***********************************************************************/ + +int prj_get_numconfigs() +{ + return prj_getlistsize((void**)project->configs); +} + + +/************************************************************************ + * Return the total number of options in the project + ***********************************************************************/ + +int prj_get_numoptions() +{ + return prj_getlistsize((void**)project->options); +} + + +/************************************************************************ + * Return the total number of packages in the project + ***********************************************************************/ + +int prj_get_numpackages() +{ + return prj_getlistsize((void**)project->packages); +} + + + +/************************************************************************ + * Return the name and description of the currently selected option. + ***********************************************************************/ + +const char* prj_get_optdesc() +{ + return my_opt->desc; +} + +const char* prj_get_optname() +{ + return my_opt->flag; +} + + +/************************************************************************ + * Return the active object + ***********************************************************************/ + +Package* prj_get_package() +{ + return my_pkg; +} + +Package* prj_get_package_for(int i) +{ + return project->packages[i]; +} + + +/************************************************************************ + * Return the path to the generated object scripts. + ***********************************************************************/ + +const char* prj_get_path() +{ + return project->path; +} + +const char* prj_get_pkgpath() +{ + return my_pkg->path; +} + +const char* prj_get_pkgpath_for(int i) +{ + return project->packages[i]->path; +} + +const char* prj_get_pkgfilename(const char* extension) +{ + strcpy(buffer, path_build(project->path, my_pkg->path)); + if (strlen(buffer) > 0) + strcat(buffer, "/"); + strcat(buffer, my_pkg->name); + if (extension != NULL) + { + strcat(buffer, "."); + strcat(buffer, extension); + } + return buffer; +} + + +/************************************************************************ + * Return precompiled header filenames, or NULL if none specified + ***********************************************************************/ + +const char* prj_get_pch_header() +{ + return my_cfg->pchHeader; +} + +const char* prj_get_pch_source() +{ + return my_cfg->pchSource; +} + + +/************************************************************************ + * Return the script name for an object. + ***********************************************************************/ + +const char* prj_get_script() +{ + return project->script; +} + +const char* prj_get_pkgscript() +{ + return my_pkg->script; +} + + +/************************************************************************ + * Return the target for the active object + ***********************************************************************/ + +const char* prj_get_target() +{ + return prj_get_target_for(my_pkg->index); +} + +const char* prj_get_target_for(int i) +{ + const char* extension = ""; + + /* Get the active configuration for this target */ + Package* pkg = prj_get_package_for(i); + PkgConfig* cfg = prj_get_config_for(i); + const char* filename = path_getbasename(cfg->target); + + /* Prepopulate the buffer with the output directory */ + prj_get_outdir_for(i); + if (matches(buffer, ".")) + strcpy(buffer, ""); + if (strlen(buffer) > 0) + strcat(buffer, "/"); + + if (cfg->prefix != NULL) + strcat(buffer, cfg->prefix); + + if (matches(pkg->lang, "c#")) + { + strcat(buffer, filename); + if (matches(cfg->kind, "dll")) + extension = "dll"; + else + extension = "exe"; + } + + else if (os_is("windows")) + { + strcat(buffer, filename); + if (matches(cfg->kind, "lib")) + extension = "lib"; + else if (matches(cfg->kind, "dll")) + extension = "dll"; + else + extension = "exe"; + } + + else if (os_is("macosx") && matches(cfg->kind, "dll")) + { + if (prj_has_flag_for(i, "dylib")) + { + strcat(buffer, filename); + extension = "dylib"; + } + else + { + if (cfg->prefix == NULL) + strcat(buffer, "lib"); + strcat(buffer, filename); + extension = "so"; + } + } + + else + { + if (matches(cfg->kind, "lib")) + { + if (cfg->prefix == NULL) + strcat(buffer, "lib"); + strcat(buffer, filename); + extension = "a"; + } + else if (matches(cfg->kind, "dll")) + { + if (cfg->prefix == NULL) + strcat(buffer, "lib"); + strcat(buffer, filename); + extension = "so"; + } + else + { + strcat(buffer, filename); + } + } + + /* Apply the file extension, which can be customized */ + if (cfg->extension != NULL) + extension = cfg->extension; + + if (strlen(extension) > 0) + strcat(buffer, "."); + + strcat(buffer, extension); + + return buffer; +} + + +const char* prj_get_targetname_for(int i) +{ + Package* pkg = prj_get_package_for(i); + PkgConfig* cfg = prj_get_config_for(i); + + strcpy(buffer, path_getname(cfg->target)); + return buffer; +} + + +/************************************************************************ + * Return package URL + ***********************************************************************/ + +const char* prj_get_url() +{ + return my_pkg->url; +} + + +/************************************************************************ + * Activate a project object. + ***********************************************************************/ + +void prj_select_config(int i) +{ + if (my_pkg == NULL) + prj_select_package(0); + my_cfg = my_pkg->configs[i]; +} + +void prj_select_file(const char* name) +{ + int i; + for (i = 0; i < prj_getlistsize((void**)my_cfg->files); ++i) + { + if (matches(my_cfg->files[i], name)) + my_fcfg = my_cfg->fileconfigs[i]; + } +} + +void prj_select_option(i) +{ + my_opt = project->options[i]; +} + +void prj_select_package(int i) +{ + my_pkg = project->packages[i]; +} + + +/************************************************************************ + * List management routines + ***********************************************************************/ + +void** prj_newlist(int len) +{ + void** list = (void**)malloc(sizeof(void*) * (len + 1)); + list[len] = NULL; + return list; +} + + +void prj_freelist(void** list) +{ + int i = 0; + while (list[i] != NULL) + free(list[i++]); + free(list); +} + + +int prj_getlistsize(void** list) +{ + int count = 0; + void** ptr = list; + while (*ptr != NULL) + { + ptr++; + count++; + } + return count; +} diff --git a/build/premake/src/Src/project.h b/build/premake/src/Src/project.h new file mode 100644 index 0000000000..f2afaf0a71 --- /dev/null +++ b/build/premake/src/Src/project.h @@ -0,0 +1,161 @@ +/********************************************************************** + * Premake - project.h + * An interface around the project data. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +typedef struct tagOption +{ + const char* flag; + const char* desc; +} Option; + + +typedef struct tagPrjConfig +{ + const char* name; + const char* bindir; + const char* libdir; + const char* nasmpath; +} PrjConfig; + +typedef struct tagFileConfig +{ + const char* buildaction; +} FileConfig; + +typedef struct tagPkgConfig +{ + PrjConfig* prjConfig; + const char** buildopts; + const char** defines; + const char* extension; + const char** files; + const char** flags; + const char** incpaths; + const char** libpaths; + const char** linkopts; + const char** links; + const char* objdir; + const char* prefix; + const char* target; + const char* kind; + const char* pchHeader; + const char* pchSource; + const char* trimprefix; + FileConfig** fileconfigs; +} PkgConfig; + +typedef struct tagPackage +{ + int index; + const char* name; + const char* path; + const char* script; + const char* lang; + const char* kind; + const char* objdir; + const char* url; + PkgConfig** configs; + void* data; +} Package; + +typedef struct tagProject +{ + const char* name; + const char* path; + const char* script; + Option** options; + PrjConfig** configs; + Package** packages; +} Project; + +extern Project* project; + + +void prj_open(); +void prj_close(); + +const char* prj_find_filetype(const char* extension); +int prj_find_package(const char* name); +const char* prj_get_bindir(); +const char* prj_get_buildaction(); +const char** prj_get_buildoptions(); +const char* prj_get_cfgname(); +PkgConfig* prj_get_config_for(int i); +void* prj_get_data(); +void* prj_get_data_for(int i); +const char** prj_get_defines(); +const char* prj_get_extension(); +const char** prj_get_files(); +const char* prj_get_kind(); +const char** prj_get_incpaths(); +const char* prj_get_language(); +const char* prj_get_language_for(int i); +const char* prj_get_libdir(); +const char* prj_get_libdir_for(int i); +const char** prj_get_libpaths(); +const char** prj_get_linkoptions(); +const char** prj_get_links(); +const char* prj_get_objdir(); +const char* prj_get_prefix(); +const char* prj_get_name(); +const char* prj_get_nasmpath(); +int prj_get_numbuildoptions(); +int prj_get_numconfigs(); +int prj_get_numdefines(); +int prj_get_numincpaths(); +int prj_get_numlinkoptions(); +int prj_get_numlinks(); +int prj_get_numoptions(); +int prj_get_numpackages(); +const char* prj_get_optdesc(); +const char* prj_get_optname(); +const char* prj_get_outdir(); +const char* prj_get_outdir_for(int i); +Package* prj_get_package(); +Package* prj_get_package_for(); +const char* prj_get_path(); +const char* prj_get_pch_header(); +const char* prj_get_pch_source(); +const char* prj_get_pkgfilename(const char* extension); +const char* prj_get_pkgname(); +const char* prj_get_pkgname_for(); +const char* prj_get_pkgobjdir(); +const char* prj_get_pkgpath(); +const char* prj_get_pkgpath_for(int i); +const char* prj_get_pkgscript(); +const char* prj_get_script(); +const char* prj_get_target(); +const char* prj_get_target_for(int i); +const char* prj_get_targetname_for(int i); +const char* prj_get_trimprefix(); +const char* prj_get_url(); +int prj_has_file(const char* name); +int prj_has_flag(const char* flag); +int prj_has_flag_for(int i, const char* flag); +int prj_is_buildaction(const char* action); +int prj_is_kind(const char* kind); +int prj_is_lang(const char* lang); +void prj_select_config(int i); +void prj_select_file(const char* name); +void prj_select_option(int i); +void prj_select_package(int i); +void prj_set_buildaction(const char* action); +void prj_set_data(void* data); + +void** prj_newlist(int len); +void prj_freelist(void** list); +int prj_getlistsize(void** list); + diff --git a/build/premake/src/Src/script.c b/build/premake/src/Src/script.c new file mode 100644 index 0000000000..a936132ddf --- /dev/null +++ b/build/premake/src/Src/script.c @@ -0,0 +1,1377 @@ +/********************************************************************** + * Premake - script.c + * Interface to the Lua scripting engine. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "script.h" +#include "arg.h" +#include "os.h" +#include "Lua/lua.h" +#include "Lua/lualib.h" +#include "Lua/lauxlib.h" +#include "Lua/ldebug.h" + +static lua_State* L; +static const char* currentScript = NULL; + + +static int tbl_get(int from, const char* name); +static int tbl_geti(int from, int i); +static int tbl_getlen(int tbl); +static int tbl_getlen_deep(int tbl); +static const char* tbl_getstring(int from, const char* name); +static const char* tbl_getstringi(int from, int i); + +static int lf_addoption(lua_State* L); +static int lf_alert(lua_State* L); +static int lf_appendfile(lua_State* L); +static int lf_chdir(lua_State* L); +static int lf_copyfile(lua_State* L); +static int lf_docommand(lua_State* L); +static int lf_dopackage(lua_State* L); +static int lf_fileexists(lua_State* L); +static int lf_findlib(lua_State* L); +static int lf_getbasename(lua_State* L); +static int lf_getconfigs(lua_State* L); +static int lf_getcwd(lua_State* L); +static int lf_getdir(lua_State* L); +static int lf_getextension(lua_State* L); +static int lf_getglobal(lua_State* L); +static int lf_getname(lua_State* L); +static int lf_matchfiles(lua_State* L); +static int lf_matchrecursive(lua_State* L); +static int lf_newfileconfig(lua_State* L); +static int lf_newpackage(lua_State* L); +static int lf_panic(lua_State* L); +static int lf_rmdir(lua_State* L); +static int lf_setconfigs(lua_State* L); + +static void buildOptionsTable(); +static void buildNewProject(); + + +/********************************************************************** + * Initialize the Lua environment + **********************************************************************/ + +int script_init() +{ + /* Create a script environment and install the standard libraries */ + L = lua_open(); + luaopen_base(L); + luaopen_table(L); + luaopen_io(L); + luaopen_string(L); + luaopen_math(L); + luaopen_loadlib(L); + + lua_atpanic(L, lf_panic); + + /* Register my extensions to the Lua environment */ + lua_register(L, "addoption", lf_addoption); + lua_register(L, "_ALERT", lf_alert); + lua_register(L, "copyfile", lf_copyfile); + lua_register(L, "docommand", lf_docommand); + lua_register(L, "dopackage", lf_dopackage); + lua_register(L, "fileexists", lf_fileexists); + lua_register(L, "findlib", lf_findlib); + lua_register(L, "matchfiles", lf_matchfiles); + lua_register(L, "matchrecursive", lf_matchrecursive); + lua_register(L, "newpackage", lf_newpackage); + + /* Add some extensions to the built-in "os" table */ + lua_getglobal(L, "os"); + + lua_pushstring(L, "appendfile"); + lua_pushcfunction(L, lf_appendfile); + lua_settable(L, -3); + + lua_pushstring(L, "chdir"); + lua_pushcfunction(L, lf_chdir); + lua_settable(L, -3); + + lua_pushstring(L, "copyfile"); + lua_pushcfunction(L, lf_copyfile); + lua_settable(L, -3); + + lua_pushstring(L, "fileexists"); + lua_pushcfunction(L, lf_fileexists); + lua_settable(L, -3); + + lua_pushstring(L, "findlib"); + lua_pushcfunction(L, lf_findlib); + lua_settable(L, -3); + + lua_pushstring(L, "getcwd"); + lua_pushcfunction(L, lf_getcwd); + lua_settable(L, -3); + + lua_pushstring(L, "rmdir"); + lua_pushcfunction(L, lf_rmdir); + lua_settable(L, -3); + + lua_pop(L, 1); + + /* Add path handling functions */ + lua_newtable(L); + + lua_pushstring(L, "getbasename"); + lua_pushcfunction(L, lf_getbasename); + lua_settable(L, -3); + + lua_pushstring(L, "getdir"); + lua_pushcfunction(L, lf_getdir); + lua_settable(L, -3); + + lua_pushstring(L, "getextension"); + lua_pushcfunction(L, lf_getextension); + lua_settable(L, -3); + + lua_pushstring(L, "getname"); + lua_pushcfunction(L, lf_getname); + lua_settable(L, -3); + + lua_setglobal(L, "path"); + + /* Register some commonly used Lua4 functions */ + lua_register(L, "rmdir", lf_rmdir); + + lua_getglobal(L, "table"); + lua_pushstring(L, "insert"); + lua_gettable(L, -2); + lua_setglobal(L, "tinsert"); + lua_pop(L, 1); + + lua_getglobal(L, "os"); + lua_pushstring(L, "remove"); + lua_gettable(L, -2); + lua_setglobal(L, "remove"); + lua_pop(L, 1); + + /* Set the global OS identifiers */ + lua_pushstring(L, os_get()); + lua_setglobal(L, "OS"); + + lua_pushnumber(L, 1); + lua_setglobal(L, os_get()); + + /* Create a list of option descriptions for addoption() */ + lua_getregistry(L); + lua_pushstring(L, "options"); + lua_newtable(L); + lua_settable(L, -3); + lua_pop(L, 1); + + /* Create and populate a global "options" table */ + buildOptionsTable(); + + /* Create an empty list of packages */ + lua_getregistry(L); + lua_pushstring(L, "packages"); + lua_newtable(L); + lua_settable(L, -3); + lua_pop(L, 1); + + /* Create a default project object */ + buildNewProject(); + + /* Set hook to intercept creation of globals, used to create packages */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_newtable(L); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, lf_getglobal); + lua_settable(L, -3); + lua_setmetatable(L, -2); + lua_pop(L, 1); + + return 1; +} + + +/********************************************************************** + * Execute the specified premake script. Contains some logic for + * locating the script file if an exact match isn't found + **********************************************************************/ + +int script_run(const char* filename) +{ + char scriptname[8192]; + int result; + + strcpy(scriptname, filename); + if (!io_fileexists(scriptname)) + { + strcat(scriptname, ".lua"); + } + if (!io_fileexists(scriptname)) + { + return 0; + } + + currentScript = scriptname; + if (!script_init()) + return -1; + + result = lua_dofile(L, scriptname); + return (result == 0) ? 1 : -1; +} + + +/********************************************************************** + * After the script has run, these functions pull the project data + * out into local objects + **********************************************************************/ + +static int export_list(int parent, int object, const char* name, const char*** list) +{ + int i; + + int parArr = tbl_get(parent, name); + int parLen = tbl_getlen_deep(parArr); + int objArr = tbl_get(object, name); + int objLen = tbl_getlen_deep(objArr); + + *list = (const char**)prj_newlist(parLen + objLen); + + for (i = 0; i < parLen; ++i) + (*list)[i] = tbl_getstringi(parArr, i + 1); + + for (i = 0; i < objLen; ++i) + (*list)[parLen + i] = tbl_getstringi(objArr, i + 1); + + return (parLen + objLen); +} + +static const char* export_value(int parent, int object, const char* name) +{ + const char* value; + value = tbl_getstring(object, name); + if (value == NULL) + value = tbl_getstring(parent, name); + return value; +} + +static const char** export_files(int tbl, int obj) +{ + const char** files; + const char** excludes; + const char** result; + int numFiles, numExcludes; + int i, j, k; + + export_list(tbl, obj, "files", &files); + export_list(tbl, obj, "excludes", &excludes); + + numFiles = prj_getlistsize((void**)files); + numExcludes = prj_getlistsize((void**)excludes); + + result = (const char**)prj_newlist(numFiles); + + k = 0; + for (i = 0; i < numFiles; ++i) + { + int exclude = 0; + for (j = 0; j < numExcludes; ++j) + { + if (matches(files[i], excludes[j])) + exclude = 1; + } + + if (!exclude) + result[k++] = files[i]; + } + + free((void*)files); + free((void*)excludes); + + result[k] = NULL; + return result; +} + +static int export_fileconfig(PkgConfig* config, int arr) +{ + int obj, count, i; + + count = prj_getlistsize((void**)config->files); + config->fileconfigs = (FileConfig**)prj_newlist(count); + for (i = 0; i < count; ++i) + { + FileConfig* fconfig = ALLOCT(FileConfig); + config->fileconfigs[i] = fconfig; + + obj = tbl_get(arr, config->files[i]); + if (obj > 0) + { + fconfig->buildaction = tbl_getstring(obj, "buildaction"); + } + else + { + fconfig->buildaction = NULL; + } + } + + return 1; +} + +static int export_pkgconfig(Package* package, int tbl) +{ + int arr, obj; + int len, i; + + arr = tbl_get(tbl, "config"); + len = tbl_getlen(arr); + package->configs = (PkgConfig**)prj_newlist(len); + for (i = 0; i < len; ++i) + { + PkgConfig* config = ALLOCT(PkgConfig); + package->configs[i] = config; + config->prjConfig = project->configs[i]; + + obj = tbl_geti(arr, i + 1); + config->objdir = tbl_getstring(obj, "objdir"); + + config->extension = export_value(tbl, obj, "targetextension"); + config->prefix = export_value(tbl, obj, "targetprefix"); + config->target = export_value(tbl, obj, "target"); + config->kind = export_value(tbl, obj, "kind"); + config->pchHeader = export_value(tbl, obj, "pchheader"); + config->pchSource = export_value(tbl, obj, "pchsource"); + config->trimprefix = export_value(tbl, obj, "trimprefix"); + + /* Assign a default target, if none specified */ + if (config->target == NULL) + config->target = package->name; + + /* Pull out the value lists */ + export_list(tbl, obj, "buildflags", &config->flags); + export_list(tbl, obj, "buildoptions", &config->buildopts); + export_list(tbl, obj, "defines", &config->defines); + export_list(tbl, obj, "includepaths", &config->incpaths); + export_list(tbl, obj, "libpaths", &config->libpaths); + export_list(tbl, obj, "linkoptions", &config->linkopts); + export_list(tbl, obj, "links", &config->links); + + /* Build the file list */ + config->files = export_files(tbl, obj); + + /* Build a list of file configurations */ + export_fileconfig(config, arr); + } + + return 1; +} + + +int script_export() +{ + int tbl, arr, obj; + int len, i; + + prj_open(); + + /* Copy out the list of available options */ + tbl = tbl_get(LUA_REGISTRYINDEX, "options"); + len = tbl_getlen(tbl); + project->options = (Option**)prj_newlist(len); + for (i = 0; i < len; ++i) + { + Option* option = ALLOCT(Option); + project->options[i] = option; + + obj = tbl_geti(tbl, i + 1); + option->flag = tbl_getstringi(obj, 1); + option->desc = tbl_getstringi(obj, 2); + } + + /* Copy out the project settings */ + tbl = tbl_get(LUA_GLOBALSINDEX, "project"); + project->name = tbl_getstring(tbl, "name"); + project->path = tbl_getstring(tbl, "path"); + project->script = tbl_getstring(tbl, "script"); + + /* Copy out the project configurations */ + arr = tbl_get(tbl, "config"); + len = tbl_getlen(arr); + project->configs = (PrjConfig**)prj_newlist(len); + for (i = 0; i < len; ++i) + { + PrjConfig* config = ALLOCT(PrjConfig); + project->configs[i] = config; + + obj = tbl_geti(arr, i + 1); + config->name = tbl_getstring(obj, "name"); + config->bindir = export_value(tbl, obj, "bindir"); + config->libdir = export_value(tbl, obj, "libdir"); + config->nasmpath = export_value(tbl, obj, "nasmpath"); + } + + /* Copy out the packages */ + tbl = tbl_get(LUA_REGISTRYINDEX, "packages"); + len = tbl_getlen(tbl); + project->packages = (Package**)prj_newlist(len); + for (i = 0; i < len; ++i) + { + Package* package = ALLOCT(Package); + package->index = i; + project->packages[i] = package; + + obj = tbl_geti(tbl, i + 1); + package->name = tbl_getstring(obj, "name"); + package->path = tbl_getstring(obj, "path"); + package->script = tbl_getstring(obj, "script"); + package->lang = tbl_getstring(obj, "language"); + package->kind = tbl_getstring(obj, "kind"); + package->objdir = tbl_getstring(obj, "objdir"); + package->url = tbl_getstring(obj, "url"); + package->data = NULL; + + export_pkgconfig(package, obj); + } + + return 1; +} + + +/********************************************************************** + * Callback for commands pulled from the program arguments + **********************************************************************/ + +int script_docommand(const char* cmd) +{ + char buffer[512]; + const char* arg; + + /* Trim off the leading '--' */ + if (strncmp(cmd, "--", 2) == 0) + cmd += 2; + + /* Look for a handler */ + strcpy(buffer, "do"); + strcat(buffer, cmd); + lua_getglobal(L, buffer); + if (!lua_isfunction(L, -1)) + { + /* Fall back to the default handler */ + lua_getglobal(L, "docommand"); + if (!lua_isfunction(L, -1)) + { + lua_pop(L, 1); + return 0; + } + } + + /* Push the command and arguments onto the stack */ + lua_pushstring(L, cmd); + arg = arg_getflagarg(); + if (arg != NULL) + lua_pushstring(L, arg); + else + lua_pushnil(L); + + lua_call(L, 2, 0); + return 1; +} + + +int script_close() +{ + lua_close(L); + return 1; +} + + + +/********************************************************************** + * These function assist with setup of the script environment + **********************************************************************/ + +static void buildOptionsTable() +{ + const char* flag; + const char* arg; + + lua_newtable(L); + + arg_reset(); + flag = arg_getflag(); + while (flag != NULL) + { + if (strncmp(flag, "--", 2) == 0) + flag += 2; + + lua_pushstring(L, flag); + + /* If the flag has an argument, push that too */ + arg = arg_getflagarg(); + if (arg != NULL) + lua_pushstring(L, arg); + else + lua_pushboolean(L, 1); + + lua_settable(L, -3); + flag = arg_getflag(); + } + + lua_setglobal(L, "options"); +} + +static void buildNewProject() +{ + lua_newtable(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, "MyProject"); + lua_settable(L, -3); + + lua_pushstring(L, "path"); + lua_pushstring(L, path_getdir(currentScript)); + lua_settable(L, -3); + + lua_pushstring(L, "bindir"); + lua_pushstring(L, ""); + lua_settable(L, -3); + + lua_pushstring(L, "libdir"); + lua_pushstring(L, ""); + lua_settable(L, -3); + + /* Hook "index" metamethod so I can tell when the config list changes */ + lua_newtable(L); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, lf_setconfigs); + lua_settable(L, -3); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, lf_getconfigs); + lua_settable(L, -3); + lua_setmetatable(L, -2); + + /* Set default values */ + lua_pushstring(L, "script"); + lua_pushstring(L, path_getname(currentScript)); + lua_settable(L, -3); + + lua_pushstring(L, "configs"); + lua_newtable(L); + lua_pushstring(L, "Debug"); + lua_rawseti(L, -2, 1); + lua_pushstring(L, "Release"); + lua_rawseti(L, -2, 2); + lua_settable(L, -3); + + lua_setglobal(L, "project"); +} + +static void buildNewConfig(const char* name) +{ + /* Store the config name */ + if (name != NULL) + { + lua_pushstring(L, "name"); + lua_pushstring(L, name); + lua_settable(L, -3); + } + + /* Set defaults */ + lua_pushstring(L, "buildflags"); + lua_newtable(L); + if (matches(name, "Release")) + { + lua_pushstring(L, "no-symbols"); + lua_rawseti(L, -2, 1); + lua_pushstring(L, "optimize"); + lua_rawseti(L, -2, 2); + } + lua_settable(L, -3); + + lua_pushstring(L, "buildoptions"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "defines"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "files"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "excludes"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "includepaths"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "libpaths"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "linkoptions"); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushstring(L, "links"); + lua_newtable(L); + lua_settable(L, -3); +} + + + +/********************************************************************** + * These function help get data out of the Lua tables + **********************************************************************/ + +static int tbl_matchkey(const char* name, int index) +{ + int result, i; + + if (lua_isnumber(L, index)) + return 0; + + if (!lua_istable(L, index)) + { + const char* key = lua_tostring(L, index); + return matches(key, name); + } + + /* If key is a table, scan for value */ + for (i = 1; i <= luaL_getn(L, index); ++i) + { + lua_rawgeti(L, index, i); + result = tbl_matchkey(name, -1); + lua_pop(L, 1); + if (result) + return 1; + } + + return 0; +} + +static int tbl_get(int from, const char* name) +{ + int ref; + + /* Retrieve the `from` object */ + if (from == LUA_REGISTRYINDEX || from == LUA_GLOBALSINDEX) + { + lua_pushvalue(L, from); + } + else + { + lua_getref(L, from); + } + + /* Do a deep key search for the requested object */ + lua_pushnil(L); + while (lua_next(L, -2)) + { + if (tbl_matchkey(name, -2)) + { + /* Validate result */ + if (!lua_istable(L, -1)) + { + char msg[512]; + sprintf(msg, "'%s' should be a table.\nPlace value between brackets like: { values }", name); + lua_pushstring(L, msg); + lua_error(L); + } + + /* Reference and return */ + ref = lua_ref(L, -1); + lua_pop(L, 2); + return ref; + } + + lua_pop(L, 1); + } + + /* Not found */ + lua_pop(L, 1); + return 0; + +/* + lua_pushstring(L, name); + lua_gettable(L, -2); + + if (lua_isnil(L, -1)) + return 0; + + if (!lua_istable(L, -1)) + { + char msg[512]; + sprintf(msg, "'%s' should be a table.\nPlace value between brackets like: { values }", name); + lua_pushstring(L, msg); + lua_error(L); + } + + ref = lua_ref(L, -1); + lua_pop(L, 1); + + return ref; +*/ +} + + +static int tbl_geti(int from, int i) +{ + int ref; + + lua_getref(L, from); + lua_rawgeti(L, -1, i); + + ref = lua_ref(L, -1); + lua_pop(L, 1); + return ref; +} + + +static int tbl_getlen(int tbl) +{ + int size; + lua_getref(L, tbl); + size = luaL_getn(L, -1); + lua_pop(L, 1); + return size; +} + + +static int tbl_getlen_deep(int tbl) +{ + int size, i; + lua_getref(L, tbl); + + size = 0; + for (i = 1; i <= luaL_getn(L, -1); ++i) + { + lua_rawgeti(L, -1, i); + if (lua_istable(L, -1)) + { + size += tbl_getlen_deep(lua_ref(L, -1)); + } + else + { + lua_pop(L, 1); + size++; + } + } + + lua_pop(L, 1); + return size; +} + + +static const char* tbl_getstring(int from, const char* name) +{ + const char* str; + + lua_getref(L, from); + lua_pushstring(L, name); + lua_gettable(L, -2); + str = lua_tostring(L, -1); + lua_pop(L, 2); + + return str; +} + + +static const char* tbl_getstringi_worker(int arr, int* index) +{ + int i; + const char* result = NULL; + + lua_getref(L, arr); + for (i = 1; i <= luaL_getn(L, -1) && *index > 0; ++i) + { + lua_rawgeti(L, -1, i); + if (lua_istable(L, -1)) + { + int ref = lua_ref(L, -1); + result = tbl_getstringi_worker(ref, index); + } + else if (*index == 1) + { + result = lua_tostring(L, -1); + lua_pop(L, 1); + (*index)--; + } + else + { + lua_pop(L, 1); + (*index)--; + } + } + + lua_pop(L, 1); + return result; +} + +static const char* tbl_getstringi(int from, int i) +{ + int index = i; + const char* result = tbl_getstringi_worker(from, &index); + return result; +} + + +/********************************************************************** + * These are new functions for the Lua environment + **********************************************************************/ + +static int lf_addoption(lua_State* L) +{ + const char* name = luaL_checkstring(L, 1); + const char* desc = luaL_checkstring(L, 2); + + /* Retrieve the options list from the registry */ + lua_getregistry(L); + lua_pushstring(L, "options"); + lua_gettable(L, -2); + + /* Create a new table for this new option */ + lua_newtable(L); + lua_pushstring(L, name); + lua_rawseti(L, -2, 1); + lua_pushstring(L, desc); + lua_rawseti(L, -2, 2); + + /* Add the option to the end of the registry list */ + lua_rawseti(L, -2, luaL_getn(L, -2) + 1); + + lua_pop(L, 2); + return 0; +} + + + +static int lf_alert(lua_State* L) +{ + /* Get the error message */ + const char* msg = lua_tostring(L, -1); + + /* Swap out the file name so I can see the whole path */ + msg = strchr(msg, ':'); + + printf("%s%s\n", currentScript, msg); + exit(1); +} + + +static int lf_appendfile(lua_State* L) +{ + FILE* fSrc; + FILE* fDst; + int count; + + const char* src = luaL_checkstring(L, 1); + const char* dst = luaL_checkstring(L, 2); + + fSrc = fopen(src, "rb"); + if (fSrc == NULL) + luaL_error(L, "Unable to open file for reading '%s'\n", src); + + fDst = fopen(dst, "ab"); + if (fDst == NULL) + luaL_error(L, "Unable to open file for appending '%s'\n", dst); + + count = fread(g_buffer, 1, 8192, fSrc); + while (count > 0) + { + fwrite(g_buffer, 1, count, fDst); + count = fread(g_buffer, 1, 8192, fSrc); + } + + fclose(fSrc); + fclose(fDst); + return 0; +} + + +static int lf_docommand(lua_State* L) +{ + const char* cmd = luaL_checkstring(L, 1); + const char* arg = (!lua_isnil(L,2)) ? luaL_checkstring(L, 2) : NULL; + if (!onCommand(cmd, arg)) + exit(1); + return 0; +} + + +static int lf_chdir(lua_State* L) +{ + const char* path = luaL_checkstring(L, 2); + if (io_chdir(path)) + lua_pushnumber(L, 1); + else + lua_pushnil(L); + return 1; +} + + +static int lf_copyfile(lua_State* L) +{ + const char* src = luaL_checkstring(L, 1); + const char* dest = luaL_checkstring(L, 2); + if (io_copyfile(src, dest)) + lua_pushnumber(L, 1); + else + lua_pushnil(L); + return 1; +} + + +static int lf_dopackage(lua_State* L) +{ + const char* oldScript; + char oldcwd[8192]; + char filename[8192]; + int result; + + /* Clear the current global so included script can create a new one */ + lua_pushnil(L); + lua_setglobal(L, "package"); + + /* Remember the current state of things so I can restore after script runs */ + oldScript = currentScript; + strcpy(oldcwd, io_getcwd()); + + /* Try to locate the script file */ + strcpy(filename, lua_tostring(L, 1)); + if (!io_fileexists(filename)) + { + strcpy(filename, path_join("", lua_tostring(L, 1), "lua")); + } + if (!io_fileexists(filename)) + { + strcpy(filename, path_join(lua_tostring(L, 1), "premake.lua", "")); + } + + if (!io_fileexists(filename)) + { + lua_pushstring(L, "Unable to open package '"); + lua_pushvalue(L, 1); + lua_pushstring(L, "'"); + lua_concat(L, 3); + lua_error(L); + } + + currentScript = filename; + io_chdir(path_getdir(filename)); + + result = lua_dofile(L, path_getname(filename)); + + /* Restore the previous state */ + currentScript = oldScript; + io_chdir(oldcwd); + + return 0; +} + + +static int lf_fileexists(lua_State* L) +{ + const char* path = luaL_check_string(L, 1); + int result = io_fileexists(path); + lua_pushboolean(L, result); + return 1; +} + + +static int lf_findlib(lua_State* L) +{ + const char* libname = luaL_check_string(L, 1); + const char* result = io_findlib(libname); + if (result) + lua_pushstring(L, result); + else + lua_pushnil(L); + return 1; +} + + +static int lf_getbasename(lua_State* L) +{ + const char* path = luaL_checkstring(L, 1); + const char* result = path_getbasename(path); + lua_pushstring(L, result); + return 1; +} + + +static int lf_getcwd(lua_State* L) +{ + const char* cwd = io_getcwd(); + lua_pushstring(L, cwd); + return 1; +} + + +static int lf_getdir(lua_State* L) +{ + const char* path = luaL_checkstring(L, 1); + const char* result = path_getdir(path); + lua_pushstring(L, result); + return 1; +} + + +static int lf_getextension(lua_State* L) +{ + const char* path = luaL_checkstring(L, 1); + const char* result = path_getextension(path); + lua_pushstring(L, result); + return 1; +} + + +static int lf_getglobal(lua_State* L) +{ + const char* name = luaL_checkstring(L, 2); + if (matches(name, "package")) + { + lf_newpackage(L); + lua_pushvalue(L, -1); + lua_setglobal(L, "package"); + return 1; + } + return 0; +} + + +static int lf_getname(lua_State* L) +{ + const char* path = luaL_checkstring(L, 1); + const char* result = path_getname(path); + lua_pushstring(L, result); + return 1; +} + + +static int debugging = 0; + +static void doFileScan(lua_State* L, char* path, int recursive) +{ + MaskHandle handle; + + if (debugging) puts(path); + + handle = io_mask_open(path); + while (io_mask_getnext(handle)) + { + if (io_mask_isfile(handle)) + { + const char* name = io_mask_getname(handle); + lua_pushstring(L, name); + lua_rawseti(L, -2, luaL_getn(L, -2) + 1); + } + } + io_mask_close(handle); + + /* If recursive, scan subdirectories */ + if (recursive) + { + char mask[128]; + int len; + + /* Split the mask from the path */ + strcpy(mask, path_getname(path)); + strcpy(path, path_getdir(path)); + + /* Scan for subdirs */ + len = strlen(path); + handle = io_mask_open(path_combine(path, "*")); + while (io_mask_getnext(handle)) + { + if (!io_mask_isfile(handle)) + { + const char* name = io_mask_getname(handle); + if (!matches(name, ".") && !matches(name, "..") && !endsWith(name, "/.") && !endsWith(name, "/..")) + { + strcpy(path, path_combine(name, mask)); + doFileScan(L, path, recursive); + path[len] = '\0'; + } + } + } + io_mask_close(handle); + } +} + +static int doFileMatching(lua_State* L, int recursive) +{ + char path[8192]; + const char* pkgPath; + const char* filename; + int pathlen, i; + + /* Get the current package path */ + lua_getglobal(L, "package"); + lua_pushstring(L, "path"); + lua_gettable(L, -2); + pkgPath = lua_tostring(L, -1); + lua_pop(L, 2); + + /* If path is same as current, I can ignore it */ + if (path_compare(path_getdir(currentScript), pkgPath)) + pkgPath = ""; + + /* Create a table to hold the results */ + lua_newtable(L); + + /* Scan each mask */ + for (i = 1; i < lua_gettop(L); ++i) + { + const char* mask = luaL_checkstring(L, i); + const char* maskWithPath = path_combine(pkgPath, mask); + strcpy(path, maskWithPath); + doFileScan(L, path, recursive); + } + + /* Remove the base package path from all files */ + pathlen = strlen(pkgPath); + if (pathlen > 0) pathlen++; + for (i = 1; i <= luaL_getn(L, -1); ++i) + { + lua_rawgeti(L, -1, i); + filename = lua_tostring(L, -1); + lua_pushstring(L, filename + pathlen); + lua_rawseti(L, -3, i); + lua_pop(L, 1); + } + + debugging = 0; + return 1; +} + + +static int lf_matchfiles(lua_State* L) +{ + return doFileMatching(L, 0); +} + + +static int lf_matchrecursive(lua_State* L) +{ + return doFileMatching(L, 1); +} + + +static int lf_newfileconfig(lua_State* L) +{ + lua_newtable(L); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, -3); + lua_pop(L, 1); + return 1; +} + + +static int lf_newpackage(lua_State* L) +{ + int count, i; + + lua_newtable(L); + + /* Add this package to the master list in the registry */ + lua_getregistry(L); + lua_pushstring(L, "packages"); + lua_gettable(L, -2); + count = luaL_getn(L, -1); + + lua_pushvalue(L, -3); + lua_rawseti(L, -2, count + 1); + + lua_pop(L, 2); + + /* Set default values */ + if (count == 0) + { + lua_getglobal(L, "project"); + lua_pushstring(L, "name"); + lua_pushstring(L, "name"); + lua_gettable(L, -3); + lua_settable(L, -4); + lua_pop(L, 1); + } + else + { + lua_pushstring(L, "name"); + lua_pushstring(L, "Package"); + lua_pushnumber(L, count); + lua_concat(L, 2); + lua_settable(L, -3); + } + + lua_pushstring(L, "script"); + lua_pushstring(L, currentScript); + lua_settable(L, -3); + + lua_pushstring(L, "path"); + lua_pushstring(L, path_getdir(currentScript)); + lua_settable(L, -3); + + lua_pushstring(L, "language"); + lua_pushstring(L, "c++"); + lua_settable(L, -3); + + lua_pushstring(L, "kind"); + lua_pushstring(L, "exe"); + lua_settable(L, -3); + + lua_pushstring(L, "objdir"); + lua_pushstring(L, "obj"); + lua_settable(L, -3); + + buildNewConfig(NULL); + + /* Build list of configurations matching what is in the project, and + * which can be indexed by name or number */ + lua_pushstring(L, "config"); + lua_newtable(L); + + lua_getglobal(L, "project"); + lua_pushstring(L, "configs"); + lua_gettable(L, -2); + count = luaL_getn(L, -1); + + for (i = 1; i <= count; ++i) + { + lua_rawgeti(L, -1, i); + + lua_newtable(L); + + buildNewConfig(lua_tostring(L, -2)); + + lua_pushvalue(L, -1); + lua_rawseti(L, -6, i); + lua_settable(L, -5); + } + + lua_pop(L, 2); + + /* Hook the index metamethod so I can dynamically add file configs */ + lua_newtable(L); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, lf_newfileconfig); + lua_settable(L, -3); + lua_setmetatable(L, -2); + + /* Set the 'package' global to point to it */ + lua_pushvalue(L, -1); + lua_setglobal(L, "package"); + + lua_settable(L, -3); + + return 1; +} + + +static int lf_panic(lua_State* L) +{ + lua_Debug ar; + int stack; + + int top = lua_gettop(L); + const char* msg = lua_tostring(L, top); + printf("\n** Error: %s\n", msg); + + for (stack = 0; lua_getstack(L, stack, &ar); ++stack) + { + lua_getinfo(L, "S1", &ar); + if (ar.source && ar.currentline > 0) + { + printf("<%.70s: line %d>\n\n", ar.short_src, ar.currentline); + break; + } + } + + return 0; +} + +static int lf_rmdir(lua_State* L) +{ + const char* dir = luaL_check_string(L, 1); + io_rmdir(".", dir); + return 0; +} + + +static int lf_getconfigs(lua_State* L) +{ + const char* name = luaL_checkstring(L, 2); + if (matches(name, "configs")) + lua_pushstring(L, "__configs"); + + lua_rawget(L, 1); + return 1; +} + + +static int lf_setconfigs(lua_State* L) +{ + int i; + + const char* name = luaL_checkstring(L, 2); + if (matches(name, "configs")) + { + if (!lua_istable(L, 3)) + { + lua_pushstring(L, "Project configs must be a table of config names"); + lua_error(L); + } + + lua_pushstring(L, "config"); + lua_newtable(L); + for (i = 1; i <= luaL_getn(L, 3); ++i) + { + /* Set up the new config table to be added by name */ + lua_rawgeti(L, 3, i); + + /* Create the config and set the defaults */ + lua_newtable(L); + lua_pushstring(L, "name"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + + /* Add the config by index */ + lua_pushvalue(L, -1); + lua_rawseti(L, -4, i); + + /* Add the config by name */ + lua_rawset(L, -3); + } + + /* Add the new config table to the project */ + lua_rawset(L, 1); + + /* Add the initially requested item to the list, but under a different + * name so __newindex will be called if it is set again */ + lua_pushstring(L, "__configs"); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + } + else + { + /* Not setting "configs", just write to the table */ + lua_rawset(L, 1); + } + + return 0; +} diff --git a/build/premake/src/Src/script.h b/build/premake/src/Src/script.h new file mode 100644 index 0000000000..97b13ca222 --- /dev/null +++ b/build/premake/src/Src/script.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Premake - script.h + * Interface to the Lua scripting engine. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int script_run(const char* filename); +int script_export(); +int script_docommand(); +int script_close(); diff --git a/build/premake/src/Src/sharpdev.c b/build/premake/src/Src/sharpdev.c new file mode 100644 index 0000000000..93612df059 --- /dev/null +++ b/build/premake/src/Src/sharpdev.c @@ -0,0 +1,146 @@ +/********************************************************************** + * Premake - sharpdev.c + * The SharpDevelop and MonoDevelop targets + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "sharpdev.h" + +int sharpdev_target; +int sharpdev_warncontent; + +static int writeCombine(); + +int sharpdev_generate(const char* targetName) +{ + int i; + + sharpdev_target = matches(targetName, "monodev") ? MONODEV : SHARPDEV; + sharpdev_warncontent = 0; + + printf("Generating %sDevelop combine and project files:\n", (sharpdev_target == SHARPDEV) ? "Sharp" : "Mono"); + + if (!writeCombine()) + return 0; + + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + + printf("...%s\n", prj_get_pkgname()); + if (prj_is_lang("c#")) + { + if (!sharpdev_cs()) + return 0; + } + else if (prj_is_lang("c++") || prj_is_lang("c")) + { + printf("** Error: this generator does not support C/C++ development.\n"); + return 0; + } + else + { + printf("** Error: unrecognized language '%s'\n", prj_get_language()); + return 0; + } + } + + if (sharpdev_warncontent) + { + puts("\n** Warning: this project uses the 'Content' build action. This action is not"); + puts(" supported by #develop; some manual configuration may be needed."); + } + + return 1; +} + + +static int writeCombine() +{ + const char* path; + int i, j; + + if (!io_openfile(path_join(prj_get_path(), prj_get_name(), "cmbx"))) + return 0; + + io_print("\n", prj_get_name()); + + /* TODO: select the first executable project */ + io_print(" \n"); + + /* Write out the startup entries */ + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + io_print(" \n", prj_get_pkgname()); + } + + io_print(" \n"); + io_print(" \n"); + + /* Write out the project entries */ + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + path = prj_get_pkgfilename("prjx"); + io_print(" \n", path); + } + + io_print(" \n"); + io_print(" \n"); + + /* Write out the entries for each build configuration */ + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + io_print(" \n", prj_get_cfgname()); + + /* List all packages under this configuration */ + prj_select_config(0); + for(j = 0; j < prj_get_numpackages(); j++) + { + prj_select_package(j); + io_print(" \n", prj_get_pkgname(), prj_get_cfgname()); + } + + io_print(" \n"); + } + + /* Finish */ + io_print(" \n"); + io_print(""); + io_closefile(); + + /* MonoDevelop adds another file */ + if (sharpdev_target == MONODEV) + { + if (!io_openfile(path_join(prj_get_path(), prj_get_name(), "mdsx"))) + return 0; + + prj_select_config(0); + io_print("\n"); + io_print(" %s\n", prj_get_bindir()); + io_print("\n"); + + io_closefile(); + } + + return 1; +} diff --git a/build/premake/src/Src/sharpdev.h b/build/premake/src/Src/sharpdev.h new file mode 100644 index 0000000000..2afd092fea --- /dev/null +++ b/build/premake/src/Src/sharpdev.h @@ -0,0 +1,26 @@ +/********************************************************************** + * Premake - sharpdev.h + * The SharpDevelop and MonoDevelop targets + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int sharpdev_generate(const char* target); + +int sharpdev_cs(); + +#define SHARPDEV 0 +#define MONODEV 1 + +extern int sharpdev_target; +extern int sharpdev_warncontent; diff --git a/build/premake/src/Src/sharpdev_cs.c b/build/premake/src/Src/sharpdev_cs.c new file mode 100644 index 0000000000..246c341bee --- /dev/null +++ b/build/premake/src/Src/sharpdev_cs.c @@ -0,0 +1,304 @@ +/********************************************************************** + * Premake - sharpdev.c + * The SharpDevelop and MonoDevelop C# target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "sharpdev.h" +#include "os.h" + +static char buffer[8192]; + +static void listFiles(const char* path, int stage); +static void printFile(const char* file); +static const char* listReferences(const char* name); + + +int sharpdev_cs() +{ + const char* kind; + const char* runtime; + const char* csc; + int i; + + /* Figure out what I'm building */ + if (prj_is_kind("winexe")) + kind = "WinExe"; + else if (prj_is_kind("exe")) + kind = "Exe"; + else if (prj_is_kind("dll") || prj_is_kind("aspnet")) + kind = "Library"; + else + { + printf("** Error: unknown package kind '%s'\n", prj_get_kind()); + return 0; + } + + /* Figure out what .NET environment I'm using */ + if (g_dotnet == NULL) + g_dotnet = (os_is("windows") || sharpdev_target == MONODEV) ? "ms" : "mono"; + + if (strcmp(g_dotnet, "ms") == 0) + { + runtime = "MsNet"; + csc = "Csc"; + } + else if (strcmp(g_dotnet, "mono") == 0) + { + runtime = "Mono"; + csc = "Mcs"; + } + else if (strcmp(g_dotnet, "pnet") == 0) + { + printf("** Error: SharpDevelop does not yet support Portable.NET\n"); + return 0; + } + else + { + printf("** Error: unknown .NET runtime '%s'\n", g_dotnet); + return 0; + } + + /* Write the file */ + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "prjx"))) + return 0; + + prj_select_config(0); + + /* Project Header */ + if (sharpdev_target == SHARPDEV) + io_print("\n", prj_get_pkgname(), prj_get_pkgname()); + else + io_print("\n", prj_get_pkgname(), prj_get_pkgname()); + + /* File List */ + io_print(" \n"); + print_source_tree("", listFiles); + io_print(" \n"); + + /* References - all configuration will use the same set */ + io_print(" \n"); + print_list(prj_get_links(), " \n", "", listReferences); + io_print(" \n"); + + io_print(" \n"); + + /* Configurations */ + io_print(" \n", prj_get_cfgname()); + + for (i = 0; i < prj_get_numconfigs(); ++i) + { + int optimized; + + prj_select_config(i); + + optimized = prj_has_flag("optimize") || prj_has_flag("optimize-size") || prj_has_flag("optimize-speed"); + + io_print(" \n", prj_has_flag("fatal-warnings") ? "False" : "True", prj_get_cfgname()); + io_print(" \n"); + + io_print(" \n"); + + io_print(" \n"); + + io_print(" \n"); + } + + io_print(" \n"); + io_print("\n"); + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Callback for print_source_tree() + ***********************************************************************/ + +static void listFiles(const char* path, int stage) +{ + switch (stage) + { + case WST_OPENGROUP: + if (strlen(path) > 0) + { + io_print(" \n"); + } + break; + + case WST_CLOSEGROUP: + break; + + case WST_SOURCEFILE: + printFile(path); + break; + } +} + +static void printFile(const char* file) +{ + const char* ext; + const char* prefix = ""; + const char* subtype = ""; + const char* action = "Nothing"; + const char* depends = ""; + + if (file[0] != '.') + prefix = "./"; + + ext = path_getextension(file); + + /* If a build action was specified, use it */ + prj_select_file(file); + if (prj_get_buildaction() != NULL) + { + action = prj_get_buildaction(); + if (matches(action, "EmbeddedResource")) + action = "EmbedAsResource"; + if (matches(action, "None")) + action = "Nothing"; + if (matches(action, "Content")) + { + puts("** Warning: SharpDevelop does not support the 'Content' build action"); + action = "Nothing"; + } + subtype = "Code"; + } + else if (matches(ext, ".cs")) + { + subtype = "Code"; + action = "Compile"; + } + else if (matches(ext, ".resx")) + { + /* If a matching .cs file exists, link it */ + strcpy(buffer, file); + strcpy(buffer + strlen(file) - 5, ".cs"); + if (prj_has_file(buffer)) + { + /* Path is relative to .resx file, I assume both are in same + * directory and cut off path information */ + depends = path_getname(buffer); + } + + subtype = "Code"; + action = "EmbedAsResource"; + } + else + { + prj_select_file(file); + subtype = "Code"; + action = prj_get_buildaction(); + if (action == NULL || matches(action, "Content")) + { + sharpdev_warncontent = 1; + action = "Nothing"; + } + } + + io_print(" \n", prefix, file, subtype, action, depends); +} + + + +/************************************************************************ + * Prints entry for each reference listed in the package + ***********************************************************************/ + +static const char* listReferences(const char* name) +{ + int i; + int isSibling = 0; + const char* fileName = path_getname(name); + + strcpy(buffer," type=\""); + + /* A bit of craziness here...#dev wants to know if an assembly is local + * (type == "Assembly") or in the GAC (type == "GAC"). I would prefer + * to not have to specify this in the premake script if I can get away + * with it. So for each reference I check to see if it is a sibling + * project, and if so I consider it local. If not, I check all of the + * reference paths to see if I can find the DLL and if so I consider + * it local. If not, I consider it in the GAC. Seems to work so far */ + + for (i = 0; i < prj_get_numpackages(); ++i) + { + if (matches(prj_get_pkgname_for(i), name)) + { + isSibling = 1; + break; + } + } + + if(isSibling) + { + strcat(buffer, "Project\""); + strcat(buffer, " refto=\""); + strcat(buffer, fileName); + strcat(buffer, "\" localcopy=\"True\""); + } + else + { + const char* ext = strchr(name,',') ? "" : ".dll"; + + /* See if this assembly exists on one of the link paths */ + if (io_fileexists(path_join(prj_get_bindir(), name, ext))) + { + strcat(buffer, "Assembly\" refto=\""); + strcat(buffer, path_build(prj_get_pkgpath(), prj_get_bindir())); + strcat(buffer, "/"); + strcat(buffer, name); + strcat(buffer, ".dll\" localcopy=\"False\""); + } + else + { + strcat(buffer, "Gac\" refto=\""); + strcat(buffer, name); + strcat(buffer, ext); + strcat(buffer, "\" localcopy=\"False\""); + } + } + + return buffer; +} + diff --git a/build/premake/src/Src/util.c b/build/premake/src/Src/util.c new file mode 100644 index 0000000000..064f291bfd --- /dev/null +++ b/build/premake/src/Src/util.c @@ -0,0 +1,215 @@ +/********************************************************************** + * Premake - util.c + * Support functions. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include "premake.h" +#include "platform.h" + +static char* CPP_EXT[] = { ".cc", ".cpp", ".cxx", ".c", ".s", ".asm", NULL }; + +/* Buffer for generators */ +char g_buffer[8192]; + +/* Buffer for internal use */ +static char buffer[8192]; + + +/************************************************************************ + * Checks a pattern against the end of a string + ***********************************************************************/ + +int endsWith(const char* haystack, const char* needle) +{ + if (strlen(haystack) < strlen(needle)) + return 0; + + haystack = haystack + strlen(haystack) - strlen(needle); + return (strcmp(haystack, needle) == 0); +} + + +/************************************************************************ + * Create a pseudo-UUID, good enough for Premake's purposes + ***********************************************************************/ + +static void stringify(char* src, char* dst, int count) +{ + char buffer[4]; + int i; + + for (i = 0; i < count; ++i) + { + unsigned value = (unsigned char)src[i]; + sprintf(buffer, "%X", value); + + if (value >= 0x10) + { + *(dst++) = buffer[0]; + *(dst++) = buffer[1]; + } + else + { + *(dst++) = '0'; + *(dst++) = buffer[0]; + } + } +} + +void generateUUID(char* uuid) +{ + platform_getuuid(buffer); + + stringify(buffer, uuid, 4); + uuid[8] = '-'; + stringify(buffer + 4, uuid + 9, 2); + uuid[13] = '-'; + stringify(buffer + 6, uuid + 14, 2); + uuid[18] = '-'; + stringify(buffer + 8, uuid + 19, 2); + uuid[23] = '-'; + stringify(buffer + 10, uuid + 24, 6); + uuid[36] = '\0'; +} + + +/************************************************************************ + * Checks a file name against a list of known C/C++ file extensions + ***********************************************************************/ + +int is_cpp(const char* name) +{ + int i; + const char* ext = path_getextension(name); + if (ext == NULL) + return 0; + + for (i = 0; CPP_EXT[i] != NULL; ++i) + { + if (matches(ext, CPP_EXT[i])) + return 1; + } + + return 0; +} + + +/************************************************************************ + * Checks to see if two strings match. Just a more readable version + * of the standard strcmp() function + ***********************************************************************/ + +int matches(const char* str0, const char* str1) +{ + if (str0 == NULL || str1 == NULL) + return (str0 == str1); + + return (strcmp(str0, str1) == 0); +} + + +/************************************************************************ + * Iterate through an array of string, calling a function for each + ***********************************************************************/ + +void print_list(const char** list, const char* prefix, const char* postfix, const char* infix, const char* (*func)(const char*)) +{ + int i = 0; + while (*list) + { + const char* value = (func != NULL) ? func(*list) : *list; + if (value != NULL) + { + if (i++ > 0) + io_print(infix); + io_print("%s%s%s", prefix, value, postfix); + } + ++list; + } +} + + +/************************************************************************ + * Iterate through the list of files, build a tree structure + ***********************************************************************/ + +void print_source_tree(const char* path, void (*cb)(const char*, int)) +{ + const char** i; + + /* Open an enclosing group */ + strcpy(buffer, path); + if (buffer[strlen(buffer) - 1] == '/') /* Trim off trailing path separator */ + buffer[strlen(buffer) - 1] = '\0'; + cb(buffer, WST_OPENGROUP); + + for (i = prj_get_files(); *i != NULL; ++i) + { + const char* source = (*i); + + /* For each file in the target directory... */ + if (strlen(source) > strlen(path) && strncmp(source, path, strlen(path)) == 0) + { + /* Look for a subdirectory... */ + const char* ptr = strchr(source + strlen(path), '/'); + if (ptr != NULL) + { + const char** j; + + /* Pull out the subdirectory name */ + strncpy(buffer, source, ptr - source + 1); + buffer[ptr - source + 1] = '\0'; + + /* Have I processed this subdirectory already? Check to see if + * I encountered the same subdir name earlier in the list */ + for (j = prj_get_files(); *j != NULL; ++j) + { + if (strncmp(buffer, *j, strlen(buffer)) == 0) + break; + } + + if (i == j) + { + /* Not processed earlier, process it now. Make a local copy + * because 'buffer' will be reused in the next call */ + char* newpath = (char*)malloc(strlen(buffer) + 1); + strcpy(newpath, buffer); + print_source_tree(newpath, cb); + free(newpath); + } + } + } + } + + /* Now send all files that live in 'path' */ + for (i = prj_get_files(); *i != NULL; ++i) + { + const char* source = (*i); + const char* ptr = strrchr(source, '/'); + /* Make sure file is in path and not a subdir under path */ + if (strncmp(path, source, strlen(path)) == 0 && ptr <= source + strlen(path)) + cb(source, WST_SOURCEFILE); + } + + /* Close the enclosing group */ + strcpy(buffer, path); + if (buffer[strlen(buffer)-1] == '/') /* Trim off trailing path separator */ + buffer[strlen(buffer)-1] = '\0'; + cb(buffer, WST_CLOSEGROUP); +} + diff --git a/build/premake/src/Src/util.h b/build/premake/src/Src/util.h new file mode 100644 index 0000000000..a6aebd4ae7 --- /dev/null +++ b/build/premake/src/Src/util.h @@ -0,0 +1,29 @@ +/********************************************************************** + * Premake - util.h + * Support functions. + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#define ALLOCT(T) (T*)malloc(sizeof(T)) + +enum { WST_OPENGROUP, WST_CLOSEGROUP, WST_SOURCEFILE }; + +extern char g_buffer[]; + +int endsWith(const char* haystack, const char* needle); +void generateUUID(char* uuid); +int is_cpp(const char* name); +int matches(const char* str0, const char* str1); +void print_list(const char** list, const char* prefix, const char* postfix, const char* infix, const char* (*func)(const char*)); +void print_source_tree(const char* path, void (*cb)(const char*, int)); diff --git a/build/premake/src/Src/vs.c b/build/premake/src/Src/vs.c new file mode 100644 index 0000000000..ba7415fd7b --- /dev/null +++ b/build/premake/src/Src/vs.c @@ -0,0 +1,765 @@ +/********************************************************************** + * Premake - vs.c + * Common code for Visual Studio 2002-2005 targets. + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include +#include "premake.h" +#include "vs.h" + +static int version; + +#define S_TRUE (version < VS2005 ? "TRUE" : "true") +#define S_FALSE (version < VS2005 ? "FALSE" : "false") + +enum Blocks +{ + BlocksEnd, + VCCLCompilerTool, + VCCustomBuildTool, + VCLinkerTool, + VCMIDLTool, + VCPostBuildEventTool, + VCPreBuildEventTool, + VCPreLinkEventTool, + VCResourceCompilerTool, + VCWebServiceProxyGeneratorTool, + VCXMLDataGeneratorTool, + VCWebDeploymentTool, + VCManagedWrapperGeneratorTool, + VCAuxiliaryManagedWrapperGeneratorTool, + VCManagedResourceCompilerTool, + VCALinkTool, + VCManifestTool, + VCXDCMakeTool, + VCBscMakeTool, + VCFxCopTool, + VCAppVerifierTool +}; + +static int blocks_2002[] = +{ + VCCLCompilerTool, + VCCustomBuildTool, + VCLinkerTool, + VCMIDLTool, + VCPostBuildEventTool, + VCPreBuildEventTool, + VCPreLinkEventTool, + VCResourceCompilerTool, + VCWebServiceProxyGeneratorTool, + VCWebDeploymentTool, + BlocksEnd +}; + +static int blocks_2003[] = +{ + VCCLCompilerTool, + VCCustomBuildTool, + VCLinkerTool, + VCMIDLTool, + VCPostBuildEventTool, + VCPreBuildEventTool, + VCPreLinkEventTool, + VCResourceCompilerTool, + VCWebServiceProxyGeneratorTool, + VCXMLDataGeneratorTool, + VCWebDeploymentTool, + VCManagedWrapperGeneratorTool, + VCAuxiliaryManagedWrapperGeneratorTool, + BlocksEnd +}; + +static int blocks_2005[] = +{ + VCPreBuildEventTool, + VCCustomBuildTool, + VCXMLDataGeneratorTool, + VCWebServiceProxyGeneratorTool, + VCMIDLTool, + VCCLCompilerTool, + VCManagedResourceCompilerTool, + VCResourceCompilerTool, + VCPreLinkEventTool, + VCLinkerTool, + VCALinkTool, + VCManifestTool, + VCXDCMakeTool, + VCBscMakeTool, + VCFxCopTool, + VCAppVerifierTool, + VCWebDeploymentTool, + VCPostBuildEventTool, + BlocksEnd +}; + +static int* blocks[] = +{ + blocks_2002, + blocks_2003, + blocks_2005 +}; + + +/************************************************************************ + * Helpers to hide XML formatting style differences + ***********************************************************************/ + +static int indent = 0; +static int opened = 0; +static int attrib = 0; + +static void tag_indent() +{ + int i; + for (i = 0; i < indent; ++i) + io_print("\t"); +} + +static void tag_open(const char* name) +{ + if (opened) + { + if (version == VS2005 && attrib > 0) + { + io_print("\n"); + tag_indent(); + } + io_print(">\n"); + } + + tag_indent(); + io_print("<"); + io_print(name); + indent++; + opened = 1; + attrib = 0; +} + +static void tag_attr(const char* attr, ...) +{ + va_list args; + va_start(args, attr); + vsprintf(g_buffer, attr, args); + va_end(args); + + io_print("\n"); + tag_indent(); + io_print(g_buffer); + attrib++; +} + +static void tag_attr_open(const char* name) +{ + io_print("\n"); + tag_indent(); + io_print(name); + io_print("=\""); +} + +static tag_attr_close() +{ + io_print("\""); + attrib++; +} + +static void tag_close(const char* name, int form) +{ + indent--; + if (form == 1) + { + if (opened) + io_print(">\n"); + tag_indent(); + io_print("\n"); + } + else + { + if (version == VS2005) + { + io_print("\n"); + tag_indent(); + } + io_print("/>\n"); + } + opened = 0; +} + + +/************************************************************************ + * Store the current version of VS.NET being targeted + ***********************************************************************/ + +void vs_setversion(int ver) +{ + version = ver; +} + +int vs_getversion() +{ + return version; +} + + + +/************************************************************************ + * Assign GUIDs to each package by type + ***********************************************************************/ + +void vs_assign_guids() +{ + int p; + for (p = 0; p < prj_get_numpackages(); ++p) + { + VsPkgData* data = ALLOCT(VsPkgData); + prj_select_package(p); + prj_set_data(data); + + generateUUID(data->projGuid); + + prj_select_config(0); + if (version == VS2005 && prj_is_kind("aspnet")) + { + strcpy(data->toolGuid, "E24C65DC-7377-472B-9ABA-BC803B73C61A"); + strcpy(data->projExt, ""); + strcpy(data->projType, ""); + } + else if (prj_is_lang("c++") || prj_is_lang("c")) + { + strcpy(data->toolGuid, "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); + strcpy(data->projExt, "vcproj"); + strcpy(data->projType, "Win32"); + } + else if (prj_is_lang("c#")) + { + strcpy(data->toolGuid, "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"); + strcpy(data->projExt, "csproj"); + if (version < VS2005) + strcpy(data->projType, ".NET"); + else + strcpy(data->projType, "Any CPU"); + } + + data->numDependencies = 0; + } +} + + +/************************************************************************ + * Write out a C++ project file + ***********************************************************************/ + +int vs_write_cpp() +{ + const char* str; + int i, b; + + VsPkgData* data = (VsPkgData*)prj_get_data(); + + /* Open the file and write the header */ + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "vcproj"))) + return 0; + + prj_select_config(0); + io_print("\n"); + + tag_open("VisualStudioProject"); + tag_attr("ProjectType=\"Visual C++\""); + + switch (version) + { + case VS2002: + str = "7.00"; + break; + case VS2003: + str = "7.10"; + break; + case VS2005: + str = "8.00"; + break; + } + tag_attr("Version=\"%s\"", str); + + tag_attr("Name=\"%s\"", prj_get_pkgname()); + tag_attr("ProjectGUID=\"{%s}\"", data->projGuid); + + if (version == VS2005) + tag_attr("RootNamespace=\"%s\"", prj_get_pkgname()); + + tag_attr("Keyword=\"%s\"", prj_has_flag("managed") ? "ManagedCProj" : "Win32Proj"); + + tag_open("Platforms"); + tag_open("Platform"); + tag_attr("Name=\"Win32\""); + tag_close("Platform", 0); + tag_close("Platforms", 1); + + if (version == VS2005) + { + tag_open("ToolFiles"); + tag_close("ToolFiles", 1); + } + + /* Write configurations */ + tag_open("Configurations"); + for (i = 0; i < prj_get_numconfigs(); ++i) + { + int optimization, debug, runtime, symbols, configTypeId; + const char* pchHeader = prj_get_pch_header(); + + prj_select_config(i); + + if (prj_is_kind("winexe") || prj_is_kind("exe")) + { + configTypeId = 1; + } + else if (prj_is_kind("dll")) + { + configTypeId = 2; + } + else if (prj_is_kind("lib")) + { + configTypeId = 4; + } + else if (prj_is_kind("aspnet")) + { + puts("** Error: C++ ASP.NET projects are not supported"); + return 0; + } + else + { + printf("** Error: unknown package kind '%s'\n", prj_get_kind()); + return 0; + } + + if (prj_has_flag("optimize-speed")) + optimization = 2; + else if (prj_has_flag("optimize-size")) + optimization = 1; + else if (prj_has_flag("optimize")) + optimization = 3; + else + optimization = 0; + + debug = (optimization ==0); + + if (prj_has_flag("static-runtime")) + runtime = (debug) ? 1 : 0; + else + runtime = (debug) ? 3 : 2; + + if (prj_has_flag("no-symbols")) + symbols = 0; + else + symbols = (prj_has_flag("managed") || prj_has_flag("no-edit-and-continue")) ? 3 : 4; + + tag_open("Configuration"); + tag_attr("Name=\"%s|Win32\"", prj_get_cfgname()); + tag_attr("OutputDirectory=\"%s\"", prj_get_outdir()); + tag_attr("IntermediateDirectory=\"%s\"", prj_get_objdir()); + tag_attr("ConfigurationType=\"%d\"", configTypeId); + tag_attr("CharacterSet=\"%d\"", prj_has_flag("unicode") ? 1 : 2); + if (prj_has_flag("managed")) + tag_attr("ManagedExtensions=\"%s\"", S_TRUE); + + /* Write out tool blocks */ + for (b = 0; blocks[version][b] != BlocksEnd; ++b) + { + tag_open("Tool"); + switch (blocks[version][b]) + { + case VCPreBuildEventTool: + tag_attr("Name=\"VCPreBuildEventTool\""); + break; + case VCCustomBuildTool: + tag_attr("Name=\"VCCustomBuildTool\""); + break; + case VCXMLDataGeneratorTool: + tag_attr("Name=\"VCXMLDataGeneratorTool\""); + break; + case VCManagedWrapperGeneratorTool: + tag_attr("Name=\"VCManagedWrapperGeneratorTool\""); + break; + case VCAuxiliaryManagedWrapperGeneratorTool: + tag_attr("Name=\"VCAuxiliaryManagedWrapperGeneratorTool\""); + break; + case VCWebServiceProxyGeneratorTool: + tag_attr("Name=\"VCWebServiceProxyGeneratorTool\""); + break; + case VCMIDLTool: + tag_attr("Name=\"VCMIDLTool\""); + break; + case VCManagedResourceCompilerTool: + tag_attr("Name=\"VCManagedResourceCompilerTool\""); + break; + case VCResourceCompilerTool: + tag_attr("Name=\"VCResourceCompilerTool\""); + if (prj_get_numincpaths() > 0) + { + tag_attr_open("AdditionalIncludeDirectories"); + print_list(prj_get_incpaths(), "", "", ";", NULL); + tag_attr_close(); + } + break; + case VCPreLinkEventTool: + tag_attr("Name=\"VCPreLinkEventTool\""); + break; + case VCALinkTool: + tag_attr("Name=\"VCALinkTool\""); + break; + case VCManifestTool: + tag_attr("Name=\"VCManifestTool\""); + break; + case VCXDCMakeTool: + tag_attr("Name=\"VCXDCMakeTool\""); + break; + case VCBscMakeTool: + tag_attr("Name=\"VCBscMakeTool\""); + break; + case VCFxCopTool: + tag_attr("Name=\"VCFxCopTool\""); + break; + case VCAppVerifierTool: + tag_attr("Name=\"VCAppVerifierTool\""); + break; + case VCWebDeploymentTool: + tag_attr("Name=\"VCWebDeploymentTool\""); + break; + case VCPostBuildEventTool: + tag_attr("Name=\"VCPostBuildEventTool\""); + break; + case VCCLCompilerTool: + tag_attr("Name=\"VCCLCompilerTool\""); + + if (prj_get_numbuildoptions() > 0) + { + tag_attr_open("AdditionalOptions"); + print_list(prj_get_buildoptions(), "", "", " ", NULL); + tag_attr_close(); + } + + tag_attr("Optimization=\"%d\"", optimization); + + if (prj_has_flag("no-frame-pointer")) + tag_attr("OmitFramePointers=\"%s\"", S_TRUE); + + if (prj_get_numincpaths() > 0) + { + tag_attr_open("AdditionalIncludeDirectories"); + print_list(prj_get_incpaths(), "", "", ";", NULL); + tag_attr_close(); + } + + if (prj_has_flag("managed")) + tag_attr("AdditionalUsingDirectories=\"%s\"", prj_get_bindir()); + + if (prj_get_numdefines() > 0) + { + tag_attr_open("PreprocessorDefinitions"); + print_list(prj_get_defines(), "", "", ";", NULL); + tag_attr_close(); + } + + if (debug && !prj_has_flag("managed")) + tag_attr("MinimalRebuild=\"%s\"", S_TRUE); + + if (prj_has_flag("no-exceptions")) + tag_attr("ExceptionHandling=\"%s\"", S_FALSE); + + if (debug && !prj_has_flag("managed")) + tag_attr("BasicRuntimeChecks=\"3\""); + + if (!debug) + tag_attr("StringPooling=\"%s\"", S_TRUE); + + tag_attr("RuntimeLibrary=\"%d\"", runtime); + tag_attr("EnableFunctionLevelLinking=\"%s\"", S_TRUE); + + if (version < VS2005 && !prj_has_flag("no-rtti")) + tag_attr("RuntimeTypeInfo=\"%s\"", S_TRUE); + if (version == VS2005 && prj_has_flag("no-rtti")) + tag_attr("RuntimeTypeInfo=\"%s\"", S_FALSE); + + if (version < VS2005 && prj_has_flag("native-wchar_t")) + tag_attr("TreatWChar_tAsBuiltInType=\"%s\"", S_TRUE); + if (version == VS2005 && prj_has_flag("no-native-wchar_t")) + tag_attr("TreatWChar_tAsBuiltInType=\"%s\"", S_FALSE); + + if (pchHeader) + { + tag_attr("UsePrecompiledHeader=\"%d\"", version < VS2005 ? 3 : 2); + tag_attr("PrecompiledHeaderThrough=\"%s\"", pchHeader); + } + else + tag_attr("UsePrecompiledHeader=\"%d\"", version < VS2005 ? 2 : 0); + + tag_attr("WarningLevel=\"%d\"", prj_has_flag("extra-warnings") ? 4 : 3); + if (prj_has_flag("fatal-warnings")) + tag_attr("WarnAsError=\"%s\"", S_TRUE); + if (!prj_has_flag("managed")) + tag_attr("Detect64BitPortabilityProblems=\"%s\"", prj_has_flag("no-64bit-checks") ? S_FALSE : S_TRUE); + + tag_attr("DebugInformationFormat=\"%d\"", symbols); + break; + case VCLinkerTool: + if (!prj_is_kind("lib")) + { + tag_attr("Name=\"VCLinkerTool\""); + if (prj_has_flag("no-import-lib")) + tag_attr("IgnoreImportLibrary=\"%s\"", S_TRUE); + + if (prj_get_numlinkoptions() > 0) + { + tag_attr_open("AdditionalOptions"); + print_list(prj_get_linkoptions(), " ", "", "", NULL); + tag_attr_close(); + } + + if (prj_get_numlinks() > 0) + { + tag_attr_open("AdditionalDependencies"); + print_list(prj_get_links(), "", ".lib", " ", vs_filter_links); + tag_attr_close(); + } + + tag_attr("OutputFile=\"$(OutDir)/%s\"", path_getname(prj_get_target())); + tag_attr("LinkIncremental=\"%d\"", debug ? 2 : 1); + + tag_attr_open("AdditionalLibraryDirectories"); + io_print(prj_get_libdir()); + print_list(prj_get_libpaths(), ";", "", "", NULL); + tag_attr_close(); + + /* Look for a .def file for DLLs */ + if (prj_find_filetype(".def") != NULL) + tag_attr("ModuleDefinitionFile=\"%s\"", prj_find_filetype(".def")); + + if (prj_has_flag("no-manifest")) + tag_attr("GenerateManifest=\"%s\"", S_FALSE); + + tag_attr("GenerateDebugInformation=\"%s\"", symbols ? S_TRUE : S_FALSE); + if (symbols) + tag_attr("ProgramDatabaseFile=\"$(OutDir)/%s.pdb\"", path_getbasename(prj_get_target())); + + tag_attr("SubSystem=\"%d\"", prj_is_kind("exe") ? 1 : 2); + if (!debug) tag_attr("OptimizeReferences=\"2\""); + if (!debug) tag_attr("EnableCOMDATFolding=\"2\""); + + if ((prj_is_kind("exe") || prj_is_kind("winexe")) && !prj_has_flag("no-main")) + { + tag_attr("EntryPointSymbol=\"mainCRTStartup\""); + } + else if (prj_is_kind("dll")) + { + tag_attr_open("ImportLibrary"); + if (prj_has_flag("no-import-lib")) + io_print(prj_get_objdir()); + else + io_print(prj_get_libdir()); + io_print("/%s.lib", path_getbasename(prj_get_target())); + tag_attr_close(); + } + tag_attr("TargetMachine=\"1\""); + } + else + { + tag_attr("Name=\"VCLibrarianTool\""); + tag_attr("OutputFile=\"$(OutDir)/%s.lib\"", path_getbasename(prj_get_target())); + } + break; + } + tag_close("", 0); + } + + tag_close("Configuration", 1); + } + tag_close("Configurations", 1); + + if (version > VS2002) + { + tag_open("References"); + tag_close("References", 1); + } + + tag_open("Files"); + print_source_tree("", vs_list_files); + tag_close("Files", 1); + + tag_open("Globals"); + tag_close("Globals", 1); + tag_close("VisualStudioProject", 1); + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Checks each entry in the list of package links. If the entry refers + * to a sibling package, returns the path to that package's output + ***********************************************************************/ + +const char* vs_filter_links(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + const char* lang = prj_get_language_for(i); + if (matches(lang, "c") || matches(lang, "c++")) + { + strcpy(g_buffer, prj_get_libdir_for(i)); + return path_combine(g_buffer, prj_get_targetname_for(i)); + } + else + return NULL; + } + else + { + return name; + } +} + + +/************************************************************************ + * Callback for print_source_tree() + ***********************************************************************/ + +void vs_list_files(const char* path, int stage) +{ + int i; + const char* pchSource = prj_get_pch_source(); + const char* trimPrefix = prj_get_trimprefix(); + + const char* ptr = path; + while (strncmp(ptr, "../", 3) == 0) + ptr += 3; + + ptr = strchr(ptr, '/'); + while (ptr != NULL) + ptr = strchr(ptr + 1, '/'); + + ptr = strrchr(path, '/'); + ptr = (ptr == NULL) ? (char*)path : ptr + 1; + + switch (stage) + { + case WST_OPENGROUP: + if (strlen(path) > 0 && !matches(ptr, "..") && (!trimPrefix || strncmp(path, trimPrefix, strlen(trimPrefix)) == 0)) + { + tag_open("Filter"); + tag_attr("Name=\"%s\"", ptr); + tag_attr("Filter=\"\""); + } + break; + + case WST_CLOSEGROUP: + if (strlen(path) > 0 && !matches(ptr, "..") && (!trimPrefix || strncmp(path, trimPrefix, strlen(trimPrefix)) == 0)) + tag_close("Filter", 1); + break; + + case WST_SOURCEFILE: + tag_open("File"); + tag_attr_open("RelativePath"); + if (path[0] != '.') + io_print(".\\"); + io_print(path_translate(path, "windows")); + tag_attr_close(); + + /* Add FileConfiguration section if this is a special PCH file, or + if it's a custom-built .asm */ + if (matches(path_getname(path), pchSource) || endsWith(path, ".asm")) + { + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + + tag_open("FileConfiguration"); + tag_attr("Name=\"%s|Win32\"", prj_get_cfgname()); + + if (endsWith(path, ".asm")) + { + tag_open("Tool"); + tag_attr("Name=\"VCCustomBuildTool\""); + tag_attr("Description=\"Assembling $(InputPath)\""); + tag_attr("CommandLine=\"%s -f win32 -o "$(IntDir)\\$(InputName).obj" "$(InputPath)"\"", + path_translate(prj_get_nasmpath(), "windows")); + tag_attr("Outputs=\"$(IntDir)\\$(InputName).obj\""); + tag_close("Tool", 0); + } + else /* (.asm doesn't need PCH) */ + { + tag_open("Tool"); + tag_attr("Name=\"VCCLCompilerTool\""); + tag_attr("UsePrecompiledHeader=\"1\""); + tag_close("Tool", 0); + } + tag_close("FileConfiguration", 1); + } + } + + tag_close("File", 1); + + break; + } +} + + +/************************************************************************ + * List callback: scans the list of links for a package. If a link is + * found to a sibling package, return a dependency string for the + * solution file. + ***********************************************************************/ + +const char* vs_list_pkgdeps(const char* name) +{ + int i; + for (i = 0; i < prj_get_numpackages(); ++i) + { + if (matches(prj_get_pkgname_for(i), name)) + { + VsPkgData* data = (VsPkgData*)prj_get_data_for(i); + if (version > VS2002) + { + sprintf(g_buffer, "{%s} = {%s}", data->projGuid, data->projGuid); + } + else + { + VsPkgData* src = (VsPkgData*)prj_get_data(); + sprintf(g_buffer, "{%s}.%d = {%s}", src->projGuid, src->numDependencies, data->projGuid); + ++(src->numDependencies); + } + return g_buffer; + } + } + + return NULL; +} + + +/************************************************************************ + * VS.NET requires that all reference search paths be absolute + ***********************************************************************/ + +const char* vs_list_refpaths(const char* name) +{ + char* path = (char*)path_absolute(name); + path_translateInPlace(path, "windows"); + return path; +} diff --git a/build/premake/src/Src/vs.h b/build/premake/src/Src/vs.h new file mode 100644 index 0000000000..ca8a037b50 --- /dev/null +++ b/build/premake/src/Src/vs.h @@ -0,0 +1,42 @@ +/********************************************************************** + * Premake - vs.h + * Common code for Visual Studio 2002-2005 targets. + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +enum VsVer +{ + VS2002, + VS2003, + VS2005 +}; + +typedef struct tagVsPkgData +{ + char projGuid[38]; + char toolGuid[38]; + char projExt[8]; + char projType[8]; + int numDependencies; +} VsPkgData; + +void vs_setversion(int version); +int vs_getversion(); + +void vs_assign_guids(); +int vs_write_cpp(); +const char* vs_list_refpaths(const char* name); +const char* vs_list_pkgdeps(const char* name); +void vs_list_files(const char* path, int stage); +const char* vs_filter_links(const char* name); diff --git a/build/premake/src/Src/vs2002.c b/build/premake/src/Src/vs2002.c new file mode 100644 index 0000000000..2bbfb373ef --- /dev/null +++ b/build/premake/src/Src/vs2002.c @@ -0,0 +1,163 @@ +/********************************************************************** + * Premake - vs2002.c + * The Visual Studio 2002 and 2003 target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include "premake.h" +#include "vs.h" +#include "vs2002.h" + +static int vs2002_write_solution(); + + +int vs2002_generate(int target) +{ + int i; + + vs_setversion(target == 2002 ? VS2002 : VS2003); + + printf("Generating Visual Studio %d solution and project files:\n", target); + + /* Assign GUIDs to packages */ + vs_assign_guids(); + + /* Generate the project files */ + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + + printf("...%s\n", prj_get_pkgname()); + + if (prj_is_lang("c++") || prj_is_lang("c")) + { + if (!vs_write_cpp()) + return 0; + } + else if (prj_is_lang("c#")) + { + if (!vs2002_cs()) + return 0; + } + else + { + printf("** Warning: %s packages are not supported by this generator\n", prj_get_language()); + } + } + + return vs2002_write_solution(); +} + + +/************************************************************************ + * Write out the solution file + ***********************************************************************/ + +static int vs2002_write_solution() +{ + VsPkgData* data; + int i, j; + + if (!io_openfile(path_join(prj_get_path(), prj_get_name(), "sln"))) + return 0; + + /* Format identification string */ + io_print("Microsoft Visual Studio Solution File, Format Version "); + if (vs_getversion() == VS2002) + io_print("7.00\n"); + else + io_print("8.00\n"); + + /* List packages */ + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + data = (VsPkgData*)prj_get_data(); + + io_print("Project(\"{%s}\") = \"%s\", \"%s\", \"{%s}\"\n", data->toolGuid, prj_get_pkgname(), prj_get_pkgfilename(data->projExt), data->projGuid); + + /* Write package dependencies for post-2002 */ + if (vs_getversion() > VS2002) + { + prj_select_config(0); + io_print("\tProjectSection(ProjectDependencies) = postProject\n"); + print_list(prj_get_links(), "\t\t", "\n", "", vs_list_pkgdeps); + io_print("\tEndProjectSection\n"); + } + + io_print("EndProject\n"); + } + + /* List configurations */ + io_print("Global\n"); + io_print("\tGlobalSection(SolutionConfiguration) = preSolution\n"); + + prj_select_package(0); + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + if (vs_getversion() == VS2002) + io_print("\t\tConfigName.%d = %s\n", i, prj_get_cfgname()); + else + io_print("\t\t%s = %s\n", prj_get_cfgname(), prj_get_cfgname()); + } + io_print("\tEndGlobalSection\n"); + + /* Write package dependencies for 2002 */ + if (vs_getversion() == VS2002) + { + io_print("\tGlobalSection(ProjectDependencies) = postSolution\n"); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + prj_select_config(0); + print_list(prj_get_links(), "\t\t", "\n", "", vs_list_pkgdeps); + } + io_print("\tEndGlobalSection\n"); + } + + /* Write configuration for each package */ + io_print("\tGlobalSection(ProjectConfiguration) = postSolution\n"); + + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + for (j = 0; j < prj_get_numconfigs(); ++j) + { + prj_select_config(j); + data = (VsPkgData*)prj_get_data(); + + /* I may actually be writing the wrong thing for VS2002-2003, but has + * seemed to work for this long so I am going to leave it alone */ + io_print("\t\t{%s}.%s.ActiveCfg = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), data->projType); + io_print("\t\t{%s}.%s.Build.0 = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), data->projType); + } + } + io_print("\tEndGlobalSection\n"); + + /* Finish */ + io_print("\tGlobalSection(ExtensibilityGlobals) = postSolution\n"); + io_print("\tEndGlobalSection\n"); + io_print("\tGlobalSection(ExtensibilityAddIns) = postSolution\n"); + io_print("\tEndGlobalSection\n"); + io_print("EndGlobal\n"); + + io_closefile(); + return 1; +} + + diff --git a/build/premake/src/Src/vs2002.h b/build/premake/src/Src/vs2002.h new file mode 100644 index 0000000000..ef58af9e0d --- /dev/null +++ b/build/premake/src/Src/vs2002.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Premake - vs2002.h + * The Visual Studio 2002 and 2003 target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int vs2002_generate(); +int vs2002_cs(); diff --git a/build/premake/src/Src/vs2002_cs.c b/build/premake/src/Src/vs2002_cs.c new file mode 100644 index 0000000000..02148da5bf --- /dev/null +++ b/build/premake/src/Src/vs2002_cs.c @@ -0,0 +1,355 @@ +/********************************************************************** + * Premake - vs2002_cs.c + * The Visual Studio 2002 and 2003 C# target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include "premake.h" +#include "vs.h" +#include "vs2002.h" + +static const char* listReferences(const char* name); +static const char* listFiles(const char* name); + + +int vs2002_cs() +{ + const char* outputType; + int i; + + VsPkgData* data = (VsPkgData*)prj_get_data(); + + /* Figure out what I'm building */ + prj_select_config(0); + if (prj_is_kind("winexe")) + outputType = "WinExe"; + else if (prj_is_kind("exe")) + outputType = "Exe"; + else if (prj_is_kind("dll") || prj_is_kind("aspnet")) + outputType = "Library"; + else + { + printf("** Error: unknown package kind '%s'\n", prj_get_kind()); + return 0; + } + + /* Open the file and write the header */ + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj"))) + return 0; + + io_print("\n"); + io_print("\tprojGuid); + io_print("\t>\n"); + io_print("\t\t\n"); + io_print("\t\t\t\n"); + + for (i = 0; i < prj_get_numconfigs(); ++i) + { + int optimize; + + prj_select_config(i); + + optimize = prj_has_flag("optimize") || prj_has_flag("optimize-size") || prj_has_flag("optimize-speed"); + + io_print("\t\t\t\t\n"); + } + + io_print("\t\t\t\n"); + + /* VS7 requires same references for all configurations */ + prj_select_config(0); + io_print("\t\t\t\n"); + print_list(prj_get_links(), "\t\t\t\t\n", "", listReferences); + io_print("\t\t\t\n"); + io_print("\t\t\n"); + + io_print("\t\t\n"); + io_print("\t\t\t\n"); + print_list(prj_get_files(), "\t\t\t\t\n", "", listFiles); + io_print("\t\t\t\n"); + io_print("\t\t\n"); + io_print("\t\n"); + io_print("\n"); + + io_closefile(); + + /* Now write the .csproj.user file for non-web applications or + * .csproj.webinfo for web applications */ + if (!prj_is_kind("aspnet")) + { + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj.user"))) + return 0; + + + io_print("\n"); + io_print("\t\n"); + io_print("\t\t\n"); + io_print("\t\t\t\n"); + + + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + + io_print("\t\t\t\t\n"); + } + + io_print("\t\t\t\n"); + io_print("\t\t\n"); + io_print("\t\t\n"); + io_print("\t\n"); + io_print("\n"); + } + else + { + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj.webinfo"))) + return 0; + + io_print("\n"); + io_print("\t\n", prj_get_pkgname()); + io_print("\n"); + } + + io_closefile(); + return 1; +} + + + +/************************************************************************ + * Checks each entry in the list of package links. If the entry refers + * to a sibling package, returns the path to that package's output + ***********************************************************************/ + +static const char* listReferences(const char* name) +{ + char assembly[8192]; + char* comma; + int i; + + /* Pull out the file name, the comma check is for full assembly names */ + strcpy(assembly, name); + comma = strchr(name, ','); + if (comma != NULL) + *comma = '\0'; + + strcpy(g_buffer, "\t\t\t\t\tName = \""); + strcat(g_buffer, assembly); + strcat(g_buffer, "\"\n"); + + /* Is this a sibling package? */ + i = prj_find_package(name); + if (i >= 0) + { + VsPkgData* data = (VsPkgData*)prj_get_data_for(i); + strcat(g_buffer, "\t\t\t\t\tProject = \"{"); + strcat(g_buffer, data->projGuid); + strcat(g_buffer, "}\"\n"); + strcat(g_buffer, "\t\t\t\t\tPackage = \"{"); + strcat(g_buffer, data->toolGuid); + strcat(g_buffer, "}\"\n"); + return g_buffer; + } + + strcat(g_buffer, "\t\t\t\t\tAssemblyName = \""); + strcat(g_buffer, path_getname(assembly)); + strcat(g_buffer, "\"\n"); + if (!matches(assembly, path_getname(assembly))) + { + strcat(g_buffer, "\t\t\t\t\tHintPath = \""); + strcat(g_buffer, assembly); + strcat(g_buffer, ".dll\"\n"); + } + + /* Tack on any extra information about the assembly */ + while (comma != NULL) + { + char* start; + for (start = comma + 1; *start == ' '; ++start); + comma = strchr(start, '='); + *comma = '\0'; + strcat(g_buffer, "\t\t\t\t\t"); + strcat(g_buffer, start); + strcat(g_buffer, " = \""); + + start = comma + 1; + comma = strchr(start, ','); + if (comma != NULL) *comma = '\0'; + strcat(g_buffer, start); + strcat(g_buffer, "\"\n"); + } + + return g_buffer; +} + + +/************************************************************************ + * Builds an entry for each file in the project + ***********************************************************************/ + +static const char* listFiles(const char* name) +{ + io_print("\t\t\t\t\n"); + return NULL; +} diff --git a/build/premake/src/Src/vs2005.c b/build/premake/src/Src/vs2005.c new file mode 100644 index 0000000000..83998b17a0 --- /dev/null +++ b/build/premake/src/Src/vs2005.c @@ -0,0 +1,238 @@ +/********************************************************************** + * Premake - vs2005.c + * The Visual Studio 2005 target + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include +#include "premake.h" +#include "vs.h" +#include "vs2005.h" + +static int vs2005_write_solution(); +static const char* list_aspnet_refs(const char* name); + +int vs2005_generate(int target) +{ + int p; + + vs_setversion(VS2005); + printf("Generating Visual Studio 2005 solution and project files:\n"); + + /* Assign GUIDs to packages */ + vs_assign_guids(); + + /* Generate the project files */ + for (p = 0; p < prj_get_numpackages(); ++p) + { + prj_select_package(p); + prj_select_config(0); + + printf("...%s\n", prj_get_pkgname()); + + if (prj_is_kind("aspnet")) + { + /* No project files?! */ + } + else if (prj_is_lang("c++") || prj_is_lang("c")) + { + if (!vs_write_cpp()) + return 0; + } + else if (prj_is_lang("c#")) + { + if (!vs2005_cs()) + return 0; + } + else + { + printf("** Warning: %s packages are not supported by this generator\n", prj_get_language()); + } + } + + return vs2005_write_solution(); +} + + +/************************************************************************ + * Write out the solution file + ***********************************************************************/ + +static int vs2005_write_solution() +{ + VsPkgData* data; + int hasDotNet, hasCpp; + int i, j; + int numAspNet, port; + + if (!io_openfile(path_join(prj_get_path(), prj_get_name(), "sln"))) + return 0; + + /* Format identification string */ + io_print("Microsoft Visual Studio Solution File, Format Version 9.00\n"); + io_print("# Visual Studio 2005\n"); + + /* List packages */ + numAspNet = 0; + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + prj_select_config(0); + + data = (VsPkgData*)prj_get_data(); + + if (prj_is_kind("aspnet")) + { + const char* path = prj_get_pkgpath(); + if (strlen(path) == 0) path = "."; + + io_print("Project(\"{%s}\") = \"%s\", \"%s\\\", \"{%s}\"\n", data->toolGuid, prj_get_pkgname(), path, data->projGuid); + io_print("\tProjectSection(WebsiteProperties) = preProject\n"); + + if (prj_get_numlinks() > 0) + print_list(prj_get_links(), "\t\tProjectReferences = \"", ";\"\n", ";", list_aspnet_refs); + + for (j = 0; j < prj_get_numconfigs(); ++j) + { + prj_select_config(j); + io_print("\t\t%s.AspNetCompiler.VirtualPath = \"/%s\"\n", prj_get_cfgname(), prj_get_pkgname()); + io_print("\t\t%s.AspNetCompiler.PhysicalPath = \"%s\\\"\n", prj_get_cfgname(), path); + io_print("\t\t%s.AspNetCompiler.TargetPath = \"PrecompiledWeb\\%s\\\"\n", prj_get_cfgname(), prj_get_pkgname()); + io_print("\t\t%s.AspNetCompiler.Updateable = \"true\"\n", prj_get_cfgname()); + io_print("\t\t%s.AspNetCompiler.ForceOverwrite = \"true\"\n", prj_get_cfgname()); + io_print("\t\t%s.AspNetCompiler.FixedNames = \"false\"\n", prj_get_cfgname()); + io_print("\t\t%s.AspNetCompiler.Debug = \"%s\"\n", prj_get_cfgname(), prj_has_flag("no-symbols") ? "False" : "True"); + } + + if (numAspNet == 0) + port = 1106; + else if (numAspNet == 1) + port = 1231; + else + port = 1251 + 2 * (numAspNet - 2); + io_print("\t\tVWDPort = \"%d\"\n", port); + numAspNet++; + + if (prj_is_lang("c#")) + io_print("\t\tDefaultWebSiteLanguage = \"Visual C#\"\n"); + + io_print("\tEndProjectSection\n"); + } + else + { + io_print("Project(\"{%s}\") = \"%s\", \"%s\", \"{%s}\"\n", data->toolGuid, prj_get_pkgname(), prj_get_pkgfilename(data->projExt), data->projGuid); + + /* Write dependencies */ + prj_select_config(0); + io_print("\tProjectSection(ProjectDependencies) = postProject\n"); + print_list(prj_get_links(), "\t\t", "\n", "", vs_list_pkgdeps); + io_print("\tEndProjectSection\n"); + } + + io_print("EndProject\n"); + } + + /* List configurations */ + io_print("Global\n"); + io_print("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"); + + hasDotNet = 0; + hasCpp = 0; + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + if (prj_is_lang("c") || prj_is_lang("c++")) + hasCpp = 1; + else + hasDotNet = 1; + } + + prj_select_package(0); + for (i = 0; i < prj_get_numconfigs(); ++i) + { + prj_select_config(i); + if (hasDotNet) + io_print("\t\t%s|Any CPU = %s|Any CPU\n", prj_get_cfgname(), prj_get_cfgname()); + if (hasDotNet && hasCpp) + io_print("\t\t%s|Mixed Platforms = %s|Mixed Platforms\n", prj_get_cfgname(), prj_get_cfgname()); + if (hasCpp) + io_print("\t\t%s|Win32 = %s|Win32\n", prj_get_cfgname(), prj_get_cfgname()); + } + io_print("\tEndGlobalSection\n"); + + /* Write configuration for each package */ + io_print("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"); + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + for (j = 0; j < prj_get_numconfigs(); ++j) + { + const char* arch; + + prj_select_config(j); + data = (VsPkgData*)prj_get_data(); + + if (prj_is_lang("c") || prj_is_lang("c++")) + arch = "Win32"; + else + arch = "Any CPU"; + + if (hasDotNet) + { + io_print("\t\t{%s}.%s|Any CPU.ActiveCfg = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + if (!prj_is_lang("c") && !prj_is_lang("c++")) + io_print("\t\t{%s}.%s|Any CPU.Build.0 = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + } + + if (hasDotNet && hasCpp) + { + io_print("\t\t{%s}.%s|Mixed Platforms.ActiveCfg = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + io_print("\t\t{%s}.%s|Mixed Platforms.Build.0 = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + } + + if (hasCpp) + { + io_print("\t\t{%s}.%s|Win32.ActiveCfg = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + if (prj_is_lang("c") || prj_is_lang("c++")) + io_print("\t\t{%s}.%s|Win32.Build.0 = %s|%s\n", data->projGuid, prj_get_cfgname(), prj_get_cfgname(), arch); + } + } + } + io_print("\tEndGlobalSection\n"); + + /* Finish */ + io_print("\tGlobalSection(SolutionProperties) = preSolution\n"); + io_print("\t\tHideSolutionNode = FALSE\n"); + io_print("\tEndGlobalSection\n"); + io_print("EndGlobal\n"); + + io_closefile(); + return 1; +} + + + +static const char* list_aspnet_refs(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + VsPkgData* data = (VsPkgData*)prj_get_data_for(i); + sprintf(g_buffer, "{%s}|%s.dll", data->projGuid, prj_get_pkgname_for(i)); + return g_buffer; + } + return NULL; +} diff --git a/build/premake/src/Src/vs2005.h b/build/premake/src/Src/vs2005.h new file mode 100644 index 0000000000..1d949745c8 --- /dev/null +++ b/build/premake/src/Src/vs2005.h @@ -0,0 +1,20 @@ +/********************************************************************** + * Premake - vs2005.h + * The Visual Studio 2005 target + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int vs2005_generate(); +int vs2005_cs(); + diff --git a/build/premake/src/Src/vs2005_cs.c b/build/premake/src/Src/vs2005_cs.c new file mode 100644 index 0000000000..ddbe57791b --- /dev/null +++ b/build/premake/src/Src/vs2005_cs.c @@ -0,0 +1,292 @@ +/********************************************************************** + * Premake - vs2005_cs.c + * The Visual Studio 2005 C# target + * + * Copyright (c) 2002-2006 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "vs.h" +#include "vs2005.h" + +static const char* listFiles(const char* name); +static const char* listReferences(const char* name); + + +int vs2005_cs() +{ + VsPkgData* data = (VsPkgData*)prj_get_data(); + int c; + + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj"))) + return 0; + + io_print("\n"); + io_print(" \n"); + + /* Write default configuration */ + prj_select_config(0); + io_print(" %s\n", prj_get_cfgname()); + io_print(" AnyCPU\n"); + io_print(" 8.0.50727\n"); + io_print(" 2.0\n"); + io_print(" {%s}\n", data->projGuid); + + io_print(" "); + if (prj_is_kind("winexe")) + io_print("WinExe"); + else if (prj_is_kind("exe")) + io_print("Exe"); + else if (prj_is_kind("dll") || prj_is_kind("aspnet")) + io_print("Library"); + else + { + printf("** Error: unknown package kind '%s'\n", prj_get_kind()); + return 0; + } + io_print("\n"); + + io_print(" Properties\n"); + io_print(" %s\n", path_getbasename(prj_get_target())); + io_print(" %s\n", path_getbasename(prj_get_target())); + io_print(" \n"); + + for (c = 0; c < prj_get_numconfigs(); ++c) + { + prj_select_config(c); + + io_print(" \n", prj_get_cfgname()); + + if (!prj_has_flag("no-symbols")) + { + io_print(" true\n"); + io_print(" full\n"); + } + else + { + io_print(" pdbonly\n"); + } + + if (prj_has_flag("optimize") || prj_has_flag("optimize-size") || prj_has_flag("optimize-speed")) + io_print(" true\n"); + else + io_print(" false\n"); + + io_print(" %s\\\n", prj_get_outdir()); + + io_print(" "); + print_list(prj_get_defines(), "", "", ";", NULL); + io_print("\n"); + + io_print(" prompt\n"); + io_print(" 4\n"); + + if (prj_has_flag("unsafe")) + io_print(" true\n"); + + if (prj_has_flag("fatal-warnings")) + io_print(" true\n"); + + io_print(" \n"); + } + + /* Must use same references for all configurations */ + prj_select_config(0); + io_print(" \n"); + print_list(prj_get_links(), "", "", "", listReferences); + io_print(" \n"); + + io_print(" \n"); + print_list(prj_get_files(), "", "", "", listFiles); + io_print(" \n"); + + io_print(" \n"); + io_print(" \n"); + io_print("\n"); + + io_closefile(); + + /* Now write the .csproj.user file for non-web applications or + * .csproj.webinfo for web applications */ + if (!prj_is_kind("aspnet")) + { + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj.user"))) + return 0; + + io_print("\n"); + io_print(" \n"); + io_print(" "); + + strcpy(g_buffer, io_getcwd()); + io_chdir(prj_get_pkgpath()); + print_list(prj_get_libpaths(), "", ";", "", vs_list_refpaths); + io_print(vs_list_refpaths(prj_get_bindir())); + io_chdir(g_buffer); + + io_print("\n"); + io_print(" \n"); + io_print("\n"); + } + else + { + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "csproj.webinfo"))) + return 0; + } + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Checks each entry in the list of package links. If the entry refers + * to a sibling package, returns the path to that package's output + ***********************************************************************/ + +static const char* listReferences(const char* name) +{ + /* Is this a sibling package? */ + int i = prj_find_package(name); + if (i >= 0) + { + VsPkgData* data = (VsPkgData*)prj_get_data_for(i); + + strcpy(g_buffer, path_build(prj_get_pkgpath(), prj_get_pkgpath_for(i))); + io_print(" \n", path_translate(g_buffer, "windows"), name); + io_print(" {%s}\n", data->projGuid); + io_print(" %s\n", name); + io_print(" \n"); + } + else + { + io_print(" \n", name); + } + + return NULL; +} + + +/************************************************************************ + * Builds an entry for each file in the project + ***********************************************************************/ + +static const char* listFiles(const char* name) +{ + const char* related; + + /* If a build action was specified, use it */ + prj_select_file(name); + if (prj_get_buildaction() != NULL) + { + if (matches(prj_get_buildaction(), "Content")) + { + io_print(" \n", path_translate(name, "windows")); + io_print(" PreserveNewest\n"); + io_print(" \n"); + } + else + { + io_print(" <%s Include=\"%s\" />\n", prj_get_buildaction(), path_translate(name, "windows")); + } + return NULL; + } + + if (endsWith(name, ".cs")) + { + int fullstop = 0; + io_print(" \n %s\n", path_getname(g_buffer)); + fullstop = 1; + } + else + { + /* ...look for a .resx dependency */ + strcpy(g_buffer, path_swapextension(name, ".Designer.cs", ".resx")); + if (prj_has_file(g_buffer)) + { + io_print(">\n True\n"); + io_print(" %s\n", path_getname(g_buffer)); + fullstop = 1; + } + } + } + else + { + /* If a matching ".Designer.cs" exists, mark this as a Form */ + related = path_swapextension(name, ".cs", ".Designer.cs"); + if (prj_has_file(related)) + { + io_print(">\n Form\n"); + fullstop = 1; + } + } + io_print(fullstop ? " \n" : " />\n"); + } + else if (endsWith(name, ".resx")) + { + int fullstop = 0; + io_print(" \n"); + + /* Is this related to a form? */ + related = path_swapextension(name, ".resx", ".Designer.cs"); + if (prj_has_file(related)) + io_print(" Designer\n"); + io_print(" %s\n", path_getname(g_buffer)); + } + else + { + /* If no .cs but .Designer.cs then auto-generated */ + strcpy(g_buffer, path_swapextension(name, ".resx", ".Designer.cs")); + if (prj_has_file(g_buffer)) + { + fullstop = 1; + io_print(">\n"); + + io_print(" Designer\n"); + io_print(" ResXFileCodeGenerator\n"); + io_print(" %s\n", path_getname(g_buffer)); + } + } + io_print(fullstop ? " \n" : " />\n"); + } + else + { + io_print(" \n", path_translate(name, "windows")); + } + + return NULL; +} + diff --git a/build/premake/src/Src/vs6.c b/build/premake/src/Src/vs6.c new file mode 100644 index 0000000000..ba9f5c1ad6 --- /dev/null +++ b/build/premake/src/Src/vs6.c @@ -0,0 +1,135 @@ +/********************************************************************** + * Premake - vs6.c + * The Visual C++ 6 target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "vs6.h" + +static int writeWorkspace(); + +static const char* listPackageDeps(const char* name); + + +int vs6_generate() +{ + int i; + + puts("Generating Visual Studio 6 workspace and project files:"); + + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + + printf("...%s\n", prj_get_pkgname()); + + if (prj_is_lang("c++") || prj_is_lang("c")) + { + vs6_cpp(); + } + else if (prj_is_lang("c#")) + { + puts("** Error: C# projects are not supported by Visual Studio 6"); + return 0; + } + else + { + printf("** Error: unrecognized language '%s'\n", prj_get_language()); + return 0; + } + } + + return writeWorkspace(); +} + + +static int writeWorkspace() +{ + int i; + + if (!io_openfile(path_join(prj_get_path(), prj_get_name(), "dsw"))) + return 0; + + io_print("Microsoft Developer Studio Workspace File, Format Version 6.00\n"); + io_print("# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n"); + io_print("\n"); + io_print("###############################################################################\n"); + io_print("\n"); + + for (i = 0; i < prj_get_numpackages(); ++i) + { + prj_select_package(i); + + io_print("Project: \"%s\"=%s - Package Owner=<4>\n", prj_get_pkgname(), prj_get_pkgfilename("dsp")); + io_print("\n"); + io_print("Package=<5>\n"); + io_print("{{{\n"); + io_print("}}}\n"); + io_print("\n"); + io_print("Package=<4>\n"); + io_print("{{{\n"); + + /* Write package dependencies */ + prj_select_config(0); + print_list(prj_get_links(), "", "", "", listPackageDeps); + + io_print("}}}\n"); + io_print("\n"); + io_print("###############################################################################\n"); + io_print("\n"); + } + + io_print("Global:\n"); + io_print("\n"); + io_print("Package=<5>\n"); + io_print("{{{\n"); + io_print("}}}\n"); + io_print("\n"); + io_print("Package=<3>\n"); + io_print("{{{\n"); + io_print("}}}\n"); + io_print("\n"); + io_print("###############################################################################\n"); + io_print("\n"); + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Checks if a package link matches the name of a sibling package. If + * so, generate a dependency on that sibling + ***********************************************************************/ + +static const char* listPackageDeps(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + strcpy(g_buffer, " Begin Project Dependency\n"); + strcat(g_buffer, " Project_Dep_Name "); + strcat(g_buffer, prj_get_pkgname_for(i)); + strcat(g_buffer, "\n"); + strcat(g_buffer, " End Project Dependency\n"); + return g_buffer; + } + else + { + return NULL; + } +} diff --git a/build/premake/src/Src/vs6.h b/build/premake/src/Src/vs6.h new file mode 100644 index 0000000000..164968ef4b --- /dev/null +++ b/build/premake/src/Src/vs6.h @@ -0,0 +1,20 @@ +/********************************************************************** + * Premake - vs6.h + * The Visual C++ 6 target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +int vs6_generate(); + +int vs6_cpp(); diff --git a/build/premake/src/Src/vs6_cpp.c b/build/premake/src/Src/vs6_cpp.c new file mode 100644 index 0000000000..8de9488170 --- /dev/null +++ b/build/premake/src/Src/vs6_cpp.c @@ -0,0 +1,344 @@ +/********************************************************************** + * Premake - vs6_cpp.c + * The Visual C++ 6 C/C++ target + * + * Copyright (c) 2002-2005 Jason Perkins and the Premake project + * + * 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 2 + * 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 in the file LICENSE.txt for details. + **********************************************************************/ + +#include +#include +#include "premake.h" +#include "vs6.h" + +static void writeCppFlags(); +static void writeLinkFlags(); +static const char* filterLinks(const char* name); +static void listFiles(const char* path, int stage); + + +int vs6_cpp() +{ + const char* projTypeTag; + const char* projTypeId; + int i; + + /* Start the file */ + if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "dsp"))) + return 0; + + prj_select_config(0); + if (prj_is_kind("winexe")) + { + projTypeTag = "Win32 (x86) Application"; + projTypeId = "0x0101"; + } + else if (prj_is_kind("exe")) + { + projTypeTag = "Win32 (x86) Console Application"; + projTypeId = "0x0103"; + } + else if (prj_is_kind("dll")) + { + projTypeTag = "Win32 (x86) Dynamic-Link Library"; + projTypeId = "0x0102"; + } + else if (prj_is_kind("lib")) + { + projTypeTag = "Win32 (x86) Static Library"; + projTypeId = "0x0104"; + } + else + { + puts("** Error: unrecognized package type"); + return 0; + } + + io_print("# Microsoft Developer Studio Project File - Name=\"%s\" - Package Owner=<4>\n", prj_get_pkgname()); + io_print("# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"); + io_print("# ** DO NOT EDIT **\n"); + io_print("\n"); + io_print("# TARGTYPE \"%s\" %s\n", projTypeTag, projTypeId); + io_print("\n"); + + prj_select_config(0); + io_print("CFG=%s - Win32 %s\n", prj_get_pkgname(), prj_get_cfgname()); + + io_print("!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n"); + io_print("!MESSAGE use the Export Makefile command and run\n"); + io_print("!MESSAGE \n"); + io_print("!MESSAGE NMAKE /f \"%s.mak\".\n", prj_get_pkgname()); + io_print("!MESSAGE \n"); + io_print("!MESSAGE You can specify a configuration when running NMAKE\n"); + io_print("!MESSAGE by defining the macro CFG on the command line. For example:\n"); + io_print("!MESSAGE \n"); + io_print("!MESSAGE NMAKE /f \"%s.mak\" CFG=\"%s - Win32 %s\"\n", prj_get_pkgname(), prj_get_pkgname(), prj_get_cfgname()); + io_print("!MESSAGE \n"); + io_print("!MESSAGE Possible choices for configuration are:\n"); + io_print("!MESSAGE \n"); + + for (i = prj_get_numconfigs() - 1; i >= 0; --i) + { + prj_select_config(i); + io_print("!MESSAGE \"%s - Win32 %s\" (based on \"%s\")\n", prj_get_pkgname(), prj_get_cfgname(), projTypeTag); + } + + io_print("!MESSAGE \n"); + io_print("\n"); + io_print("# Begin Project\n"); + io_print("# PROP AllowPerConfigDependencies 0\n"); + io_print("# PROP Scc_ProjName \"\"\n"); + io_print("# PROP Scc_LocalPath \"\"\n"); + + io_print("CPP=cl.exe\n"); + if (!prj_is_kind("lib")) + io_print("MTL=midl.exe\n"); + io_print("RSC=rc.exe\n\n"); + + for (i = prj_get_numconfigs() - 1; i >= 0; --i) + { + const char* debugSymbol; + + int optimizeSize = prj_has_flag("optimize-size"); + int optimizeSpeed = prj_has_flag("optimize-speed") || prj_has_flag("optimize"); + int useDebugLibs = (!optimizeSize && !optimizeSpeed); + + prj_select_config(i); + + io_print("!%s \"$(CFG)\" == \"%s - Win32 %s\"\n\n", + (i == (prj_get_numconfigs() - 1) ? "IF" : "ELSEIF"), prj_get_pkgname(), prj_get_cfgname()); + + io_print("# PROP BASE Use_MFC 0\n"); + io_print("# PROP BASE Use_Debug_Libraries %d\n", useDebugLibs ? 1 : 0); + io_print("# PROP BASE Output_Dir \"%s\"\n", prj_get_outdir()); + io_print("# PROP BASE Intermediate_Dir \"%s\"\n", prj_get_objdir()); + io_print("# PROP BASE Target_Dir \"\"\n"); + io_print("# PROP Use_MFC 0\n"); + io_print("# PROP Use_Debug_Libraries %d\n", useDebugLibs ? 1 : 0); + io_print("# PROP Output_Dir \"%s\"\n", prj_get_outdir()); + io_print("# PROP Intermediate_Dir \"%s\"\n", prj_get_objdir()); + if (prj_is_kind("dll") && prj_has_flag("no-import-lib")) + io_print("# PROP Ignore_Export_Lib 1\n"); + io_print("# PROP Target_Dir \"\"\n"); + + io_print("# ADD BASE CPP /nologo"); + writeCppFlags(); + io_print("# ADD CPP /nologo"); + writeCppFlags(); + + debugSymbol = prj_has_flag("no-symbols") ? "NDEBUG" : "_DEBUG"; + if (prj_is_kind("winexe") || prj_is_kind("dll")) + { + io_print("# ADD BASE MTL /nologo /D \"%s\" /mktyplib203 /win32\n", debugSymbol); + io_print("# ADD MTL /nologo /D \"%s\" /mktyplib203 /win32\n", debugSymbol); + } + + io_print("# ADD BASE RSC /l 0x409 /d \"%s\"\n", debugSymbol); + io_print("# ADD RSC /l 0x409 /d \"%s\"\n", debugSymbol); + io_print("BSC32=bscmake.exe\n"); + io_print("# ADD BASE BSC32 /nologo\n"); + io_print("# ADD BSC32 /nologo\n"); + + if (prj_is_kind("lib")) + { + io_print("LINK32=link.exe -lib\n"); + io_print("# ADD BASE LIB32 /nologo\n"); + io_print("# ADD LIB32 /nologo\n"); + } + else + { + io_print("LINK32=link.exe\n"); + io_print("# ADD BASE LINK32"); + writeLinkFlags(); + io_print("# ADD LINK32"); + writeLinkFlags(); + } + + io_print("\n"); + } + + io_print("!ENDIF\n"); + io_print("\n"); + io_print("# Begin Target\n"); + io_print("\n"); + + for (i = prj_get_numconfigs() - 1; i >= 0; --i) + { + prj_select_config(i); + io_print("# Name \"%s - Win32 %s\"\n", prj_get_pkgname(), prj_get_cfgname()); + } + + print_source_tree("", listFiles); + + io_print("# End Target\n"); + io_print("# End Project\n"); + + io_closefile(); + return 1; +} + + +/************************************************************************ + * Writes compiler flags for current configuration + ***********************************************************************/ + +static void writeCppFlags() +{ + int optimizeSize = prj_has_flag("optimize-size"); + int optimizeSpeed = prj_has_flag("optimize-speed") || prj_has_flag("optimize"); + int useDebugLibs = (!optimizeSize && !optimizeSpeed); + + if (useDebugLibs) + io_print(prj_has_flag("static-runtime") ? " /MTd" : " /MDd"); + else + io_print(prj_has_flag("static-runtime") ? " /MT" : " /MD"); + + io_print(" /W%d", prj_has_flag("extra-warnings") ? 4 : 3); + + if (prj_has_flag("fatal-warnings")) + io_print(" /WX"); + + if (useDebugLibs) + io_print(" /Gm"); /* minimal rebuild */ + + if (!prj_has_flag("no-rtti")) + io_print(" /GR"); + + if (!prj_has_flag("no-exceptions")) + io_print(" /GX"); + + if (!prj_has_flag("no-symbols")) + io_print(" /ZI"); /* debug symbols for edit-and-continue */ + + if (optimizeSize) + io_print(" /O1"); + else if (optimizeSpeed) + io_print(" /O2"); + else + io_print(" /Od"); + + if (prj_has_flag("no-frame-pointer")) + io_print(" /Oy"); + + print_list(prj_get_incpaths(), " /I \"", "\"", "", NULL); + print_list(prj_get_defines(), " /D \"", "\"", "", NULL); + + io_print(" /YX /FD"); + + if (!optimizeSize && !optimizeSpeed) + io_print(" /GZ"); + + io_print(" /c"); + + print_list(prj_get_buildoptions(), " ", "", "", NULL); + + io_print("\n"); +} + + +/************************************************************************ + * Writes linker flags for current configuration + ***********************************************************************/ + +static void writeLinkFlags() +{ + print_list(prj_get_links(), " ", ".lib", "", filterLinks); + io_print(" /nologo"); + + if ((prj_is_kind("winexe") || prj_is_kind("exe")) && !prj_has_flag("no-main")) + io_print(" /entry:\"mainCRTStartup\""); + + if (prj_is_kind("winexe")) + io_print(" /subsystem:windows"); + else if (prj_is_kind("exe")) + io_print(" /subsystem:console"); + else + io_print(" /dll"); + + if (!prj_has_flag("no-symbols")) + io_print(" /incremental:yes /debug"); + + io_print(" /machine:I386"); + + if (prj_is_kind("dll")) + { + io_print(" /implib:\""); + if (prj_has_flag("no-import-lib")) + io_print(prj_get_objdir()); + else + io_print(prj_get_libdir()); + io_print("/%s.lib\"", path_getbasename(prj_get_target())); + } + + io_print(" /out:\"%s\"", prj_get_target()); + + if (!prj_has_flag("no-symbols")) + io_print(" /pdbtype:sept"); + + io_print(" /libpath:\"%s\"", prj_get_libdir()); + print_list(prj_get_libpaths(), " /libpath:\"", "\"", "", NULL); + print_list(prj_get_linkoptions(), " ", "", "", NULL); + + io_print("\n"); +} + + +/************************************************************************ + * Checks each entry in the list of package links. If the entry refers + * to a sibling package, returns the path to that package's output + ***********************************************************************/ + +static const char* filterLinks(const char* name) +{ + int i = prj_find_package(name); + if (i >= 0) + { + /* If this is a sibling package, don't return anything. VC6 + * links to dependent projects implicitly */ + return NULL; + } + else + { + return name; + } +} + + +/************************************************************************ + * Callback for print_source_tree() + ***********************************************************************/ + +static void listFiles(const char* path, int stage) +{ + const char* ptr = strrchr(path, '/'); + ptr = (ptr == NULL) ? path : ptr + 1; + + switch (stage) + { + case WST_OPENGROUP: + if (strlen(path) > 0 && strcmp(ptr, "..") != 0) { + io_print("# Begin Group \"%s\"\n\n", ptr); + io_print("# PROP Default_Filter \"\"\n"); + } + break; + case WST_CLOSEGROUP: + if (strlen(path) > 0 && strcmp(ptr, "..") != 0) + io_print("# End Group\n"); + break; + case WST_SOURCEFILE: + io_print("# Begin Source File\n\n"); + io_print("SOURCE=%s\n", path); + io_print("# End Source File\n"); + break; + } +} + diff --git a/build/premake/src/premake.lua b/build/premake/src/premake.lua new file mode 100644 index 0000000000..aca16ce3b0 --- /dev/null +++ b/build/premake/src/premake.lua @@ -0,0 +1,21 @@ +project.name = "Premake" + +-- Options + + addoption("with-tests", "Include the unit tests (requires NUnit)") + +-- Project Settings + + project.bindir = "bin" + + dopackage("Src") + if (options["with-tests"]) then + dopackage("Tests") + end + +-- A little extra cleanup + + function doclean(cmd, arg) + docommand(cmd, arg) + os.rmdir("bin") + end