1
0
forked from 0ad/0ad

Import Premake4 source (rev fc0374a03b17), minus samples/ and packages/

This was SVN commit r9828.
This commit is contained in:
Ykkrosh 2011-07-15 17:32:06 +00:00
parent 8eb7af4ac9
commit fcab9e3b5e
223 changed files with 48861 additions and 0 deletions

View File

@ -0,0 +1,123 @@
PREMAKE BUILD INSTRUCTIONS
Premake is written in a mix of C and Lua. This mix enables many new
features, but also makes building Premake a bit more complicated than
your typical application.
If you downloaded a source code package from SourceForge (as opposed
to pulling the sources from the repository), you will find project
files for all of the currently supported toolsets in the build/ folder.
Build the release configuration (the default for the makefiles) and you
will find the executable in bin/release ready to go.
If you want to use a debug build instead, or if you pulled the sources
from BitBucket instead of a SourceForge release, or if you plan on
making changes to Premake, read the next section to learn how to
prepare the project files.
If you find all of this very confusing and need some help, see the end
of this document for contact information. I'll be glad to help. And if
you have any suggestions for improving this process, we'd be glad to
hear them too.
GENERATING THE PROJECT FILES
If you downloaded a source code package from SourceForge, the project
files are already included (in build/) and you can skip ahead to the
next section.
If you pulled the sources from BitBucket, you'll need to generate your
own project files before you can build.
We use Premake to generate the project files for Premake (bootstrapping,
or eating our own dog food). So in order to generate the project files,
you need to have a working version of Premake 4.x installed on your
system. You can get it as source code (with pre-generated project files
ready to build) or a prebuilt binary from the SourceForge download page.
Once you have a working Premake 4.x installed, the first thing you need
to do is to embed the Lua scripts into the application by running this
command in the top-level Premake directory:
premake4 embed
This creates a C file (at src/host/scripts.c) which contains all of the
Lua scripts as static string buffers. These then get compiled into the
executable, which is how we get away with shipping a single file instead
of one executable and whole bunch of scripts. See EMBEDDING THE SCRIPTS,
below, for more information.
Now you can generate project files for your toolset of choice by running
a command like:
premake4 gmake -- for GNU makefiles using GCC
premake4 vs2008 -- for a Visual Studio 2008 solution
Use the "--help" option to see all of the available targets.
This will create a solution/makefile/workspace in the top-level folder,
which you can now go ahead and build.
RELEASE vs. DEBUG BUILDS
Premake can be built in either "release" or "debug" modes. Makefile users
can choose which configuration to build with the "config" argument:
make config=debug -- build in debug mode
make config=release -- build in release mode
IDEs like Visual Studio provide their own mechanism for switching build
configurations.
In release mode you can build and run Premake like any other C application
(once you've embedded the scripts, see the next section).
In debug mode, Premake ignores the embedded Lua scripts and instead reads the
latest versions from the disk at runtime. This allows you to change a script,
and then immediately test it without having to embed or compile first. Speedy!
But Premake needs some help to find the scripts.
You can specify the location of the scripts in one of two ways: using
the /scripts command line argument, like so:
premake4 /scripts=~/Code/premake4/src gmake
Or by setting a PREMAKE_PATH environment variable.
PREMAKE_PATH=~/Code/premake4/src
As you can see, you need to specify the location of the Premake "src"
directory, the one containing "_premake_main.lua".
EMBEDDING THE SCRIPTS
One of the nice things about Premake is that it comes as a single file,
easy to install or move around. To manage this, we need to embed all of
the Lua scripts into the executable, so we can deliver just the one file,
rather than an executable and a whole bunch of scripts.
Scripts are embedded by running the command
premake4 embed
This copies all of the scripts listed in _manifest.lua into the file
src/host/scripts.c, where they are represented as a set of static C
string buffers. This file is then compiled as part of Premake's release
builds.
So: very important to embed the scripts before each release build!
CONFUSED?
I'll be glad to help you out. Stop by the main project website where
you can leave a note in the forums (the preferred approach), join the
mailing list, or contact me directly.
http://industriousone.com/premake
Enjoy!

View File

@ -0,0 +1,547 @@
-------
4.3.1 (in progress)
-------
* Bug 3119793: Fixed ClCompile blocks with vs10 and PCH (Dan Dunham)
* Bug 2920784: Symbol visibility in Xcode3 libraries (burnson2)
* Bug 3133743: Sets ONLY_ACTIVE_ARCH = YES in Xcode debug builds (James Wynn)
* Properly pass return codes back to shell in release builds
* Bug 3135734: Remove WholeProgramOptimization setting in vs10 (doug)
* Bug 3138377: Link dependencies ignored within "SharedLib" configuration
-------
4.3
-------
* CHANGED LICENSE FROM GPLv2 TO BSD
* Added Visual Studio 2010 C/C++ support (Liam Devine)
* Added Solaris support (Dean Ross-Smith)
* Added deployment and image options for Xbox360 (dvoid)
* Patch 2963313: Enable setting .NET framework version (Justen Hyde)
* Patch 2965229: Fix handling of '+' symbol in file patterns (Rachel Blum)
* Patch 2997449: Print configuration with target (ergosys)
* Patch 2997452: Suppress gmake's "nothing to be done" message (ergosys)
* Patch 3011940: Add support for MFC (JTAnderson)
* Patch 3053959: kind() crashes when called with no arguments (rjmyst3)
* Bug 2997728: Project dependencies should be case-sensitive
* Bug 3056381: Xcode project breaks on special chars
* Bug 3007101: Generating PDB in Release builds is not supported
* Bug 2971841: Gmake escaping of shell variable $(...) is broken
* Fixed handling of icons in Xcode (bitshifter)
* Added imagepath to set Xbox360 image file name (Jarod)
* Patch 3063804: Set CompileAs flag for VS200x C projects (rjmyst3)
* Implemented StaticRuntime flag for Xcode (William Burnson)
* Improved portability of Mac OS X binaries (William Burnson)
* Bug 3035545: The pattern { "./folder/*.c" } matches no files
* Bug 3034222: StaticLib projects ignore linkoptions
* Bug 3020382: GCC PCH not working
* Bug 3016050: {"../Dir/file1.c","../../Dir/file2.c"} breaks Xcode (Stephane)
* Bug 3015312: Makefiles are not quoted correctly
* Bug 3097868: Removes relative paths from vs2010 filters (Robert Konrad)
* Bug 3095274: Pre-compiled header support missing for VS2010 target
* Bug 3100062: vs2010 Runtime library selection
-------
4.2.1
-------
* Feature 2944697: Add flag to disable Minimal Rebuild in Visual Studio
* Patch 2928029: Add EnableSSE, EnableSSE2 flags
* Patch 2936443: Expose configuration terms to scripts (Laurent Humbertclaude)
* Bug 2928775: Error loading external Lua module with require()
* Bug 2942438: Wrong runtime library linked
* Bug 2931722: pchheader handling not consistent between tools
* Bug 2958829: Files pattern matching including too many files
* Bug 2953594: includedirs / libdirs converting absolute paths to relative
* Bug 2936188: Improve handling for invalid values in lists
-----
4.2
-----
- Feature 1526976: Add support for Apple Xcode 3
- Feature 2900623: Add targetsuffix and implibsuffix properties
- Added project kind to list of configuration filters
- Feature 2839002: Add gcc switch to improve header dependency generation (Johannes Spohr)
- Feature 2832906: Global variable (_SCRIPT) for current script path
- Feature 2905303: Enable better folder matching in file lists
- Feature 2919629: Add help target for makefiles
- Feature 2820644: Add Xbox360 deployment and image options
- Bug 2909463: Fix Xcode handling of Obj-C++ .mm files
- Bug 2903430: Using relative instead of absolute paths with $() macro
- Bug 2910691: Duplicate build options
- Bug 2910639: Nil reference on dylib project dependency
- Bug 2872066: Two test failures in 4.1.2
- Bug 2912756: dylibs missing lib prefix
- Bug 2910202: Code::Blocks building C files as C++
- Bug 2926917: Use target name for Visual Studio PDB file
- Bug 2927604: Unable to build Premake with Visual Studio
- Clean action now removes MonoDevelop .pidb files correctly
- Added os.executef()
-------
4.1.2
-------
- Fixed ManagedExtension setting for Visual Studio
- Fixed os.match() bug for large result sets (David Raulo)
- Patch 2840052: Order problem of static link
- Patch 2802722: Floating Point Model Flags (Suigintou)
- Patch 2865333: Support for ObjC and ObjC++ sources (Johannes Spohr)
- Patch 2832852: Fix descriptions in cmd help (Sebastian Schuberth)
- Patch 2832848: Show default script name in help (Sebastian Schuberth)
-------
4.1.1
-------
- Use libtool instead of ar for Mac OS X Universal static libraries
- Fixed Xbox 360 linker settings in Visual Studio
- Remove platform-specific intermediate objects on clean
- Bug 2819232: Buildoptions not used when creating Makefile for C#
- Bug 2813297: OS X universal config should be "univ" (William Burnson)
- Bug 2814179: Xbox 360 precompiled headers not working
-----
4.1
-----
- Added support for cross-compiling target platforms
- Added Xbox 360 support to Visual Studio 2005/2008
- Added Mac OS X universal binary support
- Added Playstation 3 support
- Added precompiled header support for GCC
- Support links and libdirs for Visual Studio static libraries
- Fail gracefully when list is assigned to string field
- Changed GCC flags to -fno-exceptions and -fno-rtti
- Improved performance of configuration building step
- Fixed crash when configuration is missing a kind
- Patch 2031626: Support for additional manifest files (Colin Graf)
- Patch 2558089: workaround for --as-needed/correct link order (idl0r)
- Patch 2609028: verbose linking in makefile (kaidokert)
- Bug 2564404: FatalWarnings has no effect with gmake target
- Bug 2550759: pchheader option has wrong type
- Bug 1900333: Parentheses in build path
- Bug 2790865: SharedLib on OSX fixes (Ash Berlin)
- Bug 2790882: Trailing slash in path.getabsolute (Ash Berlin)
RC2 -> RC3
- Bug 2805763: GCC PCH breaks on path
- Bug 2709641: Location field does not propagate to projects
- Bug 2675518: Dependencies wrong on config links
- Bug 2152526: Code::Blocks doesn't build PCH correctly on GCC
RC1 -> RC2
- Removed additional MonoDevelop files in clean action
- Fixed naming of system libraries in Visual Studio link step
- Set OS to Windows when generating for Visual Studio
- Bug 2801257: Linker error LNK1112 when cross-compiling for x64
-----
4.0
-----
This version is a complete rewrite of Premake.
- A new, more readable and extensible syntax for projects
- More robust syntax validation
- A new command-line format, with better argument validation
- Improved path handling across all project settings
- Upgraded to Lua 5.1.4
- Many, many bug fixes
RC4 -> Final
- Set Mac OS X linker flags for Code::Blocks
- Bug 2533504: Files above project root not added to project
RC3 -> RC4
- Embed scripts instead of bytecodes to avoid portability issues
- solution() and project() now only set the active object when
called with a name; remains unchanged otherwise
RC2 -> RC3
- Bug: GCC Windows release builds of Premake4 crash on script errors
- Patched Lua to load precompiled bytecodes on PPC architectures.
- Display paths of generated files
RC1 -> RC2
- Enabled use of absolute Windows paths to different drive letter
- Bug: Post-build commands run before build on Code::Blocks
- Removed FatalWarnings build flag
- Fixed GCC 4.2 warnings (Ryan Pusztai)
- Enable Windows linking to shared libraries even with NoImportLib
flag set (just in case)
- Fixed handling of paths in links
- Added "ToolsVersion" attribute to VS2005 and VS2008 C# projects
- Fixed separator between library dependencies in C++ makefiles
- Added missing os.copyfile() function
- Bug: Sometimes takes a long time to complete on Linux
- Enabled Lua popen support on Linux and Mac OS X
-----
3.7
-----
- Updated Lua to 5.1.3
- Added new CodeLite support target (Ryan Pusztai)
- Added new cb-ow (Code::Blocks Open Watcom) target (Tim Channon)
- Place OSX winexe's into Content/MacOS folder (William Burnson)
- Sibling executables may now be listed in package.links
- Bug 1520012: Improper Makefiles when filenames have spaces
(Diaa Sami)
- Bug 2045506: "no-exceptions" flag ignored for VS200x (Benoit Miller)
- Bug 2034470: Error in cmd line error handler
- Bug 2114152: package or config table isn't generated automatically
-----
3.6
-----
- Patch 1946122: Add support for VS2008 (Ryan Pusztai)
- Patch 1913448: Win32 crash when using '--clean --usetargetpath'
(David Walters)
- Patch 1771168: luaL_getn speed optimization (Richard O'Grady)
- Bug 1939089: Premake segfault on Linux/PPC (Fabio Till)
- Fixed "bad argument #2 to 'chdir'" error
- Disable -MMD on multiple -arch flags (poor man's Universal binary
support)
-----
3.5
-----
- Prevent creation of import libraries on OS X
- Improved handling of dylibs on OS X
- Patch 1771977: Ability to compile C source as C++ in Code::Blocks
(Ryan Pusztai)
- Bug 1804810: out-implib not present in linux gnu compler toolchain
- Bug 1806949: .Net reference paths are broken when bindir is specified
- Bug 1806960: Make clean does not remove .mdb files
- Bug 1831389: Makefiles stored in subdirs contain no targets on
first run
-----
3.4
-----
- Added `no-pch` flag to suppress precompiled headers
- Added App.config support to GNU makefiles
- Add os.mkdir() to script environment
- Makefile now creates target directory before copying .NET references
- Feature 1520182: Enhanced file-handling functions
- Bug 531878: Problems with relative paths
- Bug 1723867: Config-specific post-build on GNU target (Benoit Miller)
- Bug 1596826: XML targets doesn't escape xml entities
- Bug 1600155: Core dump due to newpackage() and matchfiles()
- Bug 1608895: resgen command shown
- Bug 1639730: Output filename is not set
- Bug 1729227: non-portable executable with relative library path
- Bug 1559951: default clean rule removes package dir
- Patch 1733674: PCH support for Code::Block targets (Ryan Pusztai)
- Patch 1746563: Ability to specify GUID for VS targets (Ryan Pusztai)
- Patch 1754867: Creating import lib of different name (Ryan Pusztai)
-----
3.3
-----
- Added support for prebuild, prelink, and postbuild commands
- Added `target` global variable to script environment
- Added build flag `no-edit-and-continue`
- Added build flags `native-wchar` and `no-native-wchar`
- Added build flag `no-manifest`
- Added build flag `seh-exceptions` (VS2005 only)
- Added `resdefines`, `respaths`, and `resoptions`
- Added `prebuildcommands`, `prelinkcommands`, and `postbuildcommands`
- Added `pchheader` and `pchsource` (Visual Studio only)
- Feature 1337547: Package-level bindir and libdir
- Bug 1565755: Generated makefiles do not work with MSYS
- Bug 1587955: Target path ignored for libs
- Bug 1574725: Static library extension for "gnu" target
- Bug 1522861: Fixed by using "ar -rcs" instead of "ar -cr && ranlib"
- Bug 1656816: Mkdir set wrong directory rights
- Bug 1655595: Compile/build problem on FreeBSD
- Bug: "gnu" clean rule doesn't work in cmd.exe
- Improved behavior of Linux findlib()
- Updated Code::Blocks support to latest project version
(major="1" minor="6")
- Patch 1681666: GNU targets always show the console if kind = 'winexe'
-----
3.2
-----
- Added support for Code::Blocks
- Updated MonoDevelop support
- Upgraded Lua to 5.0.3
- Added new matchdirs() to Lua script environment
- Expose list of packages as _PACKAGES global in Lua
- Turn off edit-and-continue in release builds with symbols
- Bug 1559873: libpaths inserts extra space after -L
-----
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.

View File

@ -0,0 +1,27 @@
Copyright (c) 2003-2011 Jason Perkins and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the Premake nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,15 @@
PREMAKE
A build configuration tool
Copyright (C) 2002-2011 by Jason Perkins
Distributed under the terms of the BSD License, see LICENSE.txt
The Lua language and runtime library is (C) TeCGraf, PUC-Rio.
See their website at http://www.lua.org/
See the file BUILD.txt for instructions on building Premake.
For questions, comments, or more information, visit the project
website at http://industriousone.com/premake

View File

@ -0,0 +1,258 @@
# Doxyfile 1.5.1-p1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = "Premake Internals"
PROJECT_NUMBER =
OUTPUT_DIRECTORY = doc
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH = ""
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.d \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.idl \
*.odl \
*.cs \
*.php \
*.php3 \
*.inc \
*.m \
*.mm \
*.dox \
*.py
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */UnitTest++/* */lua-5.1.1/*
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View File

@ -0,0 +1,123 @@
--
-- Premake 4.x build configuration script
--
--
-- Define the project. Put the release configuration first so it will be the
-- default when folks build using the makefile. That way they don't have to
-- worry about the /scripts argument and all that.
--
solution "Premake4"
configurations { "Release", "Debug" }
location ( _OPTIONS["to"] )
project "Premake4"
targetname "premake4"
language "C"
kind "ConsoleApp"
flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" }
includedirs { "src/host/lua-5.1.4/src" }
files
{
"*.txt", "**.lua",
"src/**.h", "src/**.c",
"src/host/scripts.c"
}
excludes
{
"src/premake.lua",
"src/host/lua-5.1.4/src/lua.c",
"src/host/lua-5.1.4/src/luac.c",
"src/host/lua-5.1.4/src/print.c",
"src/host/lua-5.1.4/**.lua",
"src/host/lua-5.1.4/etc/*.c"
}
configuration "Debug"
targetdir "bin/debug"
defines "_DEBUG"
flags { "Symbols" }
configuration "Release"
targetdir "bin/release"
defines "NDEBUG"
flags { "OptimizeSize" }
configuration "vs*"
defines { "_CRT_SECURE_NO_WARNINGS" }
configuration "linux"
defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" }
links { "m", "dl" }
configuration "macosx"
defines { "LUA_USE_MACOSX" }
configuration { "macosx", "gmake" }
buildoptions { "-mmacosx-version-min=10.1" }
linkoptions { "-lstdc++-static", "-mmacosx-version-min=10.1" }
configuration { "not windows", "not solaris" }
linkoptions { "-rdynamic" }
configuration { "solaris" }
linkoptions { "-Wl,--export-dynamic" }
--
-- A more thorough cleanup.
--
if _ACTION == "clean" then
os.rmdir("bin")
os.rmdir("build")
end
--
-- Use the --to=path option to control where the project files get generated. I use
-- this to create project files for each supported toolset, each in their own folder,
-- in preparation for deployment.
--
newoption {
trigger = "to",
value = "path",
description = "Set the output location for the generated files"
}
--
-- Use the embed action to convert all of the Lua scripts into C strings, which
-- can then be built into the executable. Always embed the scripts before creating
-- a release build.
--
dofile("scripts/embed.lua")
newaction {
trigger = "embed",
description = "Embed scripts in scripts.c; required before release builds",
execute = doembed
}
--
-- Use the release action to prepare source and binary packages for a new release.
-- This action isn't complete yet; a release still requires some manual work.
--
dofile("scripts/release.lua")
newaction {
trigger = "release",
description = "Prepare a new release (incomplete)",
execute = dorelease
}

View File

@ -0,0 +1,57 @@
PREMAKE RELEASE CHECKLIST
-------------------------
VERSION NUMBERS
4.0
4.0-beta1
4.0-rc1
4.0.1
PREP
* Make sure all tests pass on Windows and POSIX
* Update CHANGELOG.txt as needed
* Prep release announcement for forums
* Run `premake4 embed`
* Commit all changes to premake-stable
* Tag premake-stable with the version number and push
* Pull changes to premake-dev
BUILD
* On each platform, run `premake4 release {version} binary`
* On one platform, run `premake4 release {version} source`
* If desired, copy binary to local path
* Upload packages (in release/) to SourceForge
RELEASE
* On SourceForge, set package properties (platform, etc.)
* Update the download page
http://industriousone.com/premake/download
* Post release announcement to the forums
* Update the Latest News on the project home page
* Post annoucement to @industrious on Twitter
* Post announcement to email list
* Post announcement to Industrious Facebook group
* Add release to Freshmeat
http://freshmeat.net/projects/premake

View File

@ -0,0 +1,96 @@
--
-- Embed the Lua scripts into src/host/scripts.c as static data buffers.
-- I embed the actual scripts, rather than Lua bytecodes, because the
-- bytecodes are not portable to different architectures, which causes
-- issues in Mac OS X Universal builds.
--
local function stripfile(fname)
local f = io.open(fname)
local s = f:read("*a")
f:close()
-- strip tabs
s = s:gsub("[\t]", "")
-- strip any CRs
s = s:gsub("[\r]", "")
-- strip out comments
s = s:gsub("\n%-%-[^\n]*", "")
-- escape backslashes
s = s:gsub("\\", "\\\\")
-- strip duplicate line feeds
s = s:gsub("\n+", "\n")
-- strip out leading comments
s = s:gsub("^%-%-\n", "")
-- escape line feeds
s = s:gsub("\n", "\\n")
-- escape double quote marks
s = s:gsub("\"", "\\\"")
return s
end
local function writeline(out, s, continues)
out:write("\t\"")
out:write(s)
out:write(iif(continues, "\"\n", "\",\n"))
end
local function writefile(out, fname, contents)
local max = 1024
out:write("\t/* " .. fname .. " */\n")
-- break up large strings to fit in Visual Studio's string length limit
local start = 1
local len = contents:len()
while start <= len do
local n = len - start
if n > max then n = max end
local finish = start + n
-- make sure I don't cut an escape sequence
while contents:sub(finish, finish) == "\\" do
finish = finish - 1
end
writeline(out, contents:sub(start, finish), finish < len)
start = finish + 1
end
out:write("\n")
end
function doembed()
-- load the manifest of script files
scripts = dofile("src/_manifest.lua")
-- main script always goes at the end
table.insert(scripts, "_premake_main.lua")
-- open scripts.c and write the file header
local out = io.open("src/host/scripts.c", "w+b")
out:write("/* Premake's Lua scripts, as static data buffers for release mode builds */\n")
out:write("/* DO NOT EDIT - this file is autogenerated - see BUILD.txt */\n")
out:write("/* To regenerate this file, run: premake4 embed */ \n\n")
out:write("const char* builtin_scripts[] = {\n")
for i,fn in ipairs(scripts) do
print(fn)
local s = stripfile("src/" .. fn)
writefile(out, fn, s)
end
out:write("\t0\n};\n");
out:close()
end

View File

@ -0,0 +1,214 @@
--
-- Prepare a new Premake release. This is still incomplete and some manual
-- work is needed to get everything packaged up. See RELEASE.txt in this
-- folder for the full checklist.
--
-- Info on using Mercurial to manage releases:
-- http://hgbook.red-bean.com/read/managing-releases-and-branchy-development.html
-- http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
--
function dorelease()
local z
local hgroot = "https://bitbucket.org/premake/premake-stable"
--
-- Helper function: runs a command (formatted, with optional arguments) and
-- suppresses any output. Works on both Windows and POSIX. Might be a good
-- candidate for a core function.
--
local function exec(cmd, ...)
cmd = string.format(cmd, unpack(arg))
local z = os.execute(cmd .. " > output.log 2> error.log")
os.remove("output.log")
os.remove("error.log")
return z
end
--
-- Make sure a version was specified
--
if #_ARGS ~= 2 then
error("** Usage: release [version] [source | binary]", 0)
end
local version = _ARGS[1]
local kind = _ARGS[2]
local pkgname = "premake-" .. version
--
-- Look for required utilities
--
local required = { "hg", "zip", "tar", "make", "gcc" }
for _, value in ipairs(required) do
z = exec("%s --version", value)
if z ~= 0 then
error("** '" .. value .. "' not found", 0)
end
end
--
-- Pre-release checklist
--
print( "")
print( "BEFORE RUNNING THIS SCRIPT follow the checklist in RELEASE.txt" )
print( "")
print( "Press [Enter] to begin.")
io .read()
---------------------------------------------------------------------------
--
-- Everything below this needs to be reworked for Mercurial
--
---------------------------------------------------------------------------
--
-- Check out the release tagged sources to releases/
--
print("Downloading release tag...")
os.mkdir("release")
os.chdir("release")
os.rmdir(pkgname)
z = exec( "hg clone -r %s %s %s", version, hgroot, pkgname)
if z ~= 0 then
error("** Failed to download tagged sources", 0)
end
os.chdir(pkgname)
--
-- Update the version number in premake.c
--
print("Updating version number...")
io.input("src/host/premake.c")
local text = io.read("*a")
text = text:gsub("HEAD", version)
io.output("src/host/premake.c")
io.write(text)
io.close()
--
-- Make absolutely sure the embedded scripts have been updated
--
print("Updating embedded scripts...")
z = exec("premake4 embed")
if z ~= 0 then
error("** Failed to update the embedded scripts", 0)
end
--
-- Generate source packaging
--
if kind == "source" then
--
-- Remove extra directories
--
print("Cleaning up the source tree...")
os.rmdir("samples")
os.rmdir("packages")
os.rmdir(".hg")
os.rmdir(".hgignore")
os.rmdir(".hgtags")
--
-- Generate project files to the build directory
--
print("Generating project files...")
exec("premake4 /to=build/vs2005 vs2005")
exec("premake4 /to=build/vs2008 vs2008")
exec("premake4 /to=build/vs2010 vs2010")
exec("premake4 /to=build/gmake.windows /os=windows gmake")
exec("premake4 /to=build/gmake.unix /os=linux gmake")
exec("premake4 /to=build/gmake.macosx /os=macosx /platform=universal32 gmake")
exec("premake4 /to=build/codeblocks.windows /os=windows codeblocks")
exec("premake4 /to=build/codeblocks.unix /os=linux codeblocks")
exec("premake4 /to=build/codeblocks.macosx /os=macosx /platform=universal32 codeblocks")
exec("premake4 /to=build/codelite.windows /os=windows codelite")
exec("premake4 /to=build/codelite.unix /os=linux codelite")
exec("premake4 /to=build/codelite.macosx /os=macosx /platform=universal32 codelite")
exec("premake4 /to=build/xcode3 /platform=universal32 xcode3")
--
-- Create source package
--
print("Creating source code package...")
os.chdir("..")
exec("zip -r9 %s-src.zip %s/*", pkgname, pkgname)
--
-- Create a binary package for this platform. This step requires a working
-- GNU/Make/GCC environment. I use MinGW on Windows.
--
else
print("Building platform binary release...")
exec("premake4 /platform=universal32 gmake")
exec("make config=%s", iif(os.is("macosx"), "releaseuniv32", "release"))
local fname
os.chdir("bin/release")
if os.is("windows") then
fname = string.format("%s-windows.zip", pkgname)
exec("zip -9 %s premake4.exe", fname)
else
fname = string.format("%s-%s.tar.gz", pkgname, os.get())
exec("tar czvf %s premake4", fname)
end
os.copyfile(fname, "../../../" .. fname)
os.chdir("../../..")
end
--
-- Upload files to SourceForge
--
--
-- Clean up
--
os.rmdir(pkgname)
print("")
print( "Finished.")
end

View File

@ -0,0 +1,71 @@
--
-- _manifest.lua
-- Manage the list of built-in Premake scripts.
-- Copyright (c) 2002-2010 Jason Perkins and the Premake project
--
-- The master list of built-in scripts. Order is important! If you want to
-- build a new script into Premake, add it to this list.
return
{
-- core files
"base/os.lua",
"base/path.lua",
"base/string.lua",
"base/table.lua",
"base/io.lua",
"base/globals.lua",
"base/action.lua",
"base/option.lua",
"base/tree.lua",
"base/solution.lua",
"base/project.lua",
"base/configs.lua",
"base/api.lua",
"base/cmdline.lua",
"tools/dotnet.lua",
"tools/gcc.lua",
"tools/msc.lua",
"tools/ow.lua",
"base/validate.lua",
"base/help.lua",
"base/premake.lua",
-- CodeBlocks action
"actions/codeblocks/_codeblocks.lua",
"actions/codeblocks/codeblocks_workspace.lua",
"actions/codeblocks/codeblocks_cbp.lua",
-- CodeLite action
"actions/codelite/_codelite.lua",
"actions/codelite/codelite_workspace.lua",
"actions/codelite/codelite_project.lua",
-- GNU make action
"actions/make/_make.lua",
"actions/make/make_solution.lua",
"actions/make/make_cpp.lua",
"actions/make/make_csharp.lua",
-- Visual Studio actions
"actions/vstudio/_vstudio.lua",
"actions/vstudio/vs2002_solution.lua",
"actions/vstudio/vs2002_csproj.lua",
"actions/vstudio/vs2002_csproj_user.lua",
"actions/vstudio/vs200x_vcproj.lua",
"actions/vstudio/vs2003_solution.lua",
"actions/vstudio/vs2005_solution.lua",
"actions/vstudio/vs2005_csproj.lua",
"actions/vstudio/vs2005_csproj_user.lua",
"actions/vstudio/vs_generic_solution.lua",
"actions/vstudio/vs2010_vcxproxj.lua",
-- Xcode action
"actions/xcode/_xcode.lua",
"actions/xcode/xcode_common.lua",
"actions/xcode/xcode_project.lua",
-- Clean action
"actions/clean/_clean.lua",
}

View File

@ -0,0 +1,154 @@
--
-- _premake_main.lua
-- Script-side entry point for the main program logic.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
local scriptfile = "premake4.lua"
local shorthelp = "Type 'premake4 --help' for help"
local versionhelp = "premake4 (Premake Build Script Generator) %s"
--
-- Inject a new target platform into each solution; called if the --platform
-- argument was specified on the command line.
--
local function injectplatform(platform)
if not platform then return true end
platform = premake.checkvalue(platform, premake.fields.platforms.allowed)
for sln in premake.solution.each() do
local platforms = sln.platforms or { }
-- an empty table is equivalent to a native build
if #platforms == 0 then
table.insert(platforms, "Native")
end
-- the solution must provide a native build in order to support this feature
if not table.contains(platforms, "Native") then
return false, sln.name .. " does not target native platform\nNative platform settings are required for the --platform feature."
end
-- add it to the end of the list, if it isn't in there already
if not table.contains(platforms, platform) then
table.insert(platforms, platform)
end
sln.platforms = platforms
end
return true
end
--
-- Script-side program entry point.
--
function _premake_main(scriptpath)
-- if running off the disk (in debug mode), load everything
-- listed in _manifest.lua; the list divisions make sure
-- everything gets initialized in the proper order.
if (scriptpath) then
local scripts = dofile(scriptpath .. "/_manifest.lua")
for _,v in ipairs(scripts) do
dofile(scriptpath .. "/" .. v)
end
end
-- Set up the environment for the chosen action early, so side-effects
-- can be picked up by the scripts.
premake.action.set(_ACTION)
-- Seed the random number generator so actions don't have to do it themselves
math.randomseed(os.time())
-- If there is a project script available, run it to get the
-- project information, available options and actions, etc.
local fname = _OPTIONS["file"] or scriptfile
if (os.isfile(fname)) then
dofile(fname)
end
-- Process special options
if (_OPTIONS["version"]) then
printf(versionhelp, _PREMAKE_VERSION)
return 1
end
if (_OPTIONS["help"]) then
premake.showhelp()
return 1
end
-- If no action was specified, show a short help message
if (not _ACTION) then
print(shorthelp)
return 1
end
-- If there wasn't a project script I've got to bail now
if (not os.isfile(fname)) then
error("No Premake script ("..scriptfile..") found!", 2)
end
-- Validate the command-line arguments. This has to happen after the
-- script has run to allow for project-specific options
action = premake.action.current()
if (not action) then
error("Error: no such action '" .. _ACTION .. "'", 0)
end
ok, err = premake.option.validate(_OPTIONS)
if (not ok) then error("Error: " .. err, 0) end
-- Sanity check the current project setup
ok, err = premake.checktools()
if (not ok) then error("Error: " .. err, 0) end
-- If a platform was specified on the command line, inject it now
ok, err = injectplatform(_OPTIONS["platform"])
if (not ok) then error("Error: " .. err, 0) end
-- work-in-progress: build the configurations
print("Building configurations...")
premake.buildconfigs()
ok, err = premake.checkprojects()
if (not ok) then error("Error: " .. err, 0) end
-- Hand over control to the action
printf("Running action '%s'...", action.trigger)
premake.action.call(action.trigger)
print("Done.")
return 0
end

View File

@ -0,0 +1,104 @@
--
-- _clean.lua
-- The "clean" action: removes all generated files.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.clean = { }
--
-- Clean a solution or project specific directory. Uses information in the
-- project object to build the target path.
--
-- @param obj
-- A solution or project object.
-- @param pattern
-- A filename pattern to clean; see premake.project.getfilename() for
-- a description of the format.
--
function premake.clean.directory(obj, pattern)
local fname = premake.project.getfilename(obj, pattern)
os.rmdir(fname)
end
--
-- Clean a solution or project specific file. Uses information in the project
-- object to build the target filename.
--
-- @param obj
-- A solution or project object.
-- @param pattern
-- A filename pattern to clean; see premake.project.getfilename() for
-- a description of the format.
--
function premake.clean.file(obj, pattern)
local fname = premake.project.getfilename(obj, pattern)
os.remove(fname)
end
--
-- Register the "clean" action.
--
newaction {
trigger = "clean",
description = "Remove all binaries and generated files",
onsolution = function(sln)
for action in premake.action.each() do
if action.oncleansolution then
action.oncleansolution(sln)
end
end
end,
onproject = function(prj)
for action in premake.action.each() do
if action.oncleanproject then
action.oncleanproject(prj)
end
end
if (prj.objectsdir) then
premake.clean.directory(prj, prj.objectsdir)
end
-- build a list of supported target platforms that also includes a generic build
local platforms = prj.solution.platforms or { }
if not table.contains(platforms, "Native") then
platforms = table.join(platforms, { "Native" })
end
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
premake.clean.directory(prj, cfg.objectsdir)
-- remove all permutations of the target binary
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "windows", "windows").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "posix", "linux").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "posix", "macosx").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "build", "posix", "PS3", "windows").fullpath)
if cfg.kind == "WindowedApp" then
premake.clean.directory(prj, premake.gettarget(cfg, "build", "posix", "posix", "linux").fullpath .. ".app")
end
-- if there is an import library, remove that too
premake.clean.file(prj, premake.gettarget(cfg, "link", "windows", "windows", "windows").fullpath)
premake.clean.file(prj, premake.gettarget(cfg, "link", "posix", "posix", "linux").fullpath)
-- call action.oncleantarget() with the undecorated target name
local target = path.join(premake.project.getfilename(prj, cfg.buildtarget.directory), cfg.buildtarget.basename)
for action in premake.action.each() do
if action.oncleantarget then
action.oncleantarget(target)
end
end
end
end
end
}

View File

@ -0,0 +1,38 @@
--
-- _codeblocks.lua
-- Define the Code::Blocks action(s).
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
newaction {
trigger = "codeblocks",
shortname = "Code::Blocks",
description = "Generate Code::Blocks project files",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++" },
valid_tools = {
cc = { "gcc", "ow" },
},
onsolution = function(sln)
premake.generate(sln, "%%.workspace", premake.codeblocks_workspace)
end,
onproject = function(prj)
premake.generate(prj, "%%.cbp", premake.codeblocks_cbp)
end,
oncleansolution = function(sln)
premake.clean.file(sln, "%%.workspace")
end,
oncleanproject = function(prj)
premake.clean.file(prj, "%%.cbp")
premake.clean.file(prj, "%%.depend")
premake.clean.file(prj, "%%.layout")
end
}

View File

@ -0,0 +1,138 @@
--
-- codeblocks_cbp.lua
-- Generate a Code::Blocks C/C++ project.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.codeblocks_cbp(prj)
-- alias the C/C++ compiler interface
local cc = premake.gettool(prj)
_p('<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>')
_p('<CodeBlocks_project_file>')
_p(1,'<FileVersion major="1" minor="6" />')
-- write project block header
_p(1,'<Project>')
_p(2,'<Option title="%s" />', premake.esc(prj.name))
_p(2,'<Option pch_mode="2" />')
_p(2,'<Option compiler="%s" />', _OPTIONS.cc)
-- build a list of supported target platforms; I don't support cross-compiling yet
local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native")
for i = #platforms, 1, -1 do
if premake.platforms[platforms[i]].iscrosscompiler then
table.remove(platforms, i)
end
end
-- write configuration blocks
_p(2,'<Build>')
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
_p(3,'<Target title="%s">', premake.esc(cfg.longname))
_p(4,'<Option output="%s" prefix_auto="0" extension_auto="0" />', premake.esc(cfg.buildtarget.fullpath))
_p(4,'<Option object_output="%s" />', premake.esc(cfg.objectsdir))
-- identify the type of binary
local types = { WindowedApp = 0, ConsoleApp = 1, StaticLib = 2, SharedLib = 3 }
_p(4,'<Option type="%d" />', types[cfg.kind])
_p(4,'<Option compiler="%s" />', _OPTIONS.cc)
if (cfg.kind == "SharedLib") then
_p(4,'<Option createDefFile="0" />')
_p(4,'<Option createStaticLib="%s" />', iif(cfg.flags.NoImportLib, 0, 1))
end
-- begin compiler block --
_p(4,'<Compiler>')
for _,flag in ipairs(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cc.getdefines(cfg.defines), cfg.buildoptions)) do
_p(5,'<Add option="%s" />', premake.esc(flag))
end
if not cfg.flags.NoPCH and cfg.pchheader then
_p(5,'<Add option="-Winvalid-pch" />')
_p(5,'<Add option="-include &quot;%s&quot;" />', premake.esc(cfg.pchheader))
end
for _,v in ipairs(cfg.includedirs) do
_p(5,'<Add directory="%s" />', premake.esc(v))
end
_p(4,'</Compiler>')
-- end compiler block --
-- begin linker block --
_p(4,'<Linker>')
for _,flag in ipairs(table.join(cc.getldflags(cfg), cfg.linkoptions)) do
_p(5,'<Add option="%s" />', premake.esc(flag))
end
for _,v in ipairs(premake.getlinks(cfg, "all", "directory")) do
_p(5,'<Add directory="%s" />', premake.esc(v))
end
for _,v in ipairs(premake.getlinks(cfg, "all", "basename")) do
_p(5,'<Add library="%s" />', premake.esc(v))
end
_p(4,'</Linker>')
-- end linker block --
-- begin resource compiler block --
if premake.findfile(cfg, ".rc") then
_p(4,'<ResourceCompiler>')
for _,v in ipairs(cfg.includedirs) do
_p(5,'<Add directory="%s" />', premake.esc(v))
end
for _,v in ipairs(cfg.resincludedirs) do
_p(5,'<Add directory="%s" />', premake.esc(v))
end
_p(4,'</ResourceCompiler>')
end
-- end resource compiler block --
-- begin build steps --
if #cfg.prebuildcommands > 0 or #cfg.postbuildcommands > 0 then
_p(4,'<ExtraCommands>')
for _,v in ipairs(cfg.prebuildcommands) do
_p(5,'<Add before="%s" />', premake.esc(v))
end
for _,v in ipairs(cfg.postbuildcommands) do
_p(5,'<Add after="%s" />', premake.esc(v))
end
_p(4,'</ExtraCommands>')
end
-- end build steps --
_p(3,'</Target>')
end
end
_p(2,'</Build>')
-- begin files block --
local pchheader
if (prj.pchheader) then
pchheader = path.getrelative(prj.location, prj.pchheader)
end
for _,fname in ipairs(prj.files) do
_p(2,'<Unit filename="%s">', premake.esc(fname))
if path.isresourcefile(fname) then
_p(3,'<Option compilerVar="WINDRES" />')
elseif path.iscfile(fname) and prj.language == "C++" then
_p(3,'<Option compilerVar="CC" />')
end
if not prj.flags.NoPCH and fname == pchheader then
_p(3,'<Option compilerVar="%s" />', iif(prj.language == "C", "CC", "CPP"))
_p(3,'<Option compile="1" />')
_p(3,'<Option weight="0" />')
_p(3,'<Add option="-x c++-header" />')
end
_p(2,'</Unit>')
end
-- end files block --
_p(2,'<Extensions />')
_p(1,'</Project>')
_p('</CodeBlocks_project_file>')
_p('')
end

View File

@ -0,0 +1,27 @@
--
-- codeblocks_workspace.lua
-- Generate a Code::Blocks workspace.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.codeblocks_workspace(sln)
_p('<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>')
_p('<CodeBlocks_workspace_file>')
_p(1,'<Workspace title="%s">', sln.name)
for prj in premake.solution.eachproject(sln) do
local fname = path.join(path.getrelative(sln.location, prj.location), prj.name)
local active = iif(prj.project == sln.projects[1], ' active="1"', '')
_p(2,'<Project filename="%s.cbp"%s>', fname, active)
for _,dep in ipairs(premake.getdependencies(prj)) do
_p(3,'<Depends filename="%s.cbp" />', path.join(path.getrelative(sln.location, dep.location), dep.name))
end
_p(2,'</Project>')
end
_p(1,'</Workspace>')
_p('</CodeBlocks_workspace_file>')
end

View File

@ -0,0 +1,40 @@
--
-- _codelite.lua
-- Define the CodeLite action(s).
-- Copyright (c) 2008-2009 Jason Perkins and the Premake project
--
newaction {
trigger = "codelite",
shortname = "CodeLite",
description = "Generate CodeLite project files",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++" },
valid_tools = {
cc = { "gcc" },
},
onsolution = function(sln)
premake.generate(sln, "%%.workspace", premake.codelite_workspace)
end,
onproject = function(prj)
premake.generate(prj, "%%.project", premake.codelite_project)
end,
oncleansolution = function(sln)
premake.clean.file(sln, "%%.workspace")
premake.clean.file(sln, "%%_wsp.mk")
premake.clean.file(sln, "%%.tags")
end,
oncleanproject = function(prj)
premake.clean.file(prj, "%%.project")
premake.clean.file(prj, "%%.mk")
premake.clean.file(prj, "%%.list")
premake.clean.file(prj, "%%.out")
end
}

View File

@ -0,0 +1,146 @@
--
-- codelite_project.lua
-- Generate a CodeLite C/C++ project file.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.codelite_project(prj)
_p('<?xml version="1.0" encoding="utf-8"?>')
_p('<CodeLite_Project Name="%s">', premake.esc(prj.name))
premake.walksources(prj, premake.codelite_files)
local types = {
ConsoleApp = "Executable",
WindowedApp = "Executable",
StaticLib = "Static Library",
SharedLib = "Dynamic Library",
}
_p(' <Settings Type="%s">', types[prj.kind])
-- build a list of supported target platforms; I don't support cross-compiling yet
local platforms = premake.filterplatforms(prj.solution, premake[_OPTIONS.cc].platforms, "Native")
for i = #platforms, 1, -1 do
if premake.platforms[platforms[i]].iscrosscompiler then
table.remove(platforms, i)
end
end
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
local name = premake.esc(cfg.longname)
local compiler = iif(cfg.language == "C", "gcc", "g++")
_p(' <Configuration Name="%s" CompilerType="gnu %s" DebuggerType="GNU gdb debugger" Type="%s">', name, compiler, types[cfg.kind])
local fname = premake.esc(cfg.buildtarget.fullpath)
local objdir = premake.esc(cfg.objectsdir)
local runcmd = cfg.buildtarget.name
local rundir = cfg.buildtarget.directory
local pause = iif(cfg.kind == "WindowedApp", "no", "yes")
_p(' <General OutputFile="%s" IntermediateDirectory="%s" Command="./%s" CommandArguments="" WorkingDirectory="%s" PauseExecWhenProcTerminates="%s"/>', fname, objdir, runcmd, rundir, pause)
-- begin compiler block --
local flags = premake.esc(table.join(premake.gcc.getcflags(cfg), premake.gcc.getcxxflags(cfg), cfg.buildoptions))
_p(' <Compiler Required="yes" Options="%s">', table.concat(flags, ";"))
for _,v in ipairs(cfg.includedirs) do
_p(' <IncludePath Value="%s"/>', premake.esc(v))
end
for _,v in ipairs(cfg.defines) do
_p(' <Preprocessor Value="%s"/>', premake.esc(v))
end
_p(' </Compiler>')
-- end compiler block --
-- begin linker block --
flags = premake.esc(table.join(premake.gcc.getldflags(cfg), cfg.linkoptions))
_p(' <Linker Required="yes" Options="%s">', table.concat(flags, ";"))
for _,v in ipairs(premake.getlinks(cfg, "all", "directory")) do
_p(' <LibraryPath Value="%s" />', premake.esc(v))
end
for _,v in ipairs(premake.getlinks(cfg, "all", "basename")) do
_p(' <Library Value="%s" />', premake.esc(v))
end
_p(' </Linker>')
-- end linker block --
-- begin resource compiler block --
if premake.findfile(cfg, ".rc") then
local defines = table.implode(table.join(cfg.defines, cfg.resdefines), "-D", ";", "")
local options = table.concat(cfg.resoptions, ";")
_p(' <ResourceCompiler Required="yes" Options="%s%s">', defines, options)
for _,v in ipairs(table.join(cfg.includedirs, cfg.resincludedirs)) do
_p(' <IncludePath Value="%s"/>', premake.esc(v))
end
_p(' </ResourceCompiler>')
else
_p(' <ResourceCompiler Required="no" Options=""/>')
end
-- end resource compiler block --
-- begin build steps --
if #cfg.prebuildcommands > 0 then
_p(' <PreBuild>')
for _,v in ipairs(cfg.prebuildcommands) do
_p(' <Command Enabled="yes">%s</Command>', premake.esc(v))
end
_p(' </PreBuild>')
end
if #cfg.postbuildcommands > 0 then
_p(' <PostBuild>')
for _,v in ipairs(cfg.postbuildcommands) do
_p(' <Command Enabled="yes">%s</Command>', premake.esc(v))
end
_p(' </PostBuild>')
end
-- end build steps --
_p(' <CustomBuild Enabled="no">')
_p(' <CleanCommand></CleanCommand>')
_p(' <BuildCommand></BuildCommand>')
_p(' <SingleFileCommand></SingleFileCommand>')
_p(' <MakefileGenerationCommand></MakefileGenerationCommand>')
_p(' <ThirdPartyToolName>None</ThirdPartyToolName>')
_p(' <WorkingDirectory></WorkingDirectory>')
_p(' </CustomBuild>')
_p(' <AdditionalRules>')
_p(' <CustomPostBuild></CustomPostBuild>')
_p(' <CustomPreBuild></CustomPreBuild>')
_p(' </AdditionalRules>')
_p(' </Configuration>')
end
end
_p(' </Settings>')
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
_p(' <Dependencies name="%s">', cfg.longname)
for _,dep in ipairs(premake.getdependencies(prj)) do
_p(' <Project Name="%s"/>', dep.name)
end
_p(' </Dependencies>')
end
end
_p('</CodeLite_Project>')
end
--
-- Write out entries for the files element; called from premake.walksources().
--
function premake.codelite_files(prj, fname, state, nestlevel)
local indent = string.rep(" ", nestlevel + 1)
if (state == "GroupStart") then
io.write(indent .. '<VirtualDirectory Name="' .. path.getname(fname) .. '">\n')
elseif (state == "GroupEnd") then
io.write(indent .. '</VirtualDirectory>\n')
else
io.write(indent .. '<File Name="' .. fname .. '"/>\n')
end
end

View File

@ -0,0 +1,40 @@
--
-- codelite_workspace.lua
-- Generate a CodeLite workspace file.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.codelite_workspace(sln)
_p('<?xml version="1.0" encoding="utf-8"?>')
_p('<CodeLite_Workspace Name="%s" Database="./%s.tags">', premake.esc(sln.name), premake.esc(sln.name))
for i,prj in ipairs(sln.projects) do
local name = premake.esc(prj.name)
local fname = path.join(path.getrelative(sln.location, prj.location), prj.name)
local active = iif(i==1, "Yes", "No")
_p(' <Project Name="%s" Path="%s.project" Active="%s" />', name, fname, active)
end
-- build a list of supported target platforms; I don't support cross-compiling yet
local platforms = premake.filterplatforms(sln, premake[_OPTIONS.cc].platforms, "Native")
for i = #platforms, 1, -1 do
if premake.platforms[platforms[i]].iscrosscompiler then
table.remove(platforms, i)
end
end
_p(' <BuildMatrix>')
for _, platform in ipairs(platforms) do
for _, cfgname in ipairs(sln.configurations) do
local name = premake.getconfigname(cfgname, platform)
_p(' <WorkspaceConfiguration Name="%s" Selected="yes">', name)
for _,prj in ipairs(sln.projects) do
_p(' <Project Name="%s" ConfigName="%s"/>', prj.name, name)
end
_p(' </WorkspaceConfiguration>')
end
end
_p(' </BuildMatrix>')
_p('</CodeLite_Workspace>')
end

View File

@ -0,0 +1,99 @@
-- Define a namespace for my new action. The second line defines an alias that I
-- can use in this file, saving myself some typing. It will not be visible outside
-- of this file (though I can always define it again).
premake.example = { }
local example = premake.example
-- The description of the action. Note that only the first three fields are required;
-- you can remove any of the additional fields that are not required by your action.
newaction
{
-- The trigger is what needs to be typed on the command line to cause
-- this action this run (premake4 example)
trigger = "example",
-- The short name is used when this toolset name needs to be shown to
-- the user, such as in status or error messages
shortname = "Super Studio 3000",
-- The description is shown in the help text (premake4 /help)
description = "An example action that prints simple text files",
-- Some actions imply a particular operating system: Visual Studio only
-- runs on Windows, and Xcode only on Mac OS X. If this is the case,
-- uncomment this line and set it to one of "windows", "linux" or "macosx".
-- Otherwise, this action will target the current operating system.
-- os = "macosx",
-- Which kinds of targets this action supports; remove those you don't.
valid_kinds = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib" },
-- Which programming languages this actions supports; remove those you don't.
valid_languages = { "C", "C++", "C#" },
-- Which compiler sets this action supports; remove those you don't. The set
-- is specified with the /cc and /dotnet command-line options. You can find
-- the tool interfaces at src/tools.
valid_tools = {
cc = { "msc", "gcc", "ow" },
dotnet = { "mono", "msnet", "pnet" },
},
-- This function is called during state validation. If your action has some
-- special requirements you can check them here and error if necessary.
oncheckproject = function(prj)
-- if this_project_is_no_good(prj) then
-- error("Project " .. prj.name .. " is no good", 0)
-- end
end,
-- These functions will get called for each solution and project. The function
-- premake.generate() creates a file for you in the correct place, taking into
-- account any location information specified in the script. The sequence "%%"
-- will be replaced by the solution/project name. The last parameter is the
-- function that will actually do the work of generating the file contents.
onsolution = function(sln)
premake.generate(sln, "%%.sln.txt", premake.example.solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csprj.txt", premake.example.project)
else
premake.generate(prj, "%%.cprj.txt", premake.example.project)
end
end,
-- These functions are called for each solution, project, and target as part
-- of the "clean" action. They should remove any files generated by the tools.
-- premake.clean.file() and premake.clean.directory() are convenience functions
-- that use the same pattern matching as premake.generate() above.
oncleansolution = function(sln)
premake.clean.file(sln, "%%.sln.txt")
end,
oncleanproject = function(prj)
if premake.isdotnetproject(prj) then
premake.clean.file(prj, "%%.csprj.txt")
else
premake.clean.file(prj, "%%.cprj.txt")
end
end,
oncleantarget = function(trg)
-- 'trg' is the path and base name of the target being cleaned,
-- like 'bin/debug/MyApplication'. So you might do something like:
-- os.remove(trg .. ".exe")
end,
}

View File

@ -0,0 +1,91 @@
-- An example project generator; see _example.lua for action description
--
-- The project generation function, attached to the action in _example.lua.
-- By now, premake.generate() has created the project file using the name
-- provided in _example.lua, and redirected input to this new file.
--
function premake.example.project(prj)
-- If necessary, set an explicit line ending sequence
-- io.eol = '\r\n'
-- Let's start with a header
_p('-- Example project file version 1.0')
_p('Name: %s', prj.name)
_p('Kind: %s', prj.kind)
_p('Language: %s', prj.language)
_p('ID: {%s}', prj.uuid)
_p('')
-- List the build configurations, and the settings for each
for cfg in premake.eachconfig(prj) do
_p('Configuration %s:', cfg.name)
_p(1, 'Objects directory: %s', cfg.objectsdir)
_p(1, 'Build target:')
_p(2, 'Full path: %s', cfg.buildtarget.fullpath)
_p(2, 'Directory: %s', cfg.buildtarget.directory)
_p(2, 'Name: %s', cfg.buildtarget.name)
_p(2, 'Base name: %s', cfg.buildtarget.basename)
_p(2, 'Prefix: %s', cfg.buildtarget.prefix)
_p(2, 'Suffix: %s', cfg.buildtarget.suffix)
_p('')
_p(1, 'Compiling:')
_p(2, 'Defines: %s', table.concat(cfg.defines, ";"))
_p(2, 'Include paths: %s', table.concat(cfg.includedirs, ";"))
_p(2, 'Flags: %s', table.concat(cfg.flags, ", "))
if not cfg.flags.NoPCH and cfg.pchheader then
_p(2, 'Precompiled header: %s (%s)', cfg.pchheader, cfg.pchsource)
end
_p(2, 'Options: %s', table.concat(cfg.buildoptions, " "))
_p('')
_p(1, 'Linking:')
_p(2, 'Library paths: %s', table.concat(cfg.libdirs, ";"))
_p(2, 'Options: %s', table.concat(cfg.linkoptions, " "))
_p(2, 'Libraries: %s', table.concat(premake.getlinks(cfg, "all", "fullpath")))
_p('')
if #cfg.prebuildcommands > 0 then
_p(1, 'Prebuild commands:')
for _, cmd in ipairs(cfg.prebuildcommands) do
_p(2, cmd)
end
_p('')
end
if #cfg.prelinkcommands > 0 then
_p(1, 'Prelink commands:')
for _, cmd in ipairs(cfg.prelinkcommands) do
_p(2, cmd)
end
_p('')
end
if #cfg.postbuildcommands > 0 then
_p(1, 'Postbuild commands:')
for _, cmd in ipairs(cfg.postbuildcommands) do
_p(2, cmd)
end
_p('')
end
end
-- List out the folders and files that make up the build
local tr = premake.project.buildsourcetree(prj)
premake.tree.sort(tr)
premake.tree.traverse(tr, {
onbranch = function(node, depth)
_p(depth, path.getname(node.name) .. "/")
end,
onleaf = function(node, depth)
_p(depth, path.getname(node.name))
end
})
end

View File

@ -0,0 +1,46 @@
-- An example solution generator; see _example.lua for action description
--
-- The solution generation function, attached to the action in _example.lua.
-- By now, premake.generate() has created the solution file using the name
-- provided in _example.lua, and redirected input to this new file.
--
function premake.example.solution(sln)
-- If necessary, set an explicit line ending sequence
-- io.eol = '\r\n'
-- Let's start with a header
_p('-- Example solution file version 1.0')
_p('Name: %s', sln.name)
_p('')
-- List the build configurations
for _, cfgname in ipairs(sln.configurations) do
_p('Config: %s', cfgname)
end
_p('')
-- List the projects contained by the solution, with some info on each
for prj in premake.solution.eachproject(sln) do
_p('Project: %s', prj.name)
_p(1, 'Kind: %s', prj.kind)
_p(1, 'Language: %s', prj.language)
_p(1, 'ID: {%s}', prj.uuid)
_p(1, 'Relative path: %s', path.getrelative(sln.location, prj.location))
-- List dependencies, if there are any
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p(1, 'Dependencies:')
for _, depprj in ipairs(deps) do
_p(2, '%s {%s}', depprj.name, depprj.uuid)
end
end
_p('')
end
end

View File

@ -0,0 +1,141 @@
--
-- _make.lua
-- Define the makefile action(s).
-- Copyright (c) 2002-2010 Jason Perkins and the Premake project
--
_MAKE = { }
premake.make = { }
--
-- Escape a string so it can be written to a makefile.
--
function _MAKE.esc(value)
local result
if (type(value) == "table") then
result = { }
for _,v in ipairs(value) do
table.insert(result, _MAKE.esc(v))
end
return result
else
-- handle simple replacements
result = value:gsub("\\", "\\\\")
result = result:gsub(" ", "\\ ")
result = result:gsub("%(", "\\%(")
result = result:gsub("%)", "\\%)")
-- leave $(...) shell replacement sequences alone
result = result:gsub("$\\%((.-)\\%)", "$%(%1%)")
return result
end
end
--
-- Rules for file ops based on the shell type. Can't use defines and $@ because
-- it screws up the escaping of spaces and parethesis (anyone know a solution?)
--
function premake.make_copyrule(source, target)
_p('%s: %s', target, source)
_p('\t@echo Copying $(notdir %s)', target)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) cp -fR %s %s', source, target)
_p('else')
_p('\t$(SILENT) copy /Y $(subst /,\\\\,%s) $(subst /,\\\\,%s)', source, target)
_p('endif')
end
function premake.make_mkdirrule(var)
_p('\t@echo Creating %s', var)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) mkdir -p %s', var)
_p('else')
_p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', var)
_p('endif')
_p('')
end
--
-- Get the makefile file name for a solution or a project. If this object is the
-- only one writing to a location then I can use "Makefile". If more than one object
-- writes to the same location I use name + ".make" to keep it unique.
--
function _MAKE.getmakefilename(this, searchprjs)
-- how many projects/solutions use this location?
local count = 0
for sln in premake.solution.each() do
if (sln.location == this.location) then count = count + 1 end
if (searchprjs) then
for _,prj in ipairs(sln.projects) do
if (prj.location == this.location) then count = count + 1 end
end
end
end
if (count == 1) then
return "Makefile"
else
return this.name .. ".make"
end
end
--
-- Returns a list of object names, properly escaped to be included in the makefile.
--
function _MAKE.getnames(tbl)
local result = table.extract(tbl, "name")
for k,v in pairs(result) do
result[k] = _MAKE.esc(v)
end
return result
end
--
-- Register the "gmake" action
--
newaction {
trigger = "gmake",
shortname = "GNU Make",
description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "gcc" },
dotnet = { "mono", "msnet", "pnet" },
},
onsolution = function(sln)
premake.generate(sln, _MAKE.getmakefilename(sln, false), premake.make_solution)
end,
onproject = function(prj)
local makefile = _MAKE.getmakefilename(prj, true)
if premake.isdotnetproject(prj) then
premake.generate(prj, makefile, premake.make_csharp)
else
premake.generate(prj, makefile, premake.make_cpp)
end
end,
oncleansolution = function(sln)
premake.clean.file(sln, _MAKE.getmakefilename(sln, false))
end,
oncleanproject = function(prj)
premake.clean.file(prj, _MAKE.getmakefilename(prj, true))
end
}

View File

@ -0,0 +1,269 @@
--
-- make_cpp.lua
-- Generate a C/C++ project makefile.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.make.cpp = { }
local _ = premake.make.cpp
function premake.make_cpp(prj)
-- create a shortcut to the compiler interface
local cc = premake.gettool(prj)
-- build a list of supported target platforms that also includes a generic build
local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native")
premake.gmake_cpp_header(prj, cc, platforms)
for _, platform in ipairs(platforms) do
for cfg in premake.eachconfig(prj, platform) do
premake.gmake_cpp_config(cfg, cc)
end
end
-- list intermediate files
_p('OBJECTS := \\')
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('\t$(OBJDIR)/%s.o \\', _MAKE.esc(path.getbasename(file)))
end
end
_p('')
_p('RESOURCES := \\')
for _, file in ipairs(prj.files) do
if path.isresourcefile(file) then
_p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file)))
end
end
_p('')
-- identify the shell type
_p('SHELLTYPE := msdos')
_p('ifeq (,$(ComSpec)$(COMSPEC))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('')
-- main build rule(s)
_p('.PHONY: clean prebuild prelink')
_p('')
if os.is("MacOSX") and prj.kind == "WindowedApp" then
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist')
else
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)')
end
_p('\t@:')
_p('')
-- target build rule
_p('$(TARGET): $(GCH) $(OBJECTS) $(LDDEPS) $(RESOURCES)')
_p('\t@echo Linking %s', prj.name)
_p('\t$(SILENT) $(LINKCMD)')
_p('\t$(POSTBUILDCMDS)')
_p('')
-- Create destination directories. Can't use $@ for this because it loses the
-- escaping, causing issues with spaces and parenthesis
_p('$(TARGETDIR):')
premake.make_mkdirrule("$(TARGETDIR)")
_p('$(OBJDIR):')
premake.make_mkdirrule("$(OBJDIR)")
-- Mac OS X specific targets
if os.is("MacOSX") and prj.kind == "WindowedApp" then
_p('$(dir $(TARGETDIR))PkgInfo:')
_p('$(dir $(TARGETDIR))Info.plist:')
_p('')
end
-- clean target
_p('clean:')
_p('\t@echo Cleaning %s', prj.name)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) rm -f $(TARGET)')
_p('\t$(SILENT) rm -rf $(OBJDIR)')
_p('else')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
_p('endif')
_p('')
-- custom build step targets
_p('prebuild:')
_p('\t$(PREBUILDCMDS)')
_p('')
_p('prelink:')
_p('\t$(PRELINKCMDS)')
_p('')
-- precompiler header rule
_.pchrules(prj)
-- per-file rules
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
if (path.iscfile(file)) then
_p('\t$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"')
else
_p('\t$(SILENT) $(CXX) $(CXXFLAGS) -o "$@" -c "$<"')
end
elseif (path.getextension(file) == ".rc") then
_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) windres $< -O coff -o "$@" $(RESFLAGS)')
end
end
_p('')
-- include the dependencies, built by GCC (with the -MMD flag)
_p('-include $(OBJECTS:%%.o=%%.d)')
end
--
-- Write the makefile header
--
function premake.gmake_cpp_header(prj, cc, platforms)
_p('# %s project makefile autogenerated by Premake', premake.action.current().shortname)
-- set up the environment
_p('ifndef config')
_p(' config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true)))
_p('endif')
_p('')
_p('ifndef verbose')
_p(' SILENT = @')
_p('endif')
_p('')
_p('ifndef CC')
_p(' CC = %s', cc.cc)
_p('endif')
_p('')
_p('ifndef CXX')
_p(' CXX = %s', cc.cxx)
_p('endif')
_p('')
_p('ifndef AR')
_p(' AR = %s', cc.ar)
_p('endif')
_p('')
end
--
-- Write a block of configuration settings.
--
function premake.gmake_cpp_config(cfg, cc)
_p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname))
-- if this platform requires a special compiler or linker, list it now
local platform = cc.platforms[cfg.platform]
if platform.cc then
_p(' CC = %s', platform.cc)
end
if platform.cxx then
_p(' CXX = %s', platform.cxx)
end
if platform.ar then
_p(' AR = %s', platform.ar)
end
_p(' OBJDIR = %s', _MAKE.esc(cfg.objectsdir))
_p(' TARGETDIR = %s', _MAKE.esc(cfg.buildtarget.directory))
_p(' TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name))
_p(' DEFINES += %s', table.concat(cc.getdefines(cfg.defines), " "))
_p(' INCLUDES += %s', table.concat(cc.getincludedirs(cfg.includedirs), " "))
_p(' CPPFLAGS += %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), " "))
-- set up precompiled headers
_.pchconfig(cfg)
_p(' CFLAGS += $(CPPFLAGS) $(ARCH) %s', table.concat(table.join(cc.getcflags(cfg), cfg.buildoptions), " "))
_p(' CXXFLAGS += $(CFLAGS) %s', table.concat(cc.getcxxflags(cfg), " "))
_p(' LDFLAGS += %s', table.concat(table.join(cc.getldflags(cfg), cfg.linkoptions, cc.getlibdirflags(cfg)), " "))
_p(' LIBS += %s', table.concat(cc.getlinkflags(cfg), " "))
_p(' RESFLAGS += $(DEFINES) $(INCLUDES) %s', table.concat(table.join(cc.getdefines(cfg.resdefines), cc.getincludedirs(cfg.resincludedirs), cfg.resoptions), " "))
_p(' LDDEPS += %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "siblings", "fullpath")), " "))
if cfg.kind == "StaticLib" then
if cfg.platform:startswith("Universal") then
_p(' LINKCMD = libtool -o $(TARGET) $(OBJECTS)')
else
_p(' LINKCMD = $(AR) -rcs $(TARGET) $(OBJECTS)')
end
else
-- this was $(TARGET) $(LDFLAGS) $(OBJECTS) ... but was having trouble linking to certain
-- static libraries so $(OBJECTS) was moved up
_p(' LINKCMD = $(%s) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(ARCH) $(LIBS)', iif(cfg.language == "C", "CC", "CXX"))
end
_p(' define PREBUILDCMDS')
if #cfg.prebuildcommands > 0 then
_p('\t@echo Running pre-build commands')
_p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t"))
end
_p(' endef')
_p(' define PRELINKCMDS')
if #cfg.prelinkcommands > 0 then
_p('\t@echo Running pre-link commands')
_p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t"))
end
_p(' endef')
_p(' define POSTBUILDCMDS')
if #cfg.postbuildcommands > 0 then
_p('\t@echo Running post-build commands')
_p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t"))
end
_p(' endef')
_p('endif')
_p('')
end
--
-- Precompiled header support
--
function _.pchconfig(cfg)
if not cfg.flags.NoPCH and cfg.pchheader then
_p(' PCH = %s', _MAKE.esc(path.getrelative(cfg.location, cfg.pchheader)))
_p(' GCH = $(OBJDIR)/%s.gch', _MAKE.esc(path.getname(cfg.pchheader)))
_p(' CPPFLAGS += -I$(OBJDIR) -include $(OBJDIR)/%s', _MAKE.esc(path.getname(cfg.pchheader)))
end
end
function _.pchrules(prj)
_p('ifneq (,$(PCH))')
_p('$(GCH): $(PCH)')
_p('\t@echo $(notdir $<)')
_p('\t-$(SILENT) cp $< $(OBJDIR)')
if prj.language == "C" then
_p('\t$(SILENT) $(CC) $(CFLAGS) -o "$@" -c "$<"')
else
_p('\t$(SILENT) $(CXX) $(CXXFLAGS) -o "$@" -c "$<"')
end
_p('endif')
_p('')
end

View File

@ -0,0 +1,271 @@
--
-- make_csharp.lua
-- Generate a C# project makefile.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
--
-- Given a .resx resource file, builds the path to corresponding .resource
-- file, matching the behavior and naming of Visual Studio.
--
local function getresourcefilename(cfg, fname)
if path.getextension(fname) == ".resx" then
local name = cfg.buildtarget.basename .. "."
local dir = path.getdirectory(fname)
if dir ~= "." then
name = name .. path.translate(dir, ".") .. "."
end
return "$(OBJDIR)/" .. _MAKE.esc(name .. path.getbasename(fname)) .. ".resources"
else
return fname
end
end
--
-- Main function
--
function premake.make_csharp(prj)
local csc = premake.dotnet
-- Do some processing up front: build a list of configuration-dependent libraries.
-- Libraries that are built to a location other than $(TARGETDIR) will need to
-- be copied so they can be found at runtime.
local cfglibs = { }
local cfgpairs = { }
local anycfg
for cfg in premake.eachconfig(prj) do
anycfg = cfg
cfglibs[cfg] = premake.getlinks(cfg, "siblings", "fullpath")
cfgpairs[cfg] = { }
for _, fname in ipairs(cfglibs[cfg]) do
if path.getdirectory(fname) ~= cfg.buildtarget.directory then
cfgpairs[cfg]["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fname))] = _MAKE.esc(fname)
end
end
end
-- sort the files into categories, based on their build action
local sources = {}
local embedded = { }
local copypairs = { }
for fcfg in premake.eachfile(prj) do
local action = csc.getbuildaction(fcfg)
if action == "Compile" then
table.insert(sources, fcfg.name)
elseif action == "EmbeddedResource" then
table.insert(embedded, fcfg.name)
elseif action == "Content" then
copypairs["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fcfg.name))] = _MAKE.esc(fcfg.name)
elseif path.getname(fcfg.name):lower() == "app.config" then
copypairs["$(TARGET).config"] = _MAKE.esc(fcfg.name)
end
end
-- Any assemblies that are on the library search paths should be copied
-- to $(TARGETDIR) so they can be found at runtime
local paths = table.translate(prj.libdirs, function(v) return path.join(prj.basedir, v) end)
paths = table.join({prj.basedir}, paths)
for _, libname in ipairs(premake.getlinks(prj, "system", "fullpath")) do
local libdir = os.pathsearch(libname..".dll", unpack(paths))
if (libdir) then
local target = "$(TARGETDIR)/" .. _MAKE.esc(path.getname(libname))
local source = path.getrelative(prj.basedir, path.join(libdir, libname))..".dll"
copypairs[target] = _MAKE.esc(source)
end
end
-- end of preprocessing --
-- set up the environment
_p('# %s project makefile autogenerated by Premake', premake.action.current().shortname)
_p('')
_p('ifndef config')
_p(' config=%s', _MAKE.esc(prj.configurations[1]:lower()))
_p('endif')
_p('')
_p('ifndef verbose')
_p(' SILENT = @')
_p('endif')
_p('')
_p('ifndef CSC')
_p(' CSC=%s', csc.getcompilervar(prj))
_p('endif')
_p('')
_p('ifndef RESGEN')
_p(' RESGEN=resgen')
_p('endif')
_p('')
-- Platforms aren't support for .NET projects, but I need the ability to match
-- the buildcfg:platform identifiers with a block of settings. So enumerate the
-- pairs the same way I do for C/C++ projects, but always use the generic settings
local platforms = premake.filterplatforms(prj.solution, premake[_OPTIONS.cc].platforms)
table.insert(platforms, 1, "")
-- write the configuration blocks
for cfg in premake.eachconfig(prj) do
premake.gmake_cs_config(cfg, csc, cfglibs)
end
-- set project level values
_p('# To maintain compatibility with VS.NET, these values must be set at the project level')
_p('TARGET := $(TARGETDIR)/%s', _MAKE.esc(prj.buildtarget.name))
_p('FLAGS += /t:%s %s', csc.getkind(prj):lower(), table.implode(_MAKE.esc(prj.libdirs), "/lib:", "", " "))
_p('REFERENCES += %s', table.implode(_MAKE.esc(premake.getlinks(prj, "system", "basename")), "/r:", ".dll", " "))
_p('')
-- list source files
_p('SOURCES := \\')
for _, fname in ipairs(sources) do
_p('\t%s \\', _MAKE.esc(path.translate(fname)))
end
_p('')
_p('EMBEDFILES := \\')
for _, fname in ipairs(embedded) do
_p('\t%s \\', getresourcefilename(prj, fname))
end
_p('')
_p('COPYFILES += \\')
for target, source in pairs(cfgpairs[anycfg]) do
_p('\t%s \\', target)
end
for target, source in pairs(copypairs) do
_p('\t%s \\', target)
end
_p('')
-- identify the shell type
_p('SHELLTYPE := msdos')
_p('ifeq (,$(ComSpec)$(COMSPEC))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
_p(' SHELLTYPE := posix')
_p('endif')
_p('')
-- main build rule(s)
_p('.PHONY: clean prebuild prelink')
_p('')
_p('all: $(TARGETDIR) $(OBJDIR) prebuild $(EMBEDFILES) $(COPYFILES) prelink $(TARGET)')
_p('')
_p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS)')
_p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) $(SOURCES) $(patsubst %%,/resource:%%,$(EMBEDFILES))')
_p('\t$(POSTBUILDCMDS)')
_p('')
-- Create destination directories. Can't use $@ for this because it loses the
-- escaping, causing issues with spaces and parenthesis
_p('$(TARGETDIR):')
premake.make_mkdirrule("$(TARGETDIR)")
_p('$(OBJDIR):')
premake.make_mkdirrule("$(OBJDIR)")
-- clean target
_p('clean:')
_p('\t@echo Cleaning %s', prj.name)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) rm -f $(TARGETDIR)/%s.* $(COPYFILES)', prj.buildtarget.basename)
_p('\t$(SILENT) rm -rf $(OBJDIR)')
_p('else')
_p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGETDIR)/%s.*) del $(subst /,\\\\,$(TARGETDIR)/%s.*)', prj.buildtarget.basename, prj.buildtarget.basename)
for target, source in pairs(cfgpairs[anycfg]) do
_p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
end
for target, source in pairs(copypairs) do
_p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
end
_p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
_p('endif')
_p('')
-- custom build step targets
_p('prebuild:')
_p('\t$(PREBUILDCMDS)')
_p('')
_p('prelink:')
_p('\t$(PRELINKCMDS)')
_p('')
-- per-file rules
_p('# Per-configuration copied file rules')
for cfg in premake.eachconfig(prj) do
_p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower()))
for target, source in pairs(cfgpairs[cfg]) do
premake.make_copyrule(source, target)
end
_p('endif')
_p('')
end
_p('# Copied file rules')
for target, source in pairs(copypairs) do
premake.make_copyrule(source, target)
end
_p('# Embedded file rules')
for _, fname in ipairs(embedded) do
if path.getextension(fname) == ".resx" then
_p('%s: %s', getresourcefilename(prj, fname), _MAKE.esc(fname))
_p('\t$(SILENT) $(RESGEN) $^ $@')
end
_p('')
end
end
--
-- Write a block of configuration settings.
--
function premake.gmake_cs_config(cfg, csc, cfglibs)
_p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower()))
_p(' TARGETDIR := %s', _MAKE.esc(cfg.buildtarget.directory))
_p(' OBJDIR := %s', _MAKE.esc(cfg.objectsdir))
_p(' DEPENDS := %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "dependencies", "fullpath")), " "))
_p(' REFERENCES := %s', table.implode(_MAKE.esc(cfglibs[cfg]), "/r:", "", " "))
_p(' FLAGS += %s %s', table.implode(cfg.defines, "/d:", "", " "), table.concat(table.join(csc.getflags(cfg), cfg.buildoptions), " "))
_p(' define PREBUILDCMDS')
if #cfg.prebuildcommands > 0 then
_p('\t@echo Running pre-build commands')
_p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t"))
end
_p(' endef')
_p(' define PRELINKCMDS')
if #cfg.prelinkcommands > 0 then
_p('\t@echo Running pre-link commands')
_p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t"))
end
_p(' endef')
_p(' define POSTBUILDCMDS')
if #cfg.postbuildcommands > 0 then
_p('\t@echo Running post-build commands')
_p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t"))
end
_p(' endef')
_p('endif')
_p('')
end

View File

@ -0,0 +1,74 @@
--
-- make_solution.lua
-- Generate a solution-level makefile.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
function premake.make_solution(sln)
-- create a shortcut to the compiler interface
local cc = premake[_OPTIONS.cc]
-- build a list of supported target platforms that also includes a generic build
local platforms = premake.filterplatforms(sln, cc.platforms, "Native")
-- write a header showing the build options
_p('# %s solution makefile autogenerated by Premake', premake.action.current().shortname)
_p('# Type "make help" for usage help')
_p('')
-- set a default configuration
_p('ifndef config')
_p(' config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true)))
_p('endif')
_p('export config')
_p('')
-- list the projects included in the solution
_p('PROJECTS := %s', table.concat(_MAKE.esc(table.extract(sln.projects, "name")), " "))
_p('')
_p('.PHONY: all clean help $(PROJECTS)')
_p('')
_p('all: $(PROJECTS)')
_p('')
-- write the project build rules
for _, prj in ipairs(sln.projects) do
_p('%s: %s', _MAKE.esc(prj.name), table.concat(_MAKE.esc(table.extract(premake.getdependencies(prj), "name")), " "))
_p('\t@echo "==== Building %s ($(config)) ===="', prj.name)
_p('\t@${MAKE} --no-print-directory -C %s -f %s', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true)))
_p('')
end
-- clean rules
_p('clean:')
for _ ,prj in ipairs(sln.projects) do
_p('\t@${MAKE} --no-print-directory -C %s -f %s clean', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true)))
end
_p('')
-- help rule
_p('help:')
_p(1,'@echo "Usage: make [config=name] [target]"')
_p(1,'@echo ""')
_p(1,'@echo "CONFIGURATIONS:"')
local cfgpairs = { }
for _, platform in ipairs(platforms) do
for _, cfgname in ipairs(sln.configurations) do
_p(1,'@echo " %s"', premake.getconfigname(cfgname, platform, true))
end
end
_p(1,'@echo ""')
_p(1,'@echo "TARGETS:"')
_p(1,'@echo " all (default)"')
_p(1,'@echo " clean"')
for _, prj in ipairs(sln.projects) do
_p(1,'@echo " %s"', prj.name)
end
_p(1,'@echo ""')
_p(1,'@echo "For more information, see http://industriousone.com/premake/quick-start"')
end

View File

@ -0,0 +1,458 @@
--
-- _vstudio.lua
-- Define the Visual Studio 200x actions.
-- Copyright (c) 2008-2010 Jason Perkins and the Premake project
--
_VS = { } -- deprecated, will remove eventually
premake.vstudio = { }
local vstudio = premake.vstudio
--
-- Map Premake platform identifiers to the Visual Studio versions. Adds the Visual
-- Studio specific "any" and "mixed" to make solution generation easier.
--
premake.vstudio_platforms = {
any = "Any CPU",
mixed = "Mixed Platforms",
Native = "Win32",
x32 = "Win32",
x64 = "x64",
PS3 = "PS3",
Xbox360 = "Xbox 360",
}
--
-- Returns the architecture identifier for a project.
--
function _VS.arch(prj)
if (prj.language == "C#") then
if (_ACTION < "vs2005") then
return ".NET"
else
return "Any CPU"
end
else
return "Win32"
end
end
--
-- Return the version-specific text for a boolean value.
-- (this should probably go in vs200x_vcproj.lua)
--
function _VS.bool(value)
if (_ACTION < "vs2005") then
return iif(value, "TRUE", "FALSE")
else
return iif(value, "true", "false")
end
end
--
-- Process the solution's list of configurations and platforms, creates a list
-- of build configuration/platform pairs in a Visual Studio compatible format.
--
-- @param sln
-- The solution containing the configuration and platform lists.
-- @param with_pseudo
-- If true, Visual Studio's "Any CPU" and "Mixed Platforms" platforms will
-- be added for .NET and mixed mode solutions.
--
--
-- Process the solution's list of configurations and platforms, creates a list
-- of build configuration/platform pairs in a Visual Studio compatible format.
--
-- @param sln
-- The solution containing the configuration and platform lists.
--
function premake.vstudio_buildconfigs(sln)
local cfgs = { }
local platforms = premake.filterplatforms(sln, premake.vstudio_platforms, "Native")
-- .NET projects add "Any CPU", mixed mode solutions add "Mixed Platforms"
local hascpp = premake.hascppproject(sln)
local hasdotnet = premake.hasdotnetproject(sln)
if hasdotnet then
table.insert(platforms, 1, "any")
end
if hasdotnet and hascpp then
table.insert(platforms, 2, "mixed")
end
for _, buildcfg in ipairs(sln.configurations) do
for _, platform in ipairs(platforms) do
local entry = { }
entry.src_buildcfg = buildcfg
entry.src_platform = platform
-- PS3 is funky and needs special handling; it's more of a build
-- configuration than a platform from Visual Studio's point of view
if platform ~= "PS3" then
entry.buildcfg = buildcfg
entry.platform = premake.vstudio_platforms[platform]
else
entry.buildcfg = platform .. " " .. buildcfg
entry.platform = "Win32"
end
-- create a name the way VS likes it
entry.name = entry.buildcfg .. "|" .. entry.platform
-- flag the "fake" platforms added for .NET
entry.isreal = (platform ~= "any" and platform ~= "mixed")
table.insert(cfgs, entry)
end
end
return cfgs
end
--
-- Return a configuration type index.
-- (this should probably go in vs200x_vcproj.lua)
--
function _VS.cfgtype(cfg)
if (cfg.kind == "SharedLib") then
return 2
elseif (cfg.kind == "StaticLib") then
return 4
else
return 1
end
end
--
-- Clean Visual Studio files
--
function premake.vstudio.cleansolution(sln)
premake.clean.file(sln, "%%.sln")
premake.clean.file(sln, "%%.suo")
premake.clean.file(sln, "%%.ncb")
-- MonoDevelop files
premake.clean.file(sln, "%%.userprefs")
premake.clean.file(sln, "%%.usertasks")
end
function premake.vstudio.cleanproject(prj)
local fname = premake.project.getfilename(prj, "%%")
os.remove(fname .. ".vcproj")
os.remove(fname .. ".vcproj.user")
os.remove(fname .. ".vcxproj")
os.remove(fname .. ".vcxproj.user")
os.remove(fname .. ".vcxproj.filters")
os.remove(fname .. ".csproj")
os.remove(fname .. ".csproj.user")
os.remove(fname .. ".pidb")
os.remove(fname .. ".sdf")
end
function premake.vstudio.cleantarget(name)
os.remove(name .. ".pdb")
os.remove(name .. ".idb")
os.remove(name .. ".ilk")
os.remove(name .. ".vshost.exe")
os.remove(name .. ".exe.manifest")
end
--
-- Write out entries for the files element; called from premake.walksources().
-- (this should probably go in vs200x_vcproj.lua)
--
local function output(indent, value)
-- io.write(indent .. value .. "\r\n")
_p(indent .. value)
end
local function attrib(indent, name, value)
-- io.write(indent .. "\t" .. name .. '="' .. value .. '"\r\n')
_p(indent .. "\t" .. name .. '="' .. value .. '"')
end
function _VS.files(prj, fname, state, nestlevel)
local indent = string.rep("\t", nestlevel + 2)
if (state == "GroupStart") then
output(indent, "<Filter")
attrib(indent, "Name", path.getname(fname))
attrib(indent, "Filter", "")
output(indent, "\t>")
elseif (state == "GroupEnd") then
output(indent, "</Filter>")
else
output(indent, "<File")
attrib(indent, "RelativePath", path.translate(fname, "\\"))
output(indent, "\t>")
if (not prj.flags.NoPCH and prj.pchsource == fname) then
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
output(indent, "\t<FileConfiguration")
attrib(indent, "\tName", cfginfo.name)
output(indent, "\t\t>")
output(indent, "\t\t<Tool")
attrib(indent, "\t\tName", iif(cfg.system == "Xbox360", "VCCLX360CompilerTool", "VCCLCompilerTool"))
attrib(indent, "\t\tUsePrecompiledHeader", "1")
output(indent, "\t\t/>")
output(indent, "\t</FileConfiguration>")
end
end
end
output(indent, "</File>")
end
end
--
-- Return the optimization code.
-- (this should probably go in vs200x_vcproj.lua)
--
function _VS.optimization(cfg)
local result = 0
for _, value in ipairs(cfg.flags) do
if (value == "Optimize") then
result = 3
elseif (value == "OptimizeSize") then
result = 1
elseif (value == "OptimizeSpeed") then
result = 2
end
end
return result
end
--
-- Assemble the project file name.
--
function _VS.projectfile(prj)
local extension
if (prj.language == "C#") then
extension = ".csproj"
elseif (_ACTION == "vs2010" and prj.language == "C++" )then
extension = ".vcxproj"
elseif (_ACTION == "vs2010" and prj.language == "C" )then
extension = ".vcxproj"
else
extension = ".vcproj"
end
local fname = path.join(prj.location, prj.name)
return fname..extension
end
--
-- Returns the Visual Studio tool ID for a given project type.
--
function _VS.tool(prj)
if (prj.language == "C#") then
return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"
else
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
end
end
--
-- Register the Visual Studio command line actions
--
newaction {
trigger = "vs2002",
shortname = "Visual Studio 2002",
description = "Generate Microsoft Visual Studio 2002 project files",
os = "windows",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "msc" },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2002_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2002_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2002_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject = premake.vstudio.cleanproject,
oncleantarget = premake.vstudio.cleantarget
}
newaction {
trigger = "vs2003",
shortname = "Visual Studio 2003",
description = "Generate Microsoft Visual Studio 2003 project files",
os = "windows",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "msc" },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2003_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2002_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2002_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject = premake.vstudio.cleanproject,
oncleantarget = premake.vstudio.cleantarget
}
newaction {
trigger = "vs2005",
shortname = "Visual Studio 2005",
description = "Generate Microsoft Visual Studio 2005 project files",
os = "windows",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "msc" },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2005_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2005_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2005_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject = premake.vstudio.cleanproject,
oncleantarget = premake.vstudio.cleantarget
}
newaction {
trigger = "vs2008",
shortname = "Visual Studio 2008",
description = "Generate Microsoft Visual Studio 2008 project files",
os = "windows",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "msc" },
dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs2005_solution)
end,
onproject = function(prj)
if premake.isdotnetproject(prj) then
premake.generate(prj, "%%.csproj", premake.vs2005_csproj)
premake.generate(prj, "%%.csproj.user", premake.vs2005_csproj_user)
else
premake.generate(prj, "%%.vcproj", premake.vs200x_vcproj)
end
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject = premake.vstudio.cleanproject,
oncleantarget = premake.vstudio.cleantarget
}
newaction
{
trigger = "vs2010",
shortname = "Visual Studio 2010",
description = "Generate Visual Studio 2010 project files (experimental)",
os = "windows",
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" },
valid_languages = { "C++","C"},
valid_tools = {
cc = { "msc" },
--dotnet = { "msnet" },
},
onsolution = function(sln)
premake.generate(sln, "%%.sln", premake.vs_generic_solution)
end,
onproject = function(prj)
premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj)
premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user)
premake.generate(prj, "%%.vcxproj.filters", premake.vs2010_vcxproj_filters)
end,
oncleansolution = premake.vstudio.cleansolution,
oncleanproject = premake.vstudio.cleanproject,
oncleantarget = premake.vstudio.cleantarget
}

View File

@ -0,0 +1,143 @@
--
-- vs2002_csproj.lua
-- Generate a Visual Studio 2002/2003 C# project.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
--
-- Figure out what elements a particular file need in its item block,
-- based on its build action and any related files in the project.
--
local function getelements(prj, action, fname)
if action == "Compile" and fname:endswith(".cs") then
return "SubTypeCode"
end
if action == "EmbeddedResource" and fname:endswith(".resx") then
-- is there a matching *.cs file?
local basename = fname:sub(1, -6)
local testname = path.getname(basename .. ".cs")
if premake.findfile(prj, testname) then
return "Dependency", testname
end
end
return "None"
end
function premake.vs2002_csproj(prj)
io.eol = "\r\n"
_p('<VisualStudioProject>')
_p(1,'<CSHARP')
_p(2,'ProjectType = "Local"')
_p(2,'ProductVersion = "%s"', iif(_ACTION == "vs2002", "7.0.9254", "7.10.3077"))
_p(2,'SchemaVersion = "%s"', iif(_ACTION == "vs2002", "1.0", "2.0"))
_p(2,'ProjectGuid = "{%s}"', prj.uuid)
_p(1,'>')
_p(2,'<Build>')
-- Write out project-wide settings
_p(3,'<Settings')
_p(4,'ApplicationIcon = ""')
_p(4,'AssemblyKeyContainerName = ""')
_p(4,'AssemblyName = "%s"', prj.buildtarget.basename)
_p(4,'AssemblyOriginatorKeyFile = ""')
_p(4,'DefaultClientScript = "JScript"')
_p(4,'DefaultHTMLPageLayout = "Grid"')
_p(4,'DefaultTargetSchema = "IE50"')
_p(4,'DelaySign = "false"')
if _ACTION == "vs2002" then
_p(4,'NoStandardLibraries = "false"')
end
_p(4,'OutputType = "%s"', premake.dotnet.getkind(prj))
if _ACTION == "vs2003" then
_p(4,'PreBuildEvent = ""')
_p(4,'PostBuildEvent = ""')
end
_p(4,'RootNamespace = "%s"', prj.buildtarget.basename)
if _ACTION == "vs2003" then
_p(4,'RunPostBuildEvent = "OnBuildSuccess"')
end
_p(4,'StartupObject = ""')
_p(3,'>')
-- Write out configuration blocks
for cfg in premake.eachconfig(prj) do
_p(4,'<Config')
_p(5,'Name = "%s"', premake.esc(cfg.name))
_p(5,'AllowUnsafeBlocks = "%s"', iif(cfg.flags.Unsafe, "true", "false"))
_p(5,'BaseAddress = "285212672"')
_p(5,'CheckForOverflowUnderflow = "false"')
_p(5,'ConfigurationOverrideFile = ""')
_p(5,'DefineConstants = "%s"', premake.esc(table.concat(cfg.defines, ";")))
_p(5,'DocumentationFile = ""')
_p(5,'DebugSymbols = "%s"', iif(cfg.flags.Symbols, "true", "false"))
_p(5,'FileAlignment = "4096"')
_p(5,'IncrementalBuild = "false"')
if _ACTION == "vs2003" then
_p(5,'NoStdLib = "false"')
_p(5,'NoWarn = ""')
end
_p(5,'Optimize = "%s"', iif(cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed, "true", "false"))
_p(5,'OutputPath = "%s"', premake.esc(cfg.buildtarget.directory))
_p(5,'RegisterForComInterop = "false"')
_p(5,'RemoveIntegerChecks = "false"')
_p(5,'TreatWarningsAsErrors = "%s"', iif(cfg.flags.FatalWarnings, "true", "false"))
_p(5,'WarningLevel = "4"')
_p(4,'/>')
end
_p(3,'</Settings>')
-- List assembly references
_p(3,'<References>')
for _, ref in ipairs(premake.getlinks(prj, "siblings", "object")) do
_p(4,'<Reference')
_p(5,'Name = "%s"', ref.buildtarget.basename)
_p(5,'Project = "{%s}"', ref.uuid)
_p(5,'Package = "{%s}"', _VS.tool(ref))
_p(4,'/>')
end
for _, linkname in ipairs(premake.getlinks(prj, "system", "fullpath")) do
_p(4,'<Reference')
_p(5,'Name = "%s"', path.getbasename(linkname))
_p(5,'AssemblyName = "%s"', path.getname(linkname))
if path.getdirectory(linkname) ~= "." then
_p(5,'HintPath = "%s"', path.translate(linkname, "\\"))
end
_p(4,'/>')
end
_p(3,'</References>')
_p(2,'</Build>')
-- List source files
_p(2,'<Files>')
_p(3,'<Include>')
for fcfg in premake.eachfile(prj) do
local action = premake.dotnet.getbuildaction(fcfg)
local fname = path.translate(premake.esc(fcfg.name), "\\")
local elements, dependency = getelements(prj, action, fcfg.name)
_p(4,'<File')
_p(5,'RelPath = "%s"', premake.esc(fname))
_p(5,'BuildAction = "%s"', action)
if dependency then
_p(5,'DependentUpon = "%s"', premake.esc(path.translate(dependency, "\\")))
end
if elements == "SubTypeCode" then
_p(5,'SubType = "Code"')
end
_p(4,'/>')
end
_p(3,'</Include>')
_p(2,'</Files>')
_p(1,'</CSHARP>')
_p('</VisualStudioProject>')
end

View File

@ -0,0 +1,50 @@
--
-- vs2002_csproj_user.lua
-- Generate a Visual Studio 2002/2003 C# .user file.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.vs2002_csproj_user(prj)
io.eol = "\r\n"
_p('<VisualStudioProject>')
_p(1,'<CSHARP>')
_p(2,'<Build>')
-- Visual Studio wants absolute paths
local refpaths = table.translate(prj.libdirs, function(v) return path.getabsolute(prj.location .. "/" .. v) end)
_p(3,'<Settings ReferencePath = "%s">', path.translate(table.concat(refpaths, ";"), "\\"))
for cfg in premake.eachconfig(prj) do
_p(4,'<Config')
_p(5,'Name = "%s"', premake.esc(cfg.name))
_p(5,'EnableASPDebugging = "false"')
_p(5,'EnableASPXDebugging = "false"')
_p(5,'EnableUnmanagedDebugging = "false"')
_p(5,'EnableSQLServerDebugging = "false"')
_p(5,'RemoteDebugEnabled = "false"')
_p(5,'RemoteDebugMachine = ""')
_p(5,'StartAction = "Project"')
_p(5,'StartArguments = ""')
_p(5,'StartPage = ""')
_p(5,'StartProgram = ""')
_p(5,'StartURL = ""')
_p(5,'StartWorkingDirectory = ""')
_p(5,'StartWithIE = "false"')
_p(4,'/>')
end
_p(3,'</Settings>')
_p(2,'</Build>')
_p(2,'<OtherProjectSettings')
_p(3,'CopyProjectDestinationFolder = ""')
_p(3,'CopyProjectUncPath = ""')
_p(3,'CopyProjectOption = "0"')
_p(3,'ProjectView = "ProjectFiles"')
_p(3,'ProjectTrust = "0"')
_p(2,'/>')
_p(1,'</CSHARP>')
_p('</VisualStudioProject>')
end

View File

@ -0,0 +1,47 @@
--
-- vs2002_solution.lua
-- Generate a Visual Studio 2002 solution.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.vs2002_solution(sln)
io.eol = '\r\n'
-- Precompute Visual Studio configurations
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('Microsoft Visual Studio Solution File, Format Version 7.00')
-- Write out the list of project entries
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)))
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
_p('EndProject')
end
_p('Global')
_p(1,'GlobalSection(SolutionConfiguration) = preSolution')
for i, cfgname in ipairs(sln.configurations) do
_p(2,'ConfigName.%d = %s', i - 1, cfgname)
end
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ProjectDependencies) = postSolution')
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ProjectConfiguration) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfgname in ipairs(sln.configurations) do
_p(2,'{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
_p(2,'{%s}.%s.Build.0 = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
end
end
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ExtensibilityGlobals) = postSolution')
_p(1,'EndGlobalSection')
_p(1,'GlobalSection(ExtensibilityAddIns) = postSolution')
_p(1,'EndGlobalSection')
_p('EndGlobal')
end

View File

@ -0,0 +1,57 @@
--
-- vs2003_solution.lua
-- Generate a Visual Studio 2003 solution.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.vs2003_solution(sln)
io.eol = '\r\n'
-- Precompute Visual Studio configurations
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
_p('Microsoft Visual Studio Solution File, Format Version 8.00')
-- Write out the list of project entries
for prj in premake.solution.eachproject(sln) do
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)))
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
_p('Global')
_p('\tGlobalSection(SolutionConfiguration) = preSolution')
for _, cfgname in ipairs(sln.configurations) do
_p('\t\t%s = %s', cfgname, cfgname)
end
_p('\tEndGlobalSection')
_p('\tGlobalSection(ProjectDependencies) = postSolution')
_p('\tEndGlobalSection')
_p('\tGlobalSection(ProjectConfiguration) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfgname in ipairs(sln.configurations) do
_p('\t\t{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
_p('\t\t{%s}.%s.Build.0 = %s|%s', prj.uuid, cfgname, cfgname, _VS.arch(prj))
end
end
_p('\tEndGlobalSection')
_p('\tGlobalSection(ExtensibilityGlobals) = postSolution')
_p('\tEndGlobalSection')
_p('\tGlobalSection(ExtensibilityAddIns) = postSolution')
_p('\tEndGlobalSection')
_p('EndGlobal')
end

View File

@ -0,0 +1,208 @@
--
-- vs2005_csproj.lua
-- Generate a Visual Studio 2005/2008 C# project.
-- Copyright (c) 2009-2010 Jason Perkins and the Premake project
--
--
-- Set up namespaces
--
premake.vstudio.cs2005 = { }
local vstudio = premake.vstudio
local cs2005 = premake.vstudio.cs2005
--
-- Figure out what elements a particular source code file need in its item
-- block, based on its build action and any related files in the project.
--
local function getelements(prj, action, fname)
if action == "Compile" and fname:endswith(".cs") then
if fname:endswith(".Designer.cs") then
-- is there a matching *.cs file?
local basename = fname:sub(1, -13)
local testname = basename .. ".cs"
if premake.findfile(prj, testname) then
return "Dependency", testname
end
-- is there a matching *.resx file?
testname = basename .. ".resx"
if premake.findfile(prj, testname) then
return "AutoGen", testname
end
else
-- is there a *.Designer.cs file?
local basename = fname:sub(1, -4)
local testname = basename .. ".Designer.cs"
if premake.findfile(prj, testname) then
return "SubTypeForm"
end
end
end
if action == "EmbeddedResource" and fname:endswith(".resx") then
-- is there a matching *.cs file?
local basename = fname:sub(1, -6)
local testname = path.getname(basename .. ".cs")
if premake.findfile(prj, testname) then
if premake.findfile(prj, basename .. ".Designer.cs") then
return "DesignerType", testname
else
return "Dependency", testname
end
else
-- is there a matching *.Designer.cs?
testname = path.getname(basename .. ".Designer.cs")
if premake.findfile(prj, testname) then
return "AutoGenerated"
end
end
end
if action == "Content" then
return "CopyNewest"
end
return "None"
end
--
-- Write the opening <Project> element and project level <PropertyGroup> block.
--
function cs2005.projectelement(prj)
_p('<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"%s>', iif(_ACTION == 'vs2005', '', ' ToolsVersion="3.5"'))
end
function cs2005.projectsettings(prj)
_p(' <PropertyGroup>')
_p(' <Configuration Condition=" \'$(Configuration)\' == \'\' ">%s</Configuration>', premake.esc(prj.solution.configurations[1]))
_p(' <Platform Condition=" \'$(Platform)\' == \'\' ">AnyCPU</Platform>')
_p(' <ProductVersion>%s</ProductVersion>', iif(_ACTION == "vs2005", "8.0.50727", "9.0.21022"))
_p(' <SchemaVersion>2.0</SchemaVersion>')
_p(' <ProjectGuid>{%s}</ProjectGuid>', prj.uuid)
_p(' <OutputType>%s</OutputType>', premake.dotnet.getkind(prj))
_p(' <AppDesignerFolder>Properties</AppDesignerFolder>')
_p(' <RootNamespace>%s</RootNamespace>', prj.buildtarget.basename)
_p(' <AssemblyName>%s</AssemblyName>', prj.buildtarget.basename)
if prj.framework then
_p(' <TargetFrameworkVersion>v%s</TargetFrameworkVersion>', prj.framework)
end
_p(' </PropertyGroup>')
end
--
-- The main function: write the project file.
--
function premake.vs2005_csproj(prj)
io.eol = "\r\n"
local vsversion, toolversion
if _ACTION == "vs2005" then
vsversion = "8.0.50727"
toolversion = nil
elseif _ACTION == "vs2008" then
vsversion = "9.0.21022"
toolversion = "3.5"
end
if toolversion then
_p('<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="%s">', toolversion)
else
_p('<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">')
end
_p(' <PropertyGroup>')
_p(' <Configuration Condition=" \'$(Configuration)\' == \'\' ">%s</Configuration>', premake.esc(prj.solution.configurations[1]))
_p(' <Platform Condition=" \'$(Platform)\' == \'\' ">AnyCPU</Platform>')
_p(' <ProductVersion>%s</ProductVersion>', vsversion)
_p(' <SchemaVersion>2.0</SchemaVersion>')
_p(' <ProjectGuid>{%s}</ProjectGuid>', prj.uuid)
_p(' <OutputType>%s</OutputType>', premake.dotnet.getkind(prj))
_p(' <AppDesignerFolder>Properties</AppDesignerFolder>')
_p(' <RootNamespace>%s</RootNamespace>', prj.buildtarget.basename)
_p(' <AssemblyName>%s</AssemblyName>', prj.buildtarget.basename)
_p(' </PropertyGroup>')
for cfg in premake.eachconfig(prj) do
_p(' <PropertyGroup Condition=" \'$(Configuration)|$(Platform)\' == \'%s|AnyCPU\' ">', premake.esc(cfg.name))
if cfg.flags.Symbols then
_p(' <DebugSymbols>true</DebugSymbols>')
_p(' <DebugType>full</DebugType>')
else
_p(' <DebugType>pdbonly</DebugType>')
end
_p(' <Optimize>%s</Optimize>', iif(cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed, "true", "false"))
_p(' <OutputPath>%s</OutputPath>', cfg.buildtarget.directory)
_p(' <DefineConstants>%s</DefineConstants>', table.concat(premake.esc(cfg.defines), ";"))
_p(' <ErrorReport>prompt</ErrorReport>')
_p(' <WarningLevel>4</WarningLevel>')
if cfg.flags.Unsafe then
_p(' <AllowUnsafeBlocks>true</AllowUnsafeBlocks>')
end
if cfg.flags.FatalWarnings then
_p(' <TreatWarningsAsErrors>true</TreatWarningsAsErrors>')
end
_p(' </PropertyGroup>')
end
_p(' <ItemGroup>')
for _, ref in ipairs(premake.getlinks(prj, "siblings", "object")) do
_p(' <ProjectReference Include="%s">', path.translate(path.getrelative(prj.location, _VS.projectfile(ref)), "\\"))
_p(' <Project>{%s}</Project>', ref.uuid)
_p(' <Name>%s</Name>', premake.esc(ref.name))
_p(' </ProjectReference>')
end
for _, linkname in ipairs(premake.getlinks(prj, "system", "basename")) do
_p(' <Reference Include="%s" />', premake.esc(linkname))
end
_p(' </ItemGroup>')
_p(' <ItemGroup>')
for fcfg in premake.eachfile(prj) do
local action = premake.dotnet.getbuildaction(fcfg)
local fname = path.translate(premake.esc(fcfg.name), "\\")
local elements, dependency = getelements(prj, action, fcfg.name)
if elements == "None" then
_p(' <%s Include="%s" />', action, fname)
else
_p(' <%s Include="%s">', action, fname)
if elements == "AutoGen" then
_p(' <AutoGen>True</AutoGen>')
elseif elements == "AutoGenerated" then
_p(' <SubType>Designer</SubType>')
_p(' <Generator>ResXFileCodeGenerator</Generator>')
_p(' <LastGenOutput>%s.Designer.cs</LastGenOutput>', premake.esc(path.getbasename(fcfg.name)))
elseif elements == "SubTypeDesigner" then
_p(' <SubType>Designer</SubType>')
elseif elements == "SubTypeForm" then
_p(' <SubType>Form</SubType>')
elseif elements == "PreserveNewest" then
_p(' <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>')
end
if dependency then
_p(' <DependentUpon>%s</DependentUpon>', path.translate(premake.esc(dependency), "\\"))
end
_p(' </%s>', action)
end
end
_p(' </ItemGroup>')
_p(' <Import Project="$(MSBuildBinPath)\\Microsoft.CSharp.targets" />')
_p(' <!-- To modify your build process, add your task inside one of the targets below and uncomment it.')
_p(' Other similar extension points exist, see Microsoft.Common.targets.')
_p(' <Target Name="BeforeBuild">')
_p(' </Target>')
_p(' <Target Name="AfterBuild">')
_p(' </Target>')
_p(' -->')
_p('</Project>')
end

View File

@ -0,0 +1,18 @@
--
-- vs2005_csproj_user.lua
-- Generate a Visual Studio 2005/2008 C# .user file.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.vs2005_csproj_user(prj)
io.eol = "\r\n"
_p('<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">')
_p(' <PropertyGroup>')
local refpaths = table.translate(prj.libdirs, function(v) return path.getabsolute(prj.location .. "/" .. v) end)
_p(' <ReferencePath>%s</ReferencePath>', path.translate(table.concat(refpaths, ";"), "\\"))
_p(' </PropertyGroup>')
_p('</Project>')
end

View File

@ -0,0 +1,105 @@
--
-- vs2005_solution.lua
-- Generate a Visual Studio 2005 or 2008 solution.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
function premake.vs2005_solution(sln)
io.eol = '\r\n'
-- Precompute Visual Studio configurations
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
-- Mark the file as Unicode
_p('\239\187\191')
-- Write the solution file version header
_p('Microsoft Visual Studio Solution File, Format Version %s', iif(_ACTION == 'vs2005', '9.00', '10.00'))
_p('# Visual Studio %s', iif(_ACTION == 'vs2005', '2005', '2008'))
-- Write out the list of project entries
for prj in premake.solution.eachproject(sln) do
-- Build a relative path from the solution file to the project file
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)), "\\")
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
_p('Global')
premake.vs2005_solution_platforms(sln)
premake.vs2005_solution_project_platforms(sln)
premake.vs2005_solution_properties(sln)
_p('EndGlobal')
end
--
-- Write out the contents of the SolutionConfigurationPlatforms section, which
-- lists all of the configuration/platform pairs that exist in the solution.
--
function premake.vs2005_solution_platforms(sln)
_p('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution')
for _, cfg in ipairs(sln.vstudio_configs) do
_p('\t\t%s = %s', cfg.name, cfg.name)
end
_p('\tEndGlobalSection')
end
--
-- Write out the contents of the ProjectConfigurationPlatforms section, which maps
-- the configuration/platform pairs into each project of the solution.
--
function premake.vs2005_solution_project_platforms(sln)
_p('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution')
for prj in premake.solution.eachproject(sln) do
for _, cfg in ipairs(sln.vstudio_configs) do
-- .NET projects always map to the "Any CPU" platform (for now, at
-- least). For C++, "Any CPU" and "Mixed Platforms" map to the first
-- C++ compatible target platform in the solution list.
local mapped
if premake.isdotnetproject(prj) then
mapped = "Any CPU"
else
if cfg.platform == "Any CPU" or cfg.platform == "Mixed Platforms" then
mapped = sln.vstudio_configs[3].platform
else
mapped = cfg.platform
end
end
_p('\t\t{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped)
if mapped == cfg.platform or cfg.platform == "Mixed Platforms" then
_p('\t\t{%s}.%s.Build.0 = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped)
end
end
end
_p('\tEndGlobalSection')
end
--
-- Write out contents of the SolutionProperties section; currently unused.
--
function premake.vs2005_solution_properties(sln)
_p('\tGlobalSection(SolutionProperties) = preSolution')
_p('\t\tHideSolutionNode = FALSE')
_p('\tEndGlobalSection')
end

View File

@ -0,0 +1,654 @@
--
-- vs200x_vcproj.lua
-- Generate a Visual Studio 2002-2008 C/C++ project.
-- Copyright (c) 2009, 2010 Jason Perkins and the Premake project
--
premake.vstudio.vcproj = { }
local vcproj = premake.vstudio.vcproj
--
-- Write out the <Configuration> element.
--
function vcproj.Configuration(name, cfg)
_p(2,'<Configuration')
_p(3,'Name="%s"', premake.esc(name))
_p(3,'OutputDirectory="%s"', premake.esc(cfg.buildtarget.directory))
_p(3,'IntermediateDirectory="%s"', premake.esc(cfg.objectsdir))
_p(3,'ConfigurationType="%s"', _VS.cfgtype(cfg))
if (cfg.flags.MFC) then
_p(3, 'UseOfMFC="2"')
end
_p(3,'CharacterSet="%s"', iif(cfg.flags.Unicode, 1, 2))
if cfg.flags.Managed then
_p(3,'ManagedExtensions="1"')
end
_p(3,'>')
end
--
-- Write out the <Platforms> element; ensures that each target platform
-- is listed only once. Skips over .NET's pseudo-platforms (like "Any CPU").
--
function premake.vs200x_vcproj_platforms(prj)
local used = { }
_p(1,'<Platforms>')
for _, cfg in ipairs(prj.solution.vstudio_configs) do
if cfg.isreal and not table.contains(used, cfg.platform) then
table.insert(used, cfg.platform)
_p(2,'<Platform')
_p(3,'Name="%s"', cfg.platform)
_p(2,'/>')
end
end
_p(1,'</Platforms>')
end
--
-- Return the debugging symbols level for a configuration.
--
function premake.vs200x_vcproj_symbols(cfg)
if (not cfg.flags.Symbols) then
return 0
else
-- Edit-and-continue does't work for some configurations
if cfg.flags.NoEditAndContinue or
_VS.optimization(cfg) ~= 0 or
cfg.flags.Managed or
cfg.platform == "x64" then
return 3
else
return 4
end
end
end
--
-- Compiler block for Windows and XBox360 platforms.
--
function premake.vs200x_vcproj_VCCLCompilerTool(cfg)
_p(3,'<Tool')
_p(4,'Name="%s"', iif(cfg.platform ~= "Xbox360", "VCCLCompilerTool", "VCCLX360CompilerTool"))
if #cfg.buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.buildoptions), " "))
end
_p(4,'Optimization="%s"', _VS.optimization(cfg))
if cfg.flags.NoFramePointer then
_p(4,'OmitFramePointers="%s"', _VS.bool(true))
end
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', premake.esc(table.concat(cfg.defines, ";")))
end
if premake.config.isdebugbuild(cfg) and not cfg.flags.NoMinimalRebuild and not cfg.flags.Managed then
_p(4,'MinimalRebuild="%s"', _VS.bool(true))
end
if cfg.flags.NoExceptions then
_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
elseif cfg.flags.SEH and _ACTION > "vs2003" then
_p(4,'ExceptionHandling="2"')
end
if _VS.optimization(cfg) == 0 and not cfg.flags.Managed then
_p(4,'BasicRuntimeChecks="3"')
end
if _VS.optimization(cfg) ~= 0 then
_p(4,'StringPooling="%s"', _VS.bool(true))
end
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime, 1, 3)
else
runtime = iif(cfg.flags.StaticRuntime, 0, 2)
end
-- if cfg.flags.StaticRuntime then
-- runtime = iif(cfg.flags.Symbols, 1, 0)
-- else
-- runtime = iif(cfg.flags.Symbols, 3, 2)
-- end
_p(4,'RuntimeLibrary="%s"', runtime)
_p(4,'EnableFunctionLevelLinking="%s"', _VS.bool(true))
if _ACTION > "vs2003" and cfg.platform ~= "Xbox360" and cfg.platform ~= "x64" then
if cfg.flags.EnableSSE then
_p(4,'EnableEnhancedInstructionSet="1"')
elseif cfg.flags.EnableSSE2 then
_p(4,'EnableEnhancedInstructionSet="2"')
end
end
if _ACTION < "vs2005" then
if cfg.flags.FloatFast then
_p(4,'ImproveFloatingPointConsistency="%s"', _VS.bool(false))
elseif cfg.flags.FloatStrict then
_p(4,'ImproveFloatingPointConsistency="%s"', _VS.bool(true))
end
else
if cfg.flags.FloatFast then
_p(4,'FloatingPointModel="2"')
elseif cfg.flags.FloatStrict then
_p(4,'FloatingPointModel="1"')
end
end
if _ACTION < "vs2005" and not cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', _VS.bool(true))
elseif _ACTION > "vs2003" and cfg.flags.NoRTTI then
_p(4,'RuntimeTypeInfo="%s"', _VS.bool(false))
end
if cfg.flags.NativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', _VS.bool(true))
elseif cfg.flags.NoNativeWChar then
_p(4,'TreatWChar_tAsBuiltInType="%s"', _VS.bool(false))
end
if not cfg.flags.NoPCH and cfg.pchheader then
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
_p(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
else
_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
end
_p(4,'WarningLevel="%s"', iif(cfg.flags.ExtraWarnings, 4, 3))
if cfg.flags.FatalWarnings then
_p(4,'WarnAsError="%s"', _VS.bool(true))
end
if _ACTION < "vs2008" and not cfg.flags.Managed then
_p(4,'Detect64BitPortabilityProblems="%s"', _VS.bool(not cfg.flags.No64BitChecks))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="%s"', premake.vs200x_vcproj_symbols(cfg))
if cfg.language == "C" then
_p(4, 'CompileAs="1"')
end
_p(3,'/>')
end
--
-- Linker block for Windows and Xbox 360 platforms.
--
function premake.vs200x_vcproj_VCLinkerTool(cfg)
_p(3,'<Tool')
if cfg.kind ~= "StaticLib" then
_p(4,'Name="%s"', iif(cfg.platform ~= "Xbox360", "VCLinkerTool", "VCX360LinkerTool"))
if cfg.flags.NoImportLib then
_p(4,'IgnoreImportLibrary="%s"', _VS.bool(true))
end
if #cfg.linkoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.linkoptions), " "))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="%s"', iif(_VS.optimization(cfg) == 0, 2, 1))
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
local deffile = premake.findfile(cfg, ".def")
if deffile then
_p(4,'ModuleDefinitionFile="%s"', deffile)
end
if cfg.flags.NoManifest then
_p(4,'GenerateManifest="%s"', _VS.bool(false))
end
_p(4,'GenerateDebugInformation="%s"', _VS.bool(premake.vs200x_vcproj_symbols(cfg) ~= 0))
if premake.vs200x_vcproj_symbols(cfg) ~= 0 then
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
end
_p(4,'SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2))
if _VS.optimization(cfg) ~= 0 then
_p(4,'OptimizeReferences="2"')
_p(4,'EnableCOMDATFolding="2"')
end
if (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") and not cfg.flags.WinMain then
_p(4,'EntryPointSymbol="mainCRTStartup"')
end
if cfg.kind == "SharedLib" then
local implibname = cfg.linktarget.fullpath
_p(4,'ImportLibrary="%s"', iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname))
end
_p(4,'TargetMachine="%d"', iif(cfg.platform == "x64", 17, 1))
else
_p(4,'Name="VCLibrarianTool"')
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
if #cfg.linkoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.linkoptions), " "))
end
end
_p(3,'/>')
end
--
-- Compiler and linker blocks for the PS3 platform, which uses GCC.
--
function premake.vs200x_vcproj_VCCLCompilerTool_GCC(cfg)
_p(3,'<Tool')
_p(4,'Name="VCCLCompilerTool"')
local buildoptions = table.join(premake.gcc.getcflags(cfg), premake.gcc.getcxxflags(cfg), cfg.buildoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.includedirs > 0 then
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
if #cfg.defines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(cfg.defines), ";"))
end
_p(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', path.getbasename(cfg.buildtarget.name))
_p(4,'DebugInformationFormat="0"')
_p(4,'CompileAs="0"')
_p(3,'/>')
end
function premake.vs200x_vcproj_VCLinkerTool_GCC(cfg)
_p(3,'<Tool')
if cfg.kind ~= "StaticLib" then
_p(4,'Name="VCLinkerTool"')
local buildoptions = table.join(premake.gcc.getldflags(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
_p(4,'LinkIncremental="0"')
_p(4,'AdditionalLibraryDirectories="%s"', table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"))
_p(4,'GenerateManifest="%s"', _VS.bool(false))
_p(4,'ProgramDatabaseFile=""')
_p(4,'RandomizedBaseAddress="1"')
_p(4,'DataExecutionPrevention="0"')
else
_p(4,'Name="VCLibrarianTool"')
local buildoptions = table.join(premake.gcc.getldflags(cfg), cfg.linkoptions)
if #buildoptions > 0 then
_p(4,'AdditionalOptions="%s"', premake.esc(table.concat(buildoptions, " ")))
end
if #cfg.links > 0 then
_p(4,'AdditionalDependencies="%s"', table.concat(premake.getlinks(cfg, "all", "fullpath"), " "))
end
_p(4,'OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name)
if #cfg.libdirs > 0 then
_p(4,'AdditionalLibraryDirectories="%s"', premake.esc(path.translate(table.concat(cfg.libdirs , ";"))))
end
end
_p(3,'/>')
end
--
-- Resource compiler block.
--
function premake.vs200x_vcproj_VCResourceCompilerTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCResourceCompilerTool"')
if #cfg.resoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.resoptions), " "))
end
if #cfg.defines > 0 or #cfg.resdefines > 0 then
_p(4,'PreprocessorDefinitions="%s"', table.concat(premake.esc(table.join(cfg.defines, cfg.resdefines)), ";"))
end
if #cfg.includedirs > 0 or #cfg.resincludedirs > 0 then
local dirs = table.join(cfg.includedirs, cfg.resincludedirs)
_p(4,'AdditionalIncludeDirectories="%s"', premake.esc(path.translate(table.concat(dirs, ";"), '\\')))
end
_p(3,'/>')
end
--
-- Manifest block.
--
function premake.vs200x_vcproj_VCManifestTool(cfg)
-- locate all manifest files
local manifests = { }
for _, fname in ipairs(cfg.files) do
if path.getextension(fname) == ".manifest" then
table.insert(manifests, fname)
end
end
_p(3,'<Tool')
_p(4,'Name="VCManifestTool"')
if #manifests > 0 then
_p(4,'AdditionalManifestFiles="%s"', premake.esc(table.concat(manifests, ";")))
end
_p(3,'/>')
end
--
-- VCMIDLTool block
--
function premake.vs200x_vcproj_VCMIDLTool(cfg)
_p(3,'<Tool')
_p(4,'Name="VCMIDLTool"')
if cfg.platform == "x64" then
_p(4,'TargetEnvironment="3"')
end
_p(3,'/>')
end
--
-- Write out a custom build steps block.
--
function premake.vs200x_vcproj_buildstepsblock(name, steps)
_p(3,'<Tool')
_p(4,'Name="%s"', name)
if #steps > 0 then
_p(4,'CommandLine="%s"', premake.esc(table.implode(steps, "", "", "\r\n")))
end
_p(3,'/>')
end
--
-- Map project tool blocks to handler functions. Unmapped blocks will output
-- an empty <Tool> element.
--
local blockmap =
{
VCCLCompilerTool = premake.vs200x_vcproj_VCCLCompilerTool,
VCCLCompilerTool_GCC = premake.vs200x_vcproj_VCCLCompilerTool_GCC,
VCLinkerTool = premake.vs200x_vcproj_VCLinkerTool,
VCLinkerTool_GCC = premake.vs200x_vcproj_VCLinkerTool_GCC,
VCManifestTool = premake.vs200x_vcproj_VCManifestTool,
VCMIDLTool = premake.vs200x_vcproj_VCMIDLTool,
VCResourceCompilerTool = premake.vs200x_vcproj_VCResourceCompilerTool,
}
--
-- Return a list of sections for a particular Visual Studio version and target platform.
--
local function getsections(version, platform)
if version == "vs2002" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCWebDeploymentTool"
}
end
if version == "vs2003" then
return {
"VCCLCompilerTool",
"VCCustomBuildTool",
"VCLinkerTool",
"VCMIDLTool",
"VCPostBuildEventTool",
"VCPreBuildEventTool",
"VCPreLinkEventTool",
"VCResourceCompilerTool",
"VCWebServiceProxyGeneratorTool",
"VCXMLDataGeneratorTool",
"VCWebDeploymentTool",
"VCManagedWrapperGeneratorTool",
"VCAuxiliaryManagedWrapperGeneratorTool"
}
end
if platform == "Xbox360" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCX360ImageTool",
"VCBscMakeTool",
"VCX360DeploymentTool",
"VCPostBuildEventTool",
"DebuggerTool",
}
end
if platform == "PS3" then
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool_GCC",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool_GCC",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
else
return {
"VCPreBuildEventTool",
"VCCustomBuildTool",
"VCXMLDataGeneratorTool",
"VCWebServiceProxyGeneratorTool",
"VCMIDLTool",
"VCCLCompilerTool",
"VCManagedResourceCompilerTool",
"VCResourceCompilerTool",
"VCPreLinkEventTool",
"VCLinkerTool",
"VCALinkTool",
"VCManifestTool",
"VCXDCMakeTool",
"VCBscMakeTool",
"VCFxCopTool",
"VCAppVerifierTool",
"VCWebDeploymentTool",
"VCPostBuildEventTool"
}
end
end
--
-- The main function: write the project file.
--
function premake.vs200x_vcproj(prj)
io.eol = "\r\n"
_p('<?xml version="1.0" encoding="Windows-1252"?>')
-- Write opening project block
_p('<VisualStudioProject')
_p(1,'ProjectType="Visual C++"')
if _ACTION == "vs2002" then
_p(1,'Version="7.00"')
elseif _ACTION == "vs2003" then
_p(1,'Version="7.10"')
elseif _ACTION == "vs2005" then
_p(1,'Version="8.00"')
elseif _ACTION == "vs2008" then
_p(1,'Version="9.00"')
end
_p(1,'Name="%s"', premake.esc(prj.name))
_p(1,'ProjectGUID="{%s}"', prj.uuid)
if _ACTION > "vs2003" then
_p(1,'RootNamespace="%s"', prj.name)
end
_p(1,'Keyword="%s"', iif(prj.flags.Managed, "ManagedCProj", "Win32Proj"))
_p(1,'>')
-- list the target platforms
premake.vs200x_vcproj_platforms(prj)
if _ACTION > "vs2003" then
_p(1,'<ToolFiles>')
_p(1,'</ToolFiles>')
end
_p(1,'<Configurations>')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
if cfginfo.isreal then
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
-- Start a configuration
vcproj.Configuration(cfginfo.name, cfg)
for _, block in ipairs(getsections(_ACTION, cfginfo.src_platform)) do
if blockmap[block] then
blockmap[block](cfg)
-- Build event blocks --
elseif block == "VCPreBuildEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPreBuildEventTool", cfg.prebuildcommands)
elseif block == "VCPreLinkEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPreLinkEventTool", cfg.prelinkcommands)
elseif block == "VCPostBuildEventTool" then
premake.vs200x_vcproj_buildstepsblock("VCPostBuildEventTool", cfg.postbuildcommands)
-- End build event blocks --
-- Xbox 360 custom sections --
elseif block == "VCX360DeploymentTool" then
_p(3,'<Tool')
_p(4,'Name="VCX360DeploymentTool"')
_p(4,'DeploymentType="0"')
if #cfg.deploymentoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.deploymentoptions), " "))
end
_p(3,'/>')
elseif block == "VCX360ImageTool" then
_p(3,'<Tool')
_p(4,'Name="VCX360ImageTool"')
if #cfg.imageoptions > 0 then
_p(4,'AdditionalOptions="%s"', table.concat(premake.esc(cfg.imageoptions), " "))
end
if cfg.imagepath ~= nil then
_p(4,'OutputFileName="%s"', premake.esc(path.translate(cfg.imagepath)))
end
_p(3,'/>')
elseif block == "DebuggerTool" then
_p(3,'<DebuggerTool')
_p(3,'/>')
-- End Xbox 360 custom sections --
else
_p(3,'<Tool')
_p(4,'Name="%s"', block)
_p(3,'/>')
end
end
_p(2,'</Configuration>')
end
end
_p(1,'</Configurations>')
_p(1,'<References>')
_p(1,'</References>')
_p(1,'<Files>')
premake.walksources(prj, _VS.files)
_p(1,'</Files>')
_p(1,'<Globals>')
_p(1,'</Globals>')
_p('</VisualStudioProject>')
end

View File

@ -0,0 +1,689 @@
premake.vstudio.vs10_helpers = { }
local vs10_helpers = premake.vstudio.vs10_helpers
function vs10_helpers.remove_relative_path(file)
file = file:gsub("%.%.\\",'')
file = file:gsub("%.\\",'')
return file
end
function vs10_helpers.file_path(file)
file = vs10_helpers.remove_relative_path(file)
local path = string.find(file,'\\[%w%.%_%-]+$')
if path then
return string.sub(file,1,path-1)
else
return nil
end
end
function vs10_helpers.list_of_directories_in_path(path)
local list={}
path = vs10_helpers.remove_relative_path(path)
if path then
for dir in string.gmatch(path,"[%w%-%_%.]+\\")do
if #list == 0 then
list[1] = dir:sub(1,#dir-1)
else
list[#list +1] = list[#list] .."\\" ..dir:sub(1,#dir-1)
end
end
end
return list
end
function vs10_helpers.table_of_file_filters(files)
local filters ={}
for _, valueTable in pairs(files) do
for _, entry in ipairs(valueTable) do
local result = vs10_helpers.list_of_directories_in_path(entry)
for __,dir in ipairs(result) do
if table.contains(filters,dir) ~= true then
filters[#filters +1] = dir
end
end
end
end
return filters
end
function vs10_helpers.get_file_extension(file)
local ext_start,ext_end = string.find(file,"%.[%w_%-]+$")
if ext_start then
return string.sub(file,ext_start+1,ext_end)
end
end
--also translates file paths from '/' to '\\'
function vs10_helpers.sort_input_files(files,sorted_container)
local types =
{
h = "ClInclude",
hpp = "ClInclude",
hxx = "ClInclude",
c = "ClCompile",
cpp = "ClCompile",
cxx = "ClCompile",
cc = "ClCompile",
rc = "ResourceCompile"
}
for _, current_file in ipairs(files) do
local translated_path = path.translate(current_file, '\\')
local ext = vs10_helpers.get_file_extension(translated_path)
if ext then
local type = types[ext]
if type then
table.insert(sorted_container[type],translated_path)
else
table.insert(sorted_container.None,translated_path)
end
end
end
end
local function vs2010_config(prj)
_p(1,'<ItemGroup Label="ProjectConfigurations">')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
_p(2,'<ProjectConfiguration Include="%s">', premake.esc(cfginfo.name))
_p(3,'<Configuration>%s</Configuration>',cfginfo.buildcfg)
_p(3,'<Platform>%s</Platform>',cfginfo.platform)
_p(2,'</ProjectConfiguration>')
end
_p(1,'</ItemGroup>')
end
local function vs2010_globals(prj)
_p(1,'<PropertyGroup Label="Globals">')
_p(2,'<ProjectGuid>{%s}</ProjectGuid>',prj.uuid)
_p(2,'<RootNamespace>%s</RootNamespace>',prj.name)
_p(2,'<Keyword>Win32Proj</Keyword>')
_p(1,'</PropertyGroup>')
end
function vs10_helpers.config_type(config)
local t =
{
SharedLib = "DynamicLibrary",
StaticLib = "StaticLibrary",
ConsoleApp = "Application",
WindowedApp = "Application"
}
return t[config.kind]
end
local function if_config_and_platform()
return 'Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"'
end
local function optimisation(cfg)
local result = "Disabled"
for _, value in ipairs(cfg.flags) do
if (value == "Optimize") then
result = "Full"
elseif (value == "OptimizeSize") then
result = "MinSpace"
elseif (value == "OptimizeSpeed") then
result = "MaxSpeed"
end
end
return result
end
local function config_type_block(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,'<PropertyGroup '..if_config_and_platform() ..' Label="Configuration">'
, premake.esc(cfginfo.name))
_p(2,'<ConfigurationType>%s</ConfigurationType>',vs10_helpers.config_type(cfg))
_p(2,'<CharacterSet>%s</CharacterSet>',iif(cfg.flags.Unicode,"Unicode","MultiByte"))
if cfg.flags.MFC then
_p(2,'<UseOfMfc>Dynamic</UseOfMfc>')
end
_p(2,'<UseDebugLibraries>%s</UseDebugLibraries>'
,iif(optimisation(cfg) == "Disabled","true","false"))
_p(1,'</PropertyGroup>')
end
end
local function import_props(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,'<ImportGroup '..if_config_and_platform() ..' Label="PropertySheets">'
,premake.esc(cfginfo.name))
_p(2,'<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />')
_p(1,'</ImportGroup>')
end
end
local function incremental_link(cfg,cfginfo)
if cfg.kind ~= "StaticLib" then
ShoudLinkIncrementally = 'false'
if optimisation(cfg) == "Disabled" then
ShoudLinkIncrementally = 'true'
end
_p(2,'<LinkIncremental '..if_config_and_platform() ..'>%s</LinkIncremental>'
,premake.esc(cfginfo.name),ShoudLinkIncrementally)
end
end
local function ignore_import_lib(cfg,cfginfo)
if cfg.kind == "SharedLib" then
local shouldIgnore = "false"
if cfg.flags.NoImportLib then shouldIgnore = "true" end
_p(2,'<IgnoreImportLibrary '..if_config_and_platform() ..'>%s</IgnoreImportLibrary>'
,premake.esc(cfginfo.name),shouldIgnore)
end
end
local function intermediate_and_out_dirs(prj)
_p(1,'<PropertyGroup>')
_p(2,'<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>')
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(2,'<OutDir '..if_config_and_platform() ..'>%s\\</OutDir>'
, premake.esc(cfginfo.name),premake.esc(cfg.buildtarget.directory) )
_p(2,'<IntDir '..if_config_and_platform() ..'>%s\\</IntDir>'
, premake.esc(cfginfo.name), premake.esc(cfg.objectsdir))
_p(2,'<TargetName '..if_config_and_platform() ..'>%s</TargetName>'
,premake.esc(cfginfo.name),path.getbasename(cfg.buildtarget.name))
ignore_import_lib(cfg,cfginfo)
incremental_link(cfg,cfginfo)
if cfg.flags.NoManifest then
_p(2,'<GenerateManifest '..if_config_and_platform() ..'>false</GenerateManifest>'
,premake.esc(cfginfo.name))
end
end
_p(1,'</PropertyGroup>')
end
local function runtime(cfg)
local runtime
if premake.config.isdebugbuild(cfg) then
runtime = iif(cfg.flags.StaticRuntime,"MultiThreadedDebug", "MultiThreadedDebugDLL")
else
runtime = iif(cfg.flags.StaticRuntime, "MultiThreaded", "MultiThreadedDLL")
end
return runtime
end
local function precompiled_header(cfg)
if not cfg.flags.NoPCH and cfg.pchheader then
_p(3,'<PrecompiledHeader>Use</PrecompiledHeader>')
_p(3,'<PrecompiledHeaderFile>%s</PrecompiledHeaderFile>', path.getname(cfg.pchheader))
else
_p(3,'<PrecompiledHeader></PrecompiledHeader>')
end
end
local function preprocessor(indent,cfg)
if #cfg.defines > 0 then
_p(indent,'<PreprocessorDefinitions>%s;%%(PreprocessorDefinitions)</PreprocessorDefinitions>'
,premake.esc(table.concat(cfg.defines, ";")))
else
_p(indent,'<PreprocessorDefinitions></PreprocessorDefinitions>')
end
end
local function include_dirs(indent,cfg)
if #cfg.includedirs > 0 then
_p(indent,'<AdditionalIncludeDirectories>%s;%%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>'
,premake.esc(path.translate(table.concat(cfg.includedirs, ";"), '\\')))
end
end
local function resource_compile(cfg)
_p(2,'<ResourceCompile>')
preprocessor(3,cfg)
include_dirs(3,cfg)
_p(2,'</ResourceCompile>')
end
local function exceptions(cfg)
if cfg.flags.NoExceptions then
_p(2,'<ExceptionHandling>false</ExceptionHandling>')
elseif cfg.flags.SEH then
_p(2,'<ExceptionHandling>Async</ExceptionHandling>')
end
end
local function rtti(cfg)
if cfg.flags.NoRTTI then
_p(3,'<RuntimeTypeInfo>false</RuntimeTypeInfo>')
end
end
local function wchar_t_buildin(cfg)
if cfg.flags.NativeWChar then
_p(3,'<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>')
elseif cfg.flags.NoNativeWChar then
_p(3,'<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>')
end
end
local function sse(cfg)
if cfg.flags.EnableSSE then
_p(3,'<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>')
elseif cfg.flags.EnableSSE2 then
_p(3,'<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>')
end
end
local function floating_point(cfg)
if cfg.flags.FloatFast then
_p(3,'<FloatingPointModel>Fast</FloatingPointModel>')
elseif cfg.flags.FloatStrict then
_p(3,'<FloatingPointModel>Strict</FloatingPointModel>')
end
end
local function debug_info(cfg)
--
-- EditAndContinue /ZI
-- ProgramDatabase /Zi
-- OldStyle C7 Compatable /Z7
--
local debug_info = ''
if cfg.flags.Symbols then
if optimisation(cfg) ~= "Disabled" or cfg.flags.NoEditAndContinue then
debug_info = "ProgramDatabase"
elseif cfg.platform ~= "x64" then
debug_info = "EditAndContinue"
else
debug_info = "OldStyle"
end
end
_p(3,'<DebugInformationFormat>%s</DebugInformationFormat>',debug_info)
end
local function minimal_build(cfg)
if premake.config.isdebugbuild(cfg) and not cfg.flags.NoMinimalRebuild then
_p(3,'<MinimalRebuild>true</MinimalRebuild>')
else
_p(3,'<MinimalRebuild>false</MinimalRebuild>')
end
end
local function compile_language(cfg)
if cfg.language == "C" then
_p(3,'<CompileAs>CompileAsC</CompileAs>')
end
end
local function vs10_clcompile(cfg)
_p(2,'<ClCompile>')
if #cfg.buildoptions > 0 then
_p(3,'<AdditionalOptions>%s %%(AdditionalOptions)</AdditionalOptions>',
table.concat(premake.esc(cfg.buildoptions), " "))
end
_p(3,'<Optimization>%s</Optimization>',optimisation(cfg))
include_dirs(3,cfg)
preprocessor(3,cfg)
minimal_build(cfg)
if optimisation(cfg) == "Disabled" then
_p(3,'<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>')
if cfg.flags.ExtraWarnings then
_p(3,'<SmallerTypeCheck>true</SmallerTypeCheck>')
end
else
_p(3,'<StringPooling>true</StringPooling>')
end
_p(3,'<RuntimeLibrary>%s</RuntimeLibrary>', runtime(cfg))
_p(3,'<FunctionLevelLinking>true</FunctionLevelLinking>')
precompiled_header(cfg)
if cfg.flags.ExtraWarnings then
_p(3,'<WarningLevel>Level4</WarningLevel>')
else
_p(3,'<WarningLevel>Level3</WarningLevel>')
end
if cfg.flags.FatalWarnings then
_p(3,'<TreatWarningAsError>true</TreatWarningAsError>')
end
exceptions(cfg)
rtti(cfg)
wchar_t_buildin(cfg)
sse(cfg)
floating_point(cfg)
debug_info(cfg)
if cfg.flags.NoFramePointer then
_p(3,'<OmitFramePointers>true</OmitFramePointers>')
end
compile_language(cfg)
_p(2,'</ClCompile>')
end
local function event_hooks(cfg)
if #cfg.postbuildcommands> 0 then
_p(2,'<PostBuildEvent>')
_p(3,'<Command>%s</Command>',premake.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n")))
_p(2,'</PostBuildEvent>')
end
if #cfg.prebuildcommands> 0 then
_p(2,'<PreBuildEvent>')
_p(3,'<Command>%s</Command>',premake.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n")))
_p(2,'</PreBuildEvent>')
end
if #cfg.prelinkcommands> 0 then
_p(2,'<PreLinkEvent>')
_p(3,'<Command>%s</Command>',premake.esc(table.implode(cfg.prelinkcommands, "", "", "\r\n")))
_p(2,'</PreLinkEvent>')
end
end
local function additional_options(indent,cfg)
if #cfg.linkoptions > 0 then
_p(indent,'<AdditionalOptions>%s %%(AdditionalOptions)</AdditionalOptions>',
table.concat(premake.esc(cfg.linkoptions), " "))
end
end
local function item_def_lib(cfg)
if cfg.kind == 'StaticLib' then
_p(1,'<Lib>')
_p(2,'<OutputFile>$(OutDir)%s</OutputFile>',cfg.buildtarget.name)
additional_options(2,cfg)
_p(1,'</Lib>')
end
end
local function link_target_machine(cfg)
local target
if cfg.platform == nil or cfg.platform == "x32" then target ="MachineX86"
elseif cfg.platform == "x64" then target ="MachineX64"
end
_p(3,'<TargetMachine>%s</TargetMachine>', target)
end
local function import_lib(cfg)
--Prevent the generation of an import library for a Windows DLL.
if cfg.kind == "SharedLib" then
local implibname = cfg.linktarget.fullpath
_p(3,'<ImportLibrary>%s</ImportLibrary>',iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname))
end
end
local function common_link_section(cfg)
_p(3,'<SubSystem>%s</SubSystem>',iif(cfg.kind == "ConsoleApp","Console", "Windows"))
if cfg.flags.Symbols then
_p(3,'<GenerateDebugInformation>true</GenerateDebugInformation>')
else
_p(3,'<GenerateDebugInformation>false</GenerateDebugInformation>')
end
if optimisation(cfg) ~= "Disabled" then
_p(3,'<OptimizeReferences>true</OptimizeReferences>')
_p(3,'<EnableCOMDATFolding>true</EnableCOMDATFolding>')
end
if cfg.flags.Symbols then
_p(3,'<ProgramDataBaseFileName>$(OutDir)%s.pdb</ProgramDataBaseFileName>'
, path.getbasename(cfg.buildtarget.name))
end
end
local function item_link(cfg)
_p(2,'<Link>')
if cfg.kind ~= 'StaticLib' then
if #cfg.links > 0 then
_p(3,'<AdditionalDependencies>%s;%%(AdditionalDependencies)</AdditionalDependencies>',
table.concat(premake.getlinks(cfg, "all", "fullpath"), ";"))
end
_p(3,'<OutputFile>$(OutDir)%s</OutputFile>', cfg.buildtarget.name)
_p(3,'<AdditionalLibraryDirectories>%s%s%%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>',
table.concat(premake.esc(path.translate(cfg.libdirs, '\\')) , ";"),
iif(cfg.libdirs and #cfg.libdirs >0,';',''))
common_link_section(cfg)
if vs10_helpers.config_type(cfg) == 'Application' and not cfg.flags.WinMain then
_p(3,'<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>')
end
import_lib(cfg)
_p(3,'<TargetMachine>%s</TargetMachine>', iif(cfg.platform == "x64", "MachineX64", "MachineX86"))
additional_options(3,cfg)
else
common_link_section(cfg)
end
_p(2,'</Link>')
end
local function item_definitions(prj)
for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
_p(1,'<ItemDefinitionGroup ' ..if_config_and_platform() ..'>'
,premake.esc(cfginfo.name))
vs10_clcompile(cfg)
resource_compile(cfg)
item_def_lib(cfg)
item_link(cfg)
event_hooks(cfg)
_p(1,'</ItemDefinitionGroup>')
end
end
--
-- <ItemGroup>
-- <ProjectReference Include="zlibvc.vcxproj">
-- <Project>{8fd826f8-3739-44e6-8cc8-997122e53b8d}</Project>
-- </ProjectReference>
-- </ItemGroup>
--
local function write_file_type_block(files,group_type)
if #files > 0 then
_p(1,'<ItemGroup>')
for _, current_file in ipairs(files) do
_p(2,'<%s Include=\"%s\" />', group_type,current_file)
end
_p(1,'</ItemGroup>')
end
end
local function write_file_compile_block(files,prj,configs)
if #files > 0 then
local config_mappings = {}
for _, cfginfo in ipairs(configs) do
local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then
config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\")
end
end
_p(1,'<ItemGroup>')
for _, current_file in ipairs(files) do
_p(2,'<ClCompile Include=\"%s\">', current_file)
for _, cfginfo in ipairs(configs) do
if config_mappings[cfginfo] and current_file == config_mappings[cfginfo] then
_p(3,'<PrecompiledHeader '.. if_config_and_platform() .. '>Create</PrecompiledHeader>'
,premake.esc(cfginfo.name))
--only one source file per pch
config_mappings[cfginfo] = nil
end
end
_p(2,'</ClCompile>')
end
_p(1,'</ItemGroup>')
end
end
local function vcxproj_files(prj)
local sorted =
{
ClCompile ={},
ClInclude ={},
None ={},
ResourceCompile ={}
}
cfg = premake.getconfig(prj)
vs10_helpers.sort_input_files(cfg.files,sorted)
write_file_type_block(sorted.ClInclude,"ClInclude")
write_file_compile_block(sorted.ClCompile,prj,prj.solution.vstudio_configs)
write_file_type_block(sorted.None,'None')
write_file_type_block(sorted.ResourceCompile,'ResourceCompile')
end
local function write_filter_includes(sorted_table)
local directories = vs10_helpers.table_of_file_filters(sorted_table)
--I am going to take a punt here that the ItemGroup is missing if no files!!!!
--there is a test for this see
--vs10_filters.noInputFiles_bufferDoesNotContainTagItemGroup
if #directories >0 then
_p(1,'<ItemGroup>')
for _, dir in pairs(directories) do
_p(2,'<Filter Include="%s">',dir)
_p(3,'<UniqueIdentifier>{%s}</UniqueIdentifier>',os.uuid())
_p(2,'</Filter>')
end
_p(1,'</ItemGroup>')
end
end
local function write_file_filter_block(files,group_type)
if #files > 0 then
_p(1,'<ItemGroup>')
for _, current_file in ipairs(files) do
local path_to_file = vs10_helpers.file_path(current_file)
if path_to_file then
_p(2,'<%s Include=\"%s\">', group_type,path.translate(current_file, "\\"))
_p(3,'<Filter>%s</Filter>',path_to_file)
_p(2,'</%s>',group_type)
else
_p(2,'<%s Include=\"%s\" />', group_type,path.translate(current_file, "\\"))
end
end
_p(1,'</ItemGroup>')
end
end
local tool_version_and_xmlns = 'ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"'
local xml_version_and_encoding = '<?xml version="1.0" encoding="utf-8"?>'
local function vcxproj_filter_files(prj)
local sorted =
{
ClCompile ={},
ClInclude ={},
None ={},
ResourceCompile ={}
}
cfg = premake.getconfig(prj)
vs10_helpers.sort_input_files(cfg.files,sorted)
io.eol = "\r\n"
_p(xml_version_and_encoding)
_p('<Project ' ..tool_version_and_xmlns ..'>')
write_filter_includes(sorted)
write_file_filter_block(sorted.ClInclude,"ClInclude")
write_file_filter_block(sorted.ClCompile,"ClCompile")
write_file_filter_block(sorted.None,"None")
write_file_filter_block(sorted.ResourceCompile,"ResourceCompile")
_p('</Project>')
end
function premake.vs2010_vcxproj(prj)
io.eol = "\r\n"
_p(xml_version_and_encoding)
_p('<Project DefaultTargets="Build" ' ..tool_version_and_xmlns ..'>')
vs2010_config(prj)
vs2010_globals(prj)
_p(1,'<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />')
config_type_block(prj)
_p(1,'<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />')
--check what this section is doing
_p(1,'<ImportGroup Label="ExtensionSettings">')
_p(1,'</ImportGroup>')
import_props(prj)
--what type of macros are these?
_p(1,'<PropertyGroup Label="UserMacros" />')
intermediate_and_out_dirs(prj)
item_definitions(prj)
vcxproj_files(prj)
_p(1,'<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />')
_p(1,'<ImportGroup Label="ExtensionTargets">')
_p(1,'</ImportGroup>')
_p('</Project>')
end
function premake.vs2010_vcxproj_user(prj)
_p(xml_version_and_encoding)
_p('<Project ' ..tool_version_and_xmlns ..'>')
_p('</Project>')
end
function premake.vs2010_vcxproj_filters(prj)
vcxproj_filter_files(prj)
end

View File

@ -0,0 +1,66 @@
local vs_format_version = function()
local t =
{
vs2005 = '9.00',
vs2008 = '10.00',
vs2010 = '11.00'
}
return t[_ACTION]
end
local vs_version = function()
local t =
{
vs2005 = '2005',
vs2008 = '2008',
vs2010 = '2010'
}
return t[_ACTION]
end
local vs_write_version_info = function()
_p('Microsoft Visual Studio Solution File, Format Version %s', vs_format_version())
_p('# Visual Studio %s', vs_version() )
end
local vs_write_projects = function(sln)
-- Write out the list of project entries
for prj in premake.solution.eachproject(sln) do
-- Build a relative path from the solution file to the project file
local projpath = path.translate(path.getrelative(sln.location, _VS.projectfile(prj)), "\\")
_p('Project("{%s}") = "%s", "%s", "{%s}"', _VS.tool(prj), prj.name, projpath, prj.uuid)
local deps = premake.getdependencies(prj)
if #deps > 0 then
_p('\tProjectSection(ProjectDependencies) = postProject')
for _, dep in ipairs(deps) do
_p('\t\t{%s} = {%s}', dep.uuid, dep.uuid)
end
_p('\tEndProjectSection')
end
_p('EndProject')
end
end
local vs_write_pre_version = function(sln)
io.eol = '\r\n'
sln.vstudio_configs = premake.vstudio_buildconfigs(sln)
-- Mark the file as Unicode
_p('\239\187\191')
end
function premake.vs_generic_solution(sln)
vs_write_pre_version(sln)
vs_write_version_info()
vs_write_projects(sln)
_p('Global')
premake.vs2005_solution_platforms(sln)
premake.vs2005_solution_project_platforms(sln)
premake.vs2005_solution_properties(sln)
_p('EndGlobal')
end

View File

@ -0,0 +1,58 @@
--
-- _xcode.lua
-- Define the Apple XCode action and support functions.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
premake.xcode = { }
newaction
{
trigger = "xcode3",
shortname = "Xcode 3",
description = "Generate Apple Xcode 3 project files (experimental)",
os = "macosx",
valid_kinds = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib" },
valid_languages = { "C", "C++" },
valid_tools = {
cc = { "gcc" },
},
valid_platforms = {
Native = "Native",
x32 = "Native 32-bit",
x64 = "Native 64-bit",
Universal32 = "32-bit Universal",
Universal64 = "64-bit Universal",
Universal = "Universal",
},
default_platform = "Universal",
onsolution = function(sln)
-- Assign IDs needed for inter-project dependencies
premake.xcode.preparesolution(sln)
end,
onproject = function(prj)
premake.generate(prj, "%%.xcodeproj/project.pbxproj", premake.xcode.project)
end,
oncleanproject = function(prj)
premake.clean.directory(prj, "%%.xcodeproj")
end,
oncheckproject = function(prj)
-- Xcode can't mix target kinds within a project
local last
for cfg in premake.eachconfig(prj) do
if last and last ~= cfg.kind then
error("Project '" .. prj.name .. "' uses more than one target kind; not supported by Xcode", 0)
end
last = cfg.kind
end
end,
}

View File

@ -0,0 +1,873 @@
--
-- xcode_common.lua
-- Functions to generate the different sections of an Xcode project.
-- Copyright (c) 2009-2010 Jason Perkins and the Premake project
--
local xcode = premake.xcode
local tree = premake.tree
--
-- Return the Xcode build category for a given file, based on the file extension.
--
-- @param node
-- The node to identify.
-- @returns
-- An Xcode build category, one of "Sources", "Resources", "Frameworks", or nil.
--
function xcode.getbuildcategory(node)
local categories = {
[".a"] = "Frameworks",
[".c"] = "Sources",
[".cc"] = "Sources",
[".cpp"] = "Sources",
[".cxx"] = "Sources",
[".dylib"] = "Frameworks",
[".framework"] = "Frameworks",
[".m"] = "Sources",
[".mm"] = "Sources",
[".strings"] = "Resources",
[".nib"] = "Resources",
[".xib"] = "Resources",
[".icns"] = "Resources",
}
return categories[path.getextension(node.name)]
end
--
-- Return the displayed name for a build configuration, taking into account the
-- configuration and platform, i.e. "Debug 32-bit Universal".
--
-- @param cfg
-- The configuration being identified.
-- @returns
-- A build configuration name.
--
function xcode.getconfigname(cfg)
local name = cfg.name
if #cfg.project.solution.xcode.platforms > 1 then
name = name .. " " .. premake.action.current().valid_platforms[cfg.platform]
end
return name
end
--
-- Return the Xcode type for a given file, based on the file extension.
--
-- @param fname
-- The file name to identify.
-- @returns
-- An Xcode file type, string.
--
function xcode.getfiletype(node)
local types = {
[".c"] = "sourcecode.c.c",
[".cc"] = "sourcecode.cpp.cpp",
[".cpp"] = "sourcecode.cpp.cpp",
[".css"] = "text.css",
[".cxx"] = "sourcecode.cpp.cpp",
[".framework"] = "wrapper.framework",
[".gif"] = "image.gif",
[".h"] = "sourcecode.c.h",
[".html"] = "text.html",
[".lua"] = "sourcecode.lua",
[".m"] = "sourcecode.c.objc",
[".mm"] = "sourcecode.cpp.objc",
[".nib"] = "wrapper.nib",
[".pch"] = "sourcecode.c.h",
[".plist"] = "text.plist.xml",
[".strings"] = "text.plist.strings",
[".xib"] = "file.xib",
[".icns"] = "image.icns",
}
return types[path.getextension(node.path)] or "text"
end
--
-- Return the Xcode product type, based target kind.
--
-- @param node
-- The product node to identify.
-- @returns
-- An Xcode product type, string.
--
function xcode.getproducttype(node)
local types = {
ConsoleApp = "com.apple.product-type.tool",
WindowedApp = "com.apple.product-type.application",
StaticLib = "com.apple.product-type.library.static",
SharedLib = "com.apple.product-type.library.dynamic",
}
return types[node.cfg.kind]
end
--
-- Return the Xcode target type, based on the target file extension.
--
-- @param node
-- The product node to identify.
-- @returns
-- An Xcode target type, string.
--
function xcode.gettargettype(node)
local types = {
ConsoleApp = "\"compiled.mach-o.executable\"",
WindowedApp = "wrapper.application",
StaticLib = "archive.ar",
SharedLib = "\"compiled.mach-o.dylib\"",
}
return types[node.cfg.kind]
end
--
-- Return a unique file name for a project. Since Xcode uses .xcodeproj's to
-- represent both solutions and projects there is a likely change of a name
-- collision. Tack on a number to differentiate them.
--
-- @param prj
-- The project being queried.
-- @returns
-- A uniqued file name
--
function xcode.getxcodeprojname(prj)
-- if there is a solution with matching name, then use "projectname1.xcodeproj"
-- just get something working for now
local fname = premake.project.getfilename(prj, "%%.xcodeproj")
return fname
end
--
-- Returns true if the file name represents a framework.
--
-- @param fname
-- The name of the file to test.
--
function xcode.isframework(fname)
return (path.getextension(fname) == ".framework")
end
--
-- Retrieves a unique 12 byte ID for an object. This function accepts and ignores two
-- parameters 'node' and 'usage', which are used by an alternative implementation of
-- this function for testing.
--
-- @returns
-- A 24-character string representing the 12 byte ID.
--
function xcode.newid()
return string.format("%04X%04X%04X%04X%04X%04X",
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767),
math.random(0, 32767))
end
--
-- Create a product tree node and all projects in a solution; assigning IDs
-- that are needed for inter-project dependencies.
--
-- @param sln
-- The solution to prepare.
--
function xcode.preparesolution(sln)
-- create and cache a list of supported platforms
sln.xcode = { }
sln.xcode.platforms = premake.filterplatforms(sln, premake.action.current().valid_platforms, "Universal")
for prj in premake.solution.eachproject(sln) do
-- need a configuration to get the target information
local cfg = premake.getconfig(prj, prj.configurations[1], sln.xcode.platforms[1])
-- build the product tree node
local node = premake.tree.new(path.getname(cfg.buildtarget.bundlepath))
node.cfg = cfg
node.id = premake.xcode.newid(node, "product")
node.targetid = premake.xcode.newid(node, "target")
-- attach it to the project
prj.xcode = {}
prj.xcode.projectnode = node
end
end
--
-- Print out a list value in the Xcode format.
--
-- @param list
-- The list of values to be printed.
-- @param tag
-- The Xcode specific list tag.
--
function xcode.printlist(list, tag)
if #list > 0 then
_p(4,'%s = (', tag)
for _, item in ipairs(list) do
_p(5, '"%s",', item)
end
_p(4,');')
end
end
---------------------------------------------------------------------------
-- Section generator functions, in the same order in which they appear
-- in the .pbxproj file
---------------------------------------------------------------------------
function xcode.Header()
_p('// !$*UTF8*$!')
_p('{')
_p(1,'archiveVersion = 1;')
_p(1,'classes = {')
_p(1,'};')
_p(1,'objectVersion = 45;')
_p(1,'objects = {')
_p('')
end
function xcode.PBXBuildFile(tr)
_p('/* Begin PBXBuildFile section */')
tree.traverse(tr, {
onnode = function(node)
if node.buildid then
_p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };',
node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name)
end
end
})
_p('/* End PBXBuildFile section */')
_p('')
end
function xcode.PBXContainerItemProxy(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXContainerItemProxy section */')
for _, node in ipairs(tr.projects.children) do
_p(2,'%s /* PBXContainerItemProxy */ = {', node.productproxyid)
_p(3,'isa = PBXContainerItemProxy;')
_p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path))
_p(3,'proxyType = 2;')
_p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.id)
_p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name)
_p(2,'};')
_p(2,'%s /* PBXContainerItemProxy */ = {', node.targetproxyid)
_p(3,'isa = PBXContainerItemProxy;')
_p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path))
_p(3,'proxyType = 1;')
_p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.targetid)
_p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name)
_p(2,'};')
end
_p('/* End PBXContainerItemProxy section */')
_p('')
end
end
function xcode.PBXFileReference(tr)
_p('/* Begin PBXFileReference section */')
tree.traverse(tr, {
onleaf = function(node)
-- I'm only listing files here, so ignore anything without a path
if not node.path then
return
end
-- is this the product node, describing the output target?
if node.kind == "product" then
_p(2,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; includeInIndex = 0; name = "%s"; path = "%s"; sourceTree = BUILT_PRODUCTS_DIR; };',
node.id, node.name, xcode.gettargettype(node), node.name, path.getname(node.cfg.buildtarget.bundlepath))
-- is this a project dependency?
elseif node.parent.parent == tr.projects then
local relpath = path.getrelative(tr.project.location, node.parent.project.location)
_p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };',
node.parent.id, node.parent.name, node.parent.name, path.join(relpath, node.parent.name))
-- something else
else
local pth, src
if xcode.isframework(node.path) then
-- I need to figure out how to locate frameworks; this is just to get something working
pth = "/System/Library/Frameworks/" .. node.path
src = "absolute"
else
-- something else; probably a source code file
pth = tree.getlocalpath(node)
src = "group"
end
_p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = %s; name = "%s"; path = "%s"; sourceTree = "<%s>"; };',
node.id, node.name, xcode.getfiletype(node), node.name, pth, src)
end
end
})
_p('/* End PBXFileReference section */')
_p('')
end
function xcode.PBXFrameworksBuildPhase(tr)
_p('/* Begin PBXFrameworksBuildPhase section */')
_p(2,'%s /* Frameworks */ = {', tr.products.children[1].fxstageid)
_p(3,'isa = PBXFrameworksBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
-- write out library dependencies
tree.traverse(tr.frameworks, {
onleaf = function(node)
_p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
end
})
-- write out project dependencies
tree.traverse(tr.projects, {
onleaf = function(node)
_p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
_p('/* End PBXFrameworksBuildPhase section */')
_p('')
end
function xcode.PBXGroup(tr)
_p('/* Begin PBXGroup section */')
tree.traverse(tr, {
onnode = function(node)
-- Skip over anything that isn't a proper group
if (node.path and #node.children == 0) or node.kind == "vgroup" then
return
end
-- project references get special treatment
if node.parent == tr.projects then
_p(2,'%s /* Products */ = {', node.productgroupid)
else
_p(2,'%s /* %s */ = {', node.id, node.name)
end
_p(3,'isa = PBXGroup;')
_p(3,'children = (')
for _, childnode in ipairs(node.children) do
_p(4,'%s /* %s */,', childnode.id, childnode.name)
end
_p(3,');')
if node.parent == tr.projects then
_p(3,'name = Products;')
else
_p(3,'name = "%s";', node.name)
if node.path then
local p = node.path
if node.parent.path then
p = path.getrelative(node.parent.path, node.path)
end
_p(3,'path = %s;', p)
end
end
_p(3,'sourceTree = "<group>";')
_p(2,'};')
end
}, true)
_p('/* End PBXGroup section */')
_p('')
end
function xcode.PBXNativeTarget(tr)
_p('/* Begin PBXNativeTarget section */')
for _, node in ipairs(tr.products.children) do
local name = tr.project.name
_p(2,'%s /* %s */ = {', node.targetid, name)
_p(3,'isa = PBXNativeTarget;')
_p(3,'buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;', node.cfgsection, name)
_p(3,'buildPhases = (')
if #tr.project.prebuildcommands > 0 then
_p(4,'9607AE1010C857E500CD1376 /* Prebuild */,')
end
_p(4,'%s /* Resources */,', node.resstageid)
_p(4,'%s /* Sources */,', node.sourcesid)
if #tr.project.prelinkcommands > 0 then
_p(4,'9607AE3510C85E7E00CD1376 /* Prelink */,')
end
_p(4,'%s /* Frameworks */,', node.fxstageid)
if #tr.project.postbuildcommands > 0 then
_p(4,'9607AE3710C85E8F00CD1376 /* Postbuild */,')
end
_p(3,');')
_p(3,'buildRules = (')
_p(3,');')
_p(3,'dependencies = (')
for _, node in ipairs(tr.projects.children) do
_p(4,'%s /* PBXTargetDependency */,', node.targetdependid)
end
_p(3,');')
_p(3,'name = "%s";', name)
local p
if node.cfg.kind == "ConsoleApp" then
p = "$(HOME)/bin"
elseif node.cfg.kind == "WindowedApp" then
p = "$(HOME)/Applications"
end
if p then
_p(3,'productInstallPath = "%s";', p)
end
_p(3,'productName = "%s";', name)
_p(3,'productReference = %s /* %s */;', node.id, node.name)
_p(3,'productType = "%s";', xcode.getproducttype(node))
_p(2,'};')
end
_p('/* End PBXNativeTarget section */')
_p('')
end
function xcode.PBXProject(tr)
_p('/* Begin PBXProject section */')
_p(2,'08FB7793FE84155DC02AAC07 /* Project object */ = {')
_p(3,'isa = PBXProject;')
_p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name)
_p(3,'compatibilityVersion = "Xcode 3.1";')
_p(3,'hasScannedForEncodings = 1;')
_p(3,'mainGroup = %s /* %s */;', tr.id, tr.name)
_p(3,'projectDirPath = "";')
if #tr.projects.children > 0 then
_p(3,'projectReferences = (')
for _, node in ipairs(tr.projects.children) do
_p(4,'{')
_p(5,'ProductGroup = %s /* Products */;', node.productgroupid)
_p(5,'ProjectRef = %s /* %s */;', node.id, path.getname(node.path))
_p(4,'},')
end
_p(3,');')
end
_p(3,'projectRoot = "";')
_p(3,'targets = (')
for _, node in ipairs(tr.products.children) do
_p(4,'%s /* %s */,', node.targetid, node.name)
end
_p(3,');')
_p(2,'};')
_p('/* End PBXProject section */')
_p('')
end
function xcode.PBXReferenceProxy(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXReferenceProxy section */')
tree.traverse(tr.projects, {
onleaf = function(node)
_p(2,'%s /* %s */ = {', node.id, node.name)
_p(3,'isa = PBXReferenceProxy;')
_p(3,'fileType = %s;', xcode.gettargettype(node))
_p(3,'path = "%s";', node.path)
_p(3,'remoteRef = %s /* PBXContainerItemProxy */;', node.parent.productproxyid)
_p(3,'sourceTree = BUILT_PRODUCTS_DIR;')
_p(2,'};')
end
})
_p('/* End PBXReferenceProxy section */')
_p('')
end
end
function xcode.PBXResourcesBuildPhase(tr)
_p('/* Begin PBXResourcesBuildPhase section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Resources */ = {', target.resstageid)
_p(3,'isa = PBXResourcesBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
tree.traverse(tr, {
onnode = function(node)
if xcode.getbuildcategory(node) == "Resources" then
_p(4,'%s /* %s in Resources */,', node.buildid, node.name)
end
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
end
_p('/* End PBXResourcesBuildPhase section */')
_p('')
end
function xcode.PBXShellScriptBuildPhase(tr)
local wrapperWritten = false
local function doblock(id, name, which)
-- start with the project-level commands (most common)
local prjcmds = tr.project[which]
local commands = table.join(prjcmds, {})
-- see if there are any config-specific commands to add
for _, cfg in ipairs(tr.configs) do
local cfgcmds = cfg[which]
if #cfgcmds > #prjcmds then
table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. xcode.getconfigname(cfg) .. '" ]; then')
for i = #prjcmds + 1, #cfgcmds do
table.insert(commands, cfgcmds[i])
end
table.insert(commands, 'fi')
end
end
if #commands > 0 then
if not wrapperWritten then
_p('/* Begin PBXShellScriptBuildPhase section */')
wrapperWritten = true
end
_p(2,'%s /* %s */ = {', id, name)
_p(3,'isa = PBXShellScriptBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
_p(3,');')
_p(3,'inputPaths = (');
_p(3,');');
_p(3,'name = %s;', name);
_p(3,'outputPaths = (');
_p(3,');');
_p(3,'runOnlyForDeploymentPostprocessing = 0;');
_p(3,'shellPath = /bin/sh;');
_p(3,'shellScript = "%s";', table.concat(commands, "\\n"):gsub('"', '\\"'))
_p(2,'};')
end
end
doblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands")
doblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands")
doblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands")
if wrapperWritten then
_p('/* End PBXShellScriptBuildPhase section */')
end
end
function xcode.PBXSourcesBuildPhase(tr)
_p('/* Begin PBXSourcesBuildPhase section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Sources */ = {', target.sourcesid)
_p(3,'isa = PBXSourcesBuildPhase;')
_p(3,'buildActionMask = 2147483647;')
_p(3,'files = (')
tree.traverse(tr, {
onleaf = function(node)
if xcode.getbuildcategory(node) == "Sources" then
_p(4,'%s /* %s in Sources */,', node.buildid, node.name)
end
end
})
_p(3,');')
_p(3,'runOnlyForDeploymentPostprocessing = 0;')
_p(2,'};')
end
_p('/* End PBXSourcesBuildPhase section */')
_p('')
end
function xcode.PBXVariantGroup(tr)
_p('/* Begin PBXVariantGroup section */')
tree.traverse(tr, {
onbranch = function(node)
if node.kind == "vgroup" then
_p(2,'%s /* %s */ = {', node.id, node.name)
_p(3,'isa = PBXVariantGroup;')
_p(3,'children = (')
for _, lang in ipairs(node.children) do
_p(4,'%s /* %s */,', lang.id, lang.name)
end
_p(3,');')
_p(3,'name = %s;', node.name)
_p(3,'sourceTree = "<group>";')
_p(2,'};')
end
end
})
_p('/* End PBXVariantGroup section */')
_p('')
end
function xcode.PBXTargetDependency(tr)
if #tr.projects.children > 0 then
_p('/* Begin PBXTargetDependency section */')
tree.traverse(tr.projects, {
onleaf = function(node)
_p(2,'%s /* PBXTargetDependency */ = {', node.parent.targetdependid)
_p(3,'isa = PBXTargetDependency;')
_p(3,'name = "%s";', node.name)
_p(3,'targetProxy = %s /* PBXContainerItemProxy */;', node.parent.targetproxyid)
_p(2,'};')
end
})
_p('/* End PBXTargetDependency section */')
_p('')
end
end
function xcode.XCBuildConfiguration_Target(tr, target, cfg)
local cfgname = xcode.getconfigname(cfg)
_p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfgname)
_p(3,'isa = XCBuildConfiguration;')
_p(3,'buildSettings = {')
_p(4,'ALWAYS_SEARCH_USER_PATHS = NO;')
if not cfg.flags.Symbols then
_p(4,'DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";')
end
if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= "" then
_p(4,'EXECUTABLE_PREFIX = %s;', cfg.buildtarget.prefix)
end
local outdir = path.getdirectory(cfg.buildtarget.bundlepath)
if outdir ~= "." then
_p(4,'CONFIGURATION_BUILD_DIR = %s;', outdir)
end
_p(4,'GCC_DYNAMIC_NO_PIC = NO;')
_p(4,'GCC_MODEL_TUNING = G5;')
if tr.infoplist then
_p(4,'INFOPLIST_FILE = "%s";', tr.infoplist.path)
end
installpaths = {
ConsoleApp = '/usr/local/bin',
WindowedApp = '"$(HOME)/Applications"',
SharedLib = '/usr/local/lib',
StaticLib = '/usr/local/lib',
}
_p(4,'INSTALL_PATH = %s;', installpaths[cfg.kind])
_p(4,'PRODUCT_NAME = "%s";', cfg.buildtarget.basename)
_p(3,'};')
_p(3,'name = "%s";', cfgname)
_p(2,'};')
end
function xcode.XCBuildConfiguration_Project(tr, cfg)
local cfgname = xcode.getconfigname(cfg)
_p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfgname)
_p(3,'isa = XCBuildConfiguration;')
_p(3,'buildSettings = {')
local archs = {
Native = "$(NATIVE_ARCH_ACTUAL)",
x32 = "i386",
x64 = "x86_64",
Universal32 = "$(ARCHS_STANDARD_32_BIT)",
Universal64 = "$(ARCHS_STANDARD_64_BIT)",
Universal = "$(ARCHS_STANDARD_32_64_BIT)",
}
_p(4,'ARCHS = "%s";', archs[cfg.platform])
local targetdir = path.getdirectory(cfg.buildtarget.bundlepath)
if targetdir ~= "." then
_p(4,'CONFIGURATION_BUILD_DIR = "$(SYMROOT)";');
end
_p(4,'CONFIGURATION_TEMP_DIR = "$(OBJROOT)";')
if cfg.flags.Symbols then
_p(4,'COPY_PHASE_STRIP = NO;')
end
_p(4,'GCC_C_LANGUAGE_STANDARD = gnu99;')
if cfg.flags.NoExceptions then
_p(4,'GCC_ENABLE_CPP_EXCEPTIONS = NO;')
end
if cfg.flags.NoRTTI then
_p(4,'GCC_ENABLE_CPP_RTTI = NO;')
end
if cfg.flags.Symbols and not cfg.flags.NoEditAndContinue then
_p(4,'GCC_ENABLE_FIX_AND_CONTINUE = YES;')
end
if cfg.flags.NoExceptions then
_p(4,'GCC_ENABLE_OBJC_EXCEPTIONS = NO;')
end
if cfg.flags.Optimize or cfg.flags.OptimizeSize then
_p(4,'GCC_OPTIMIZATION_LEVEL = s;')
elseif cfg.flags.OptimizeSpeed then
_p(4,'GCC_OPTIMIZATION_LEVEL = 3;')
else
_p(4,'GCC_OPTIMIZATION_LEVEL = 0;')
end
if cfg.pchheader and not cfg.flags.NoPCH then
_p(4,'GCC_PRECOMPILE_PREFIX_HEADER = YES;')
_p(4,'GCC_PREFIX_HEADER = "%s";', cfg.pchheader)
end
xcode.printlist(cfg.defines, 'GCC_PREPROCESSOR_DEFINITIONS')
_p(4,'GCC_SYMBOLS_PRIVATE_EXTERN = NO;')
if cfg.flags.FatalWarnings then
_p(4,'GCC_TREAT_WARNINGS_AS_ERRORS = YES;')
end
_p(4,'GCC_WARN_ABOUT_RETURN_TYPE = YES;')
_p(4,'GCC_WARN_UNUSED_VARIABLE = YES;')
xcode.printlist(cfg.includedirs, 'HEADER_SEARCH_PATHS')
xcode.printlist(cfg.libdirs, 'LIBRARY_SEARCH_PATHS')
_p(4,'OBJROOT = "%s";', cfg.objectsdir)
_p(4,'ONLY_ACTIVE_ARCH = %s;',iif(premake.config.isdebugbuild(cfg),'YES','NO'))
-- build list of "other" C/C++ flags
local checks = {
["-ffast-math"] = cfg.flags.FloatFast,
["-ffloat-store"] = cfg.flags.FloatStrict,
["-fomit-frame-pointer"] = cfg.flags.NoFramePointer,
}
local flags = { }
for flag, check in pairs(checks) do
if check then
table.insert(flags, flag)
end
end
xcode.printlist(table.join(flags, cfg.buildoptions), 'OTHER_CFLAGS')
-- build list of "other" linked flags. All libraries that aren't frameworks
-- are listed here, so I don't have to try and figure out if they are ".a"
-- or ".dylib", which Xcode requires to list in the Frameworks section
flags = { }
for _, lib in ipairs(premake.getlinks(cfg, "system")) do
if not xcode.isframework(lib) then
table.insert(flags, "-l" .. lib)
end
end
flags = table.join(flags, cfg.linkoptions)
xcode.printlist(flags, 'OTHER_LDFLAGS')
_p(4,'PREBINDING = NO;')
if cfg.flags.StaticRuntime then
_p(4,'STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static;')
end
if targetdir ~= "." then
_p(4,'SYMROOT = "%s";', targetdir)
end
if cfg.flags.ExtraWarnings then
_p(4,'WARNING_CFLAGS = "-Wall";')
end
_p(3,'};')
_p(3,'name = "%s";', cfgname)
_p(2,'};')
end
function xcode.XCBuildConfiguration(tr)
_p('/* Begin XCBuildConfiguration section */')
for _, target in ipairs(tr.products.children) do
for _, cfg in ipairs(tr.configs) do
xcode.XCBuildConfiguration_Target(tr, target, cfg)
end
end
for _, cfg in ipairs(tr.configs) do
xcode.XCBuildConfiguration_Project(tr, cfg)
end
_p('/* End XCBuildConfiguration section */')
_p('')
end
function xcode.XCBuildConfigurationList(tr)
local sln = tr.project.solution
_p('/* Begin XCConfigurationList section */')
for _, target in ipairs(tr.products.children) do
_p(2,'%s /* Build configuration list for PBXNativeTarget "%s" */ = {', target.cfgsection, target.name)
_p(3,'isa = XCConfigurationList;')
_p(3,'buildConfigurations = (')
for _, cfg in ipairs(tr.configs) do
_p(4,'%s /* %s */,', cfg.xcode.targetid, xcode.getconfigname(cfg))
end
_p(3,');')
_p(3,'defaultConfigurationIsVisible = 0;')
_p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1]))
_p(2,'};')
end
_p(2,'1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */ = {', tr.name)
_p(3,'isa = XCConfigurationList;')
_p(3,'buildConfigurations = (')
for _, cfg in ipairs(tr.configs) do
_p(4,'%s /* %s */,', cfg.xcode.projectid, xcode.getconfigname(cfg))
end
_p(3,');')
_p(3,'defaultConfigurationIsVisible = 0;')
_p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1]))
_p(2,'};')
_p('/* End XCConfigurationList section */')
_p('')
end
function xcode.Footer()
_p(1,'};')
_p('\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;')
_p('}')
end

View File

@ -0,0 +1,165 @@
--
-- xcode_project.lua
-- Generate an Xcode C/C++ project.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
local xcode = premake.xcode
local tree = premake.tree
--
-- Create a tree corresponding to what is shown in the Xcode project browser
-- pane, with nodes for files and folders, resources, frameworks, and products.
--
-- @param prj
-- The project being generated.
-- @returns
-- A tree, loaded with metadata, which mirrors Xcode's view of the project.
--
function xcode.buildprjtree(prj)
local tr = premake.project.buildsourcetree(prj)
-- create a list of build configurations and assign IDs
tr.configs = {}
for _, cfgname in ipairs(prj.solution.configurations) do
for _, platform in ipairs(prj.solution.xcode.platforms) do
local cfg = premake.getconfig(prj, cfgname, platform)
cfg.xcode = {}
cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode, cfgname)
cfg.xcode.projectid = xcode.newid(tr, cfgname)
table.insert(tr.configs, cfg)
end
end
-- convert localized resources from their filesystem layout (English.lproj/MainMenu.xib)
-- to Xcode's display layout (MainMenu.xib/English).
tree.traverse(tr, {
onbranch = function(node)
if path.getextension(node.name) == ".lproj" then
local lang = path.getbasename(node.name) -- "English", "French", etc.
-- create a new language group for each file it contains
for _, filenode in ipairs(node.children) do
local grpnode = node.parent.children[filenode.name]
if not grpnode then
grpnode = tree.insert(node.parent, tree.new(filenode.name))
grpnode.kind = "vgroup"
end
-- convert the file node to a language node and add to the group
filenode.name = path.getbasename(lang)
tree.insert(grpnode, filenode)
end
-- remove this directory from the tree
tree.remove(node)
end
end
})
-- the special folder "Frameworks" lists all linked frameworks
tr.frameworks = tree.new("Frameworks")
for cfg in premake.eachconfig(prj) do
for _, link in ipairs(premake.getlinks(cfg, "system", "fullpath")) do
local name = path.getname(link)
if xcode.isframework(name) and not tr.frameworks.children[name] then
node = tree.insert(tr.frameworks, tree.new(name))
node.path = link
end
end
end
-- only add it to the tree if there are frameworks to link
if #tr.frameworks.children > 0 then
tree.insert(tr, tr.frameworks)
end
-- the special folder "Products" holds the target produced by the project; this
-- is populated below
tr.products = tree.insert(tr, tree.new("Products"))
-- the special folder "Projects" lists sibling project dependencies
tr.projects = tree.new("Projects")
for _, dep in ipairs(premake.getdependencies(prj, "sibling", "object")) do
-- create a child node for the dependency's xcodeproj
local xcpath = xcode.getxcodeprojname(dep)
local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
xcnode.path = xcpath
xcnode.project = dep
xcnode.productgroupid = xcode.newid(xcnode, "prodgrp")
xcnode.productproxyid = xcode.newid(xcnode, "prodprox")
xcnode.targetproxyid = xcode.newid(xcnode, "targprox")
xcnode.targetdependid = xcode.newid(xcnode, "targdep")
-- create a grandchild node for the dependency's link target
local cfg = premake.getconfig(dep, prj.configurations[1])
node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
node.path = cfg.linktarget.fullpath
node.cfg = cfg
end
if #tr.projects.children > 0 then
tree.insert(tr, tr.projects)
end
-- Final setup
tree.traverse(tr, {
onnode = function(node)
-- assign IDs to every node in the tree
node.id = xcode.newid(node)
-- assign build IDs to buildable files
if xcode.getbuildcategory(node) then
node.buildid = xcode.newid(node, "build")
end
-- remember key files that are needed elsewhere
if string.endswith(node.name, "Info.plist") then
tr.infoplist = node
end
end
}, true)
-- Plug in the product node into the Products folder in the tree. The node
-- was built in xcode.preparesolution() in xcode_common.lua; it contains IDs
-- that are necessary for inter-project dependencies
node = tree.insert(tr.products, prj.xcode.projectnode)
node.kind = "product"
node.path = node.cfg.buildtarget.fullpath
node.cfgsection = xcode.newid(node, "cfg")
node.resstageid = xcode.newid(node, "rez")
node.sourcesid = xcode.newid(node, "src")
node.fxstageid = xcode.newid(node, "fxs")
return tr
end
--
-- Generate an Xcode .xcodeproj for a Premake project.
--
-- @param prj
-- The Premake project to generate.
--
function premake.xcode.project(prj)
local tr = xcode.buildprjtree(prj)
xcode.Header(tr)
xcode.PBXBuildFile(tr)
xcode.PBXContainerItemProxy(tr)
xcode.PBXFileReference(tr)
xcode.PBXFrameworksBuildPhase(tr)
xcode.PBXGroup(tr)
xcode.PBXNativeTarget(tr)
xcode.PBXProject(tr)
xcode.PBXReferenceProxy(tr)
xcode.PBXResourcesBuildPhase(tr)
xcode.PBXShellScriptBuildPhase(tr)
xcode.PBXSourcesBuildPhase(tr)
xcode.PBXVariantGroup(tr)
xcode.PBXTargetDependency(tr)
xcode.XCBuildConfiguration(tr)
xcode.XCBuildConfigurationList(tr)
xcode.Footer(tr)
end

View File

@ -0,0 +1,159 @@
--
-- action.lua
-- Work with the list of registered actions.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.action = { }
--
-- The list of registered actions.
--
premake.action.list = { }
--
-- Register a new action.
--
-- @param a
-- The new action object.
--
function premake.action.add(a)
-- validate the action object, at least a little bit
local missing
for _, field in ipairs({"description", "trigger"}) do
if (not a[field]) then
missing = field
end
end
if (missing) then
error("action needs a " .. missing, 3)
end
-- add it to the master list
premake.action.list[a.trigger] = a
end
--
-- Trigger an action.
--
-- @param name
-- The name of the action to be triggered.
-- @returns
-- None.
--
function premake.action.call(name)
local a = premake.action.list[name]
for sln in premake.solution.each() do
if a.onsolution then
a.onsolution(sln)
end
for prj in premake.solution.eachproject(sln) do
if a.onproject then
a.onproject(prj)
end
end
end
if a.execute then
a.execute()
end
end
--
-- Retrieve the current action, as determined by _ACTION.
--
-- @return
-- The current action, or nil if _ACTION is nil or does not match any action.
--
function premake.action.current()
return premake.action.get(_ACTION)
end
--
-- Retrieve an action by name.
--
-- @param name
-- The name of the action to retrieve.
-- @returns
-- The requested action, or nil if the action does not exist.
--
function premake.action.get(name)
return premake.action.list[name]
end
--
-- Iterator for the list of actions.
--
function premake.action.each()
-- sort the list by trigger
local keys = { }
for _, action in pairs(premake.action.list) do
table.insert(keys, action.trigger)
end
table.sort(keys)
local i = 0
return function()
i = i + 1
return premake.action.list[keys[i]]
end
end
--
-- Activates a particular action.
--
-- @param name
-- The name of the action to activate.
--
function premake.action.set(name)
_ACTION = name
-- Some actions imply a particular operating system
local action = premake.action.get(name)
if action then
_OS = action.os or _OS
end
end
--
-- Determines if an action supports a particular language or target type.
--
-- @param action
-- The action to test.
-- @param feature
-- The feature to check, either a programming language or a target type.
-- @returns
-- True if the feature is supported, false otherwise.
--
function premake.action.supports(action, feature)
if not action then
return false
end
if action.valid_languages then
if table.contains(action.valid_languages, feature) then
return true
end
end
if action.valid_kinds then
if table.contains(action.valid_kinds, feature) then
return true
end
end
return false
end

View File

@ -0,0 +1,690 @@
--
-- api.lua
-- Implementation of the solution, project, and configuration APIs.
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
--
--
-- Here I define all of the getter/setter functions as metadata. The actual
-- functions are built programmatically below.
--
premake.fields =
{
basedir =
{
kind = "path",
scope = "container",
},
buildaction =
{
kind = "string",
scope = "config",
allowed = {
"Compile",
"Copy",
"Embed",
"None"
}
},
buildoptions =
{
kind = "list",
scope = "config",
},
configurations =
{
kind = "list",
scope = "solution",
},
defines =
{
kind = "list",
scope = "config",
},
deploymentoptions =
{
kind = "list",
scope = "config",
},
excludes =
{
kind = "filelist",
scope = "config",
},
files =
{
kind = "filelist",
scope = "config",
},
flags =
{
kind = "list",
scope = "config",
isflags = true,
allowed = {
"EnableSSE",
"EnableSSE2",
"ExtraWarnings",
"FatalWarnings",
"FloatFast",
"FloatStrict",
"Managed",
"MFC",
"NativeWChar",
"No64BitChecks",
"NoEditAndContinue",
"NoExceptions",
"NoFramePointer",
"NoImportLib",
"NoManifest",
"NoMinimalRebuild",
"NoNativeWChar",
"NoPCH",
"NoRTTI",
"Optimize",
"OptimizeSize",
"OptimizeSpeed",
"SEH",
"StaticRuntime",
"Symbols",
"Unicode",
"Unsafe",
"WinMain"
}
},
framework =
{
kind = "string",
scope = "container",
allowed = {
"1.0",
"1.1",
"2.0",
"3.0",
"3.5",
"4.0"
}
},
imagepath =
{
kind = "path",
scope = "config",
},
imageoptions =
{
kind = "list",
scope = "config",
},
implibdir =
{
kind = "path",
scope = "config",
},
implibextension =
{
kind = "string",
scope = "config",
},
implibname =
{
kind = "string",
scope = "config",
},
implibprefix =
{
kind = "string",
scope = "config",
},
implibsuffix =
{
kind = "string",
scope = "config",
},
includedirs =
{
kind = "dirlist",
scope = "config",
},
kind =
{
kind = "string",
scope = "config",
allowed = {
"ConsoleApp",
"WindowedApp",
"StaticLib",
"SharedLib"
}
},
language =
{
kind = "string",
scope = "container",
allowed = {
"C",
"C++",
"C#"
}
},
libdirs =
{
kind = "dirlist",
scope = "config",
},
linkoptions =
{
kind = "list",
scope = "config",
},
links =
{
kind = "list",
scope = "config",
allowed = function(value)
-- if library name contains a '/' then treat it as a path to a local file
if value:find('/', nil, true) then
value = path.getabsolute(value)
end
return value
end
},
location =
{
kind = "path",
scope = "container",
},
objdir =
{
kind = "path",
scope = "config",
},
pchheader =
{
kind = "string",
scope = "config",
},
pchsource =
{
kind = "path",
scope = "config",
},
platforms =
{
kind = "list",
scope = "solution",
allowed = table.keys(premake.platforms),
},
postbuildcommands =
{
kind = "list",
scope = "config",
},
prebuildcommands =
{
kind = "list",
scope = "config",
},
prelinkcommands =
{
kind = "list",
scope = "config",
},
resdefines =
{
kind = "list",
scope = "config",
},
resincludedirs =
{
kind = "dirlist",
scope = "config",
},
resoptions =
{
kind = "list",
scope = "config",
},
targetdir =
{
kind = "path",
scope = "config",
},
targetextension =
{
kind = "string",
scope = "config",
},
targetname =
{
kind = "string",
scope = "config",
},
targetprefix =
{
kind = "string",
scope = "config",
},
targetsuffix =
{
kind = "string",
scope = "config",
},
trimpaths =
{
kind = "dirlist",
scope = "config",
},
uuid =
{
kind = "string",
scope = "container",
allowed = function(value)
local ok = true
if (#value ~= 36) then ok = false end
for i=1,36 do
local ch = value:sub(i,i)
if (not ch:find("[ABCDEFabcdef0123456789-]")) then ok = false end
end
if (value:sub(9,9) ~= "-") then ok = false end
if (value:sub(14,14) ~= "-") then ok = false end
if (value:sub(19,19) ~= "-") then ok = false end
if (value:sub(24,24) ~= "-") then ok = false end
if (not ok) then
return nil, "invalid UUID"
end
return value:upper()
end
},
}
--
-- End of metadata
--
--
-- Check to see if a value exists in a list of values, using a
-- case-insensitive match. If the value does exist, the canonical
-- version contained in the list is returned, so future tests can
-- use case-sensitive comparisions.
--
function premake.checkvalue(value, allowed)
if (allowed) then
if (type(allowed) == "function") then
return allowed(value)
else
for _,v in ipairs(allowed) do
if (value:lower() == v:lower()) then
return v
end
end
return nil, "invalid value '" .. value .. "'"
end
else
return value
end
end
--
-- Retrieve the current object of a particular type from the session. The
-- type may be "solution", "container" (the last activated solution or
-- project), or "config" (the last activated configuration). Returns the
-- requested container, or nil and an error message.
--
function premake.getobject(t)
local container
if (t == "container" or t == "solution") then
container = premake.CurrentContainer
else
container = premake.CurrentConfiguration
end
if t == "solution" then
if type(container) == "project" then
container = container.solution
end
if type(container) ~= "solution" then
container = nil
end
end
local msg
if (not container) then
if (t == "container") then
msg = "no active solution or project"
elseif (t == "solution") then
msg = "no active solution"
else
msg = "no active solution, project, or configuration"
end
end
return container, msg
end
--
-- Adds values to an array field of a solution/project/configuration. `ctype`
-- specifies the container type (see premake.getobject) for the field.
--
function premake.setarray(ctype, fieldname, value, allowed)
local container, err = premake.getobject(ctype)
if (not container) then
error(err, 4)
end
if (not container[fieldname]) then
container[fieldname] = { }
end
local function doinsert(value, depth)
if (type(value) == "table") then
for _,v in ipairs(value) do
doinsert(v, depth + 1)
end
else
value, err = premake.checkvalue(value, allowed)
if (not value) then
error(err, depth)
end
table.insert(container[fieldname], value)
end
end
if (value) then
doinsert(value, 5)
end
return container[fieldname]
end
--
-- Adds values to an array-of-directories field of a solution/project/configuration.
-- `ctype` specifies the container type (see premake.getobject) for the field. All
-- values are converted to absolute paths before being stored.
--
local function domatchedarray(ctype, fieldname, value, matchfunc)
local result = { }
function makeabsolute(value, depth)
if (type(value) == "table") then
for _, item in ipairs(value) do
makeabsolute(item, depth + 1)
end
elseif type(value) == "string" then
if value:find("*") then
makeabsolute(matchfunc(value), depth + 1)
else
table.insert(result, path.getabsolute(value))
end
else
error("Invalid value in list: expected string, got " .. type(value), depth)
end
end
makeabsolute(value, 3)
return premake.setarray(ctype, fieldname, result)
end
function premake.setdirarray(ctype, fieldname, value)
return domatchedarray(ctype, fieldname, value, os.matchdirs)
end
function premake.setfilearray(ctype, fieldname, value)
return domatchedarray(ctype, fieldname, value, os.matchfiles)
end
--
-- Set a new value for a string field of a solution/project/configuration. `ctype`
-- specifies the container type (see premake.getobject) for the field.
--
function premake.setstring(ctype, fieldname, value, allowed)
-- find the container for this value
local container, err = premake.getobject(ctype)
if (not container) then
error(err, 4)
end
-- if a value was provided, set it
if (value) then
value, err = premake.checkvalue(value, allowed)
if (not value) then
error(err, 4)
end
container[fieldname] = value
end
return container[fieldname]
end
--
-- The getter/setter implemention.
--
local function accessor(name, value)
local kind = premake.fields[name].kind
local scope = premake.fields[name].scope
local allowed = premake.fields[name].allowed
if ((kind == "string" or kind == "path") and value) then
if type(value) ~= "string" then
error("string value expected", 3)
end
end
if (kind == "string") then
return premake.setstring(scope, name, value, allowed)
elseif (kind == "path") then
if value then value = path.getabsolute(value) end
return premake.setstring(scope, name, value)
elseif (kind == "list") then
return premake.setarray(scope, name, value, allowed)
elseif (kind == "dirlist") then
return premake.setdirarray(scope, name, value)
elseif (kind == "filelist") then
return premake.setfilearray(scope, name, value)
end
end
--
-- Build all of the getter/setter functions from the metadata above.
--
for name,_ in pairs(premake.fields) do
_G[name] = function(value)
return accessor(name, value)
end
end
--
-- Project object constructors.
--
function configuration(terms)
if not terms then
return premake.CurrentConfiguration
end
local container, err = premake.getobject("container")
if (not container) then
error(err, 2)
end
local cfg = { }
cfg.terms = table.flatten({terms})
table.insert(container.blocks, cfg)
premake.CurrentConfiguration = cfg
-- create a keyword list using just the indexed keyword items. This is a little
-- confusing: "terms" are what the user specifies in the script, "keywords" are
-- the Lua patterns that result. I'll refactor to better names.
cfg.keywords = { }
for _, word in ipairs(cfg.terms) do
table.insert(cfg.keywords, path.wildcards(word):lower())
end
-- initialize list-type fields to empty tables
for name, field in pairs(premake.fields) do
if (field.kind ~= "string" and field.kind ~= "path") then
cfg[name] = { }
end
end
return cfg
end
function project(name)
if not name then
return iif(type(premake.CurrentContainer) == "project", premake.CurrentContainer, nil)
end
-- identify the parent solution
local sln
if (type(premake.CurrentContainer) == "project") then
sln = premake.CurrentContainer.solution
else
sln = premake.CurrentContainer
end
if (type(sln) ~= "solution") then
error("no active solution", 2)
end
-- if this is a new project, create it
premake.CurrentContainer = sln.projects[name]
if (not premake.CurrentContainer) then
local prj = { }
premake.CurrentContainer = prj
-- add to master list keyed by both name and index
table.insert(sln.projects, prj)
sln.projects[name] = prj
-- attach a type
setmetatable(prj, {
__type = "project",
})
prj.solution = sln
prj.name = name
prj.basedir = os.getcwd()
prj.uuid = os.uuid()
prj.blocks = { }
end
-- add an empty, global configuration to the project
configuration { }
return premake.CurrentContainer
end
function solution(name)
if not name then
if type(premake.CurrentContainer) == "project" then
return premake.CurrentContainer.solution
else
return premake.CurrentContainer
end
end
premake.CurrentContainer = premake.solution.get(name)
if (not premake.CurrentContainer) then
premake.CurrentContainer = premake.solution.new(name)
end
-- add an empty, global configuration
configuration { }
return premake.CurrentContainer
end
--
-- Define a new action.
--
-- @param a
-- The new action object.
--
function newaction(a)
premake.action.add(a)
end
--
-- Define a new option.
--
-- @param opt
-- The new option object.
--
function newoption(opt)
premake.option.add(opt)
end

View File

@ -0,0 +1,90 @@
--
-- cmdline.lua
-- Functions to define and handle command line actions and options.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
--
-- Built-in command line options
--
newoption
{
trigger = "cc",
value = "VALUE",
description = "Choose a C/C++ compiler set",
allowed = {
{ "gcc", "GNU GCC (gcc/g++)" },
{ "ow", "OpenWatcom" },
}
}
newoption
{
trigger = "dotnet",
value = "VALUE",
description = "Choose a .NET compiler set",
allowed = {
{ "msnet", "Microsoft .NET (csc)" },
{ "mono", "Novell Mono (mcs)" },
{ "pnet", "Portable.NET (cscc)" },
}
}
newoption
{
trigger = "file",
value = "FILE",
description = "Read FILE as a Premake script; default is 'premake4.lua'"
}
newoption
{
trigger = "help",
description = "Display this information"
}
newoption
{
trigger = "os",
value = "VALUE",
description = "Generate files for a different operating system",
allowed = {
{ "bsd", "OpenBSD, NetBSD, or FreeBSD" },
{ "linux", "Linux" },
{ "macosx", "Apple Mac OS X" },
{ "solaris", "Solaris" },
{ "windows", "Microsoft Windows" },
}
}
newoption
{
trigger = "platform",
value = "VALUE",
description = "Add target architecture (if supported by action)",
allowed = {
{ "x32", "32-bit" },
{ "x64", "64-bit" },
{ "universal", "Mac OS X Universal, 32- and 64-bit" },
{ "universal32", "Mac OS X Universal, 32-bit only" },
{ "universal64", "Mac OS X Universal, 64-bit only" },
{ "ps3", "Playstation 3 (experimental)" },
{ "xbox360", "Xbox 360 (experimental)" },
}
}
newoption
{
trigger = "scripts",
value = "path",
description = "Search for additional scripts on the given path"
}
newoption
{
trigger = "version",
description = "Display version information"
}

View File

@ -0,0 +1,502 @@
--
-- configs.lua
--
-- Functions for working with configuration objects (which can include
-- projects and solutions).
--
-- This script also contains the configuration "baking" logic (though I
-- would like to eventually move this out to a different file):
-- Once the project scripts have been run, flatten all of the configuration
-- data down into simpler objects, keeping only the settings that apply to
-- the current runtime environment.
--
-- Copyright (c) 2008-2010 Jason Perkins and the Premake project
--
premake.config = { }
--
-- Determine if a configuration represents a "debug" or "release" build.
-- This controls the runtime library selected for Visual Studio builds
-- (and might also be useful elsewhere).
--
-- @param cfg
-- The configuration object to test.
-- @returns
-- True if the configuration represents a debug build; false otherwise.
--
function premake.config.isdebugbuild(cfg)
-- If any of the optimize flags are set, it's a release a build
if cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed then
return false
end
-- If symbols are not defined, it's a release build
if not cfg.flags.Symbols then
return false
end
return true
end
-------------------------------------------------------------------------
-- Configuration Baking Logic
-------------------------------------------------------------------------
-- do not copy these fields into the configurations
local nocopy =
{
blocks = true,
keywords = true,
projects = true,
__configs = true,
}
-- leave these paths as absolute, rather than converting to project relative
local nofixup =
{
basedir = true,
location = true,
}
--
-- Returns a list of all of the active terms from the current environment.
-- See the docs for configuration() for more information about the terms.
--
function premake.getactiveterms()
local terms = { _ACTION:lower(), os.get() }
-- add option keys or values
for key, value in pairs(_OPTIONS) do
if value ~= "" then
table.insert(terms, value:lower())
else
table.insert(terms, key:lower())
end
end
return terms
end
--
-- Test a single configuration block keyword against a list of terms.
-- The terms are a mix of key/value pairs. The keyword is tested against
-- the values; on a match, the corresponding key is returned. This
-- enables testing for required values in iskeywordsmatch(), below.
--
function premake.iskeywordmatch(keyword, terms)
-- is it negated?
if keyword:startswith("not ") then
return not premake.iskeywordmatch(keyword:sub(5), terms)
end
for _, pattern in ipairs(keyword:explode(" or ")) do
-- local pattern = "^" .. word .. "$"
for termkey, term in pairs(terms) do
if term:match(pattern) == term then
return termkey
end
end
end
end
--
-- Checks a set of configuration block keywords against a list of terms.
-- I've already forgotten the purpose of the required terms (d'oh!) but
-- I'll see if I can figure it out on a future refactoring.
--
function premake.iskeywordsmatch(keywords, terms)
local hasrequired = false
for _, keyword in ipairs(keywords) do
local matched = premake.iskeywordmatch(keyword, terms)
if not matched then
return false
end
if matched == "required" then
hasrequired = true
end
end
if terms.required and not hasrequired then
return false
else
return true
end
end
--
-- Converts path fields from absolute to location-relative paths.
--
-- @param location
-- The base location, paths will be relative to this directory.
-- @param obj
-- The object containing the fields to be adjusted.
--
local function adjustpaths(location, obj)
for name, value in pairs(obj) do
local field = premake.fields[name]
if field and value and not nofixup[name] then
if field.kind == "path" then
obj[name] = path.getrelative(location, value)
elseif field.kind == "dirlist" or field.kind == "filelist" then
for i, p in ipairs(value) do
value[i] = path.getrelative(location, p)
end
end
end
end
end
--
-- Merge all of the fields from one object into another. String values are overwritten,
-- while list values are merged. Fields listed in premake.nocopy are skipped.
--
-- @param dest
-- The destination object, to contain the merged settings.
-- @param src
-- The source object, containing the settings to added to the destination.
--
local function mergeobject(dest, src)
if not src then return end
for field, value in pairs(src) do
if not nocopy[field] then
if type(value) == "table" then
-- merge two lists, removing any duplicates along the way
local tbl = dest[field] or { }
for _, item in ipairs(value) do
if not tbl[item] then
table.insert(tbl, item)
tbl[item] = item
end
end
dest[field] = tbl
else
dest[field] = value
end
end
end
end
--
-- Merges the settings from a solution's or project's list of configuration blocks,
-- for all blocks that match the provided set of environment terms.
--
-- @param dest
-- The destination object, to contain the merged settings.
-- @param obj
-- The solution or project object being collapsed.
-- @param basis
-- "Root" level settings, from the solution, which act as a starting point for
-- all of the collapsed settings built during this call.
-- @param terms
-- A list of keywords to filter the configuration blocks; only those that
-- match will be included in the destination.
-- @param cfgname
-- The name of the configuration being collapsed. May be nil.
-- @param pltname
-- The name of the platform being collapsed. May be nil.
--
local function merge(dest, obj, basis, terms, cfgname, pltname)
-- the configuration key is the merged configuration and platform names
local key = cfgname or ""
pltname = pltname or "Native"
if pltname ~= "Native" then
key = key .. pltname
end
-- add the configuration and platform to the block filter terms
terms.config = (cfgname or ""):lower()
terms.platform = pltname:lower()
-- build the configuration base by merging the solution and project level settings
local cfg = {}
mergeobject(cfg, basis[key])
adjustpaths(obj.location, cfg)
mergeobject(cfg, obj)
-- add `kind` to the filter terms
if (cfg.kind) then
terms.kind = cfg.kind:lower()
end
-- now add in any blocks that match the filter terms
for _, blk in ipairs(obj.blocks) do
if (premake.iskeywordsmatch(blk.keywords, terms)) then
mergeobject(cfg, blk)
end
end
-- package it all up and add it to the result set
cfg.name = cfgname
cfg.platform = pltname
cfg.terms = terms
dest[key] = cfg
end
--
-- Collapse a solution or project object down to a canonical set of configuration settings,
-- keyed by configuration block/platform pairs, and taking into account the current
-- environment settings.
--
-- @param obj
-- The solution or project to be collapsed.
-- @param basis
-- "Root" level settings, from the solution, which act as a starting point for
-- all of the collapsed settings built during this call.
-- @returns
-- The collapsed list of settings, keyed by configuration block/platform pair.
--
local function collapse(obj, basis)
local result = {}
basis = basis or {}
-- find the solution, which contains the configuration and platform lists
local sln = obj.solution or obj
-- build a set of configuration filter terms; only those configuration blocks
-- with a matching set of keywords will be included in the merged results
local terms = premake.getactiveterms()
-- build a project-level configuration. If a target kind is set at this level
-- then include it into the filter terms
merge(result, obj, basis, terms)
-- if result[""].kind then
-- terms.kind = result[""].kind:lower()
-- end
-- now build configurations for each build config/platform pair
for _, cfgname in ipairs(sln.configurations) do
merge(result, obj, basis, terms, cfgname, "Native")
for _, pltname in ipairs(sln.platforms or {}) do
if pltname ~= "Native" then
merge(result, obj, basis, terms, cfgname, pltname)
end
end
end
return result
end
--
-- Post-process a project configuration, applying path fix-ups and other adjustments
-- to the "raw" setting data pulled from the project script.
--
-- @param prj
-- The project object which contains the configuration.
-- @param cfg
-- The configuration object to be fixed up.
--
local function postprocess(prj, cfg)
cfg.project = prj
cfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true)
cfg.longname = premake.getconfigname(cfg.name, cfg.platform)
-- set the project location, if not already set
cfg.location = cfg.location or cfg.basedir
-- figure out the target system
local platform = premake.platforms[cfg.platform]
if platform.iscrosscompiler then
cfg.system = cfg.platform
else
cfg.system = os.get()
end
-- adjust the kind as required by the target system
if cfg.kind == "SharedLib" and platform.nosharedlibs then
cfg.kind = "StaticLib"
end
-- remove excluded files from the file list
local files = { }
for _, fname in ipairs(cfg.files) do
local excluded = false
for _, exclude in ipairs(cfg.excludes) do
excluded = (fname == exclude)
if (excluded) then break end
end
if (not excluded) then
table.insert(files, fname)
end
end
cfg.files = files
-- fixup the data
for name, field in pairs(premake.fields) do
-- re-key flag fields for faster lookups
if field.isflags then
local values = cfg[name]
for _, flag in ipairs(values) do values[flag] = true end
end
end
-- build configuration objects for all files
cfg.__fileconfigs = { }
for _, fname in ipairs(cfg.files) do
cfg.terms.required = fname:lower()
local fcfg = {}
for _, blk in ipairs(cfg.project.blocks) do
if (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then
mergeobject(fcfg, blk)
end
end
-- add indexed by name and integer
fcfg.name = fname
cfg.__fileconfigs[fname] = fcfg
table.insert(cfg.__fileconfigs, fcfg)
end
end
--
-- Computes a unique objects directory for every configuration, using the
-- following choices:
-- [1] -> the objects directory as set in the project of config
-- [2] -> [1] + the platform name
-- [3] -> [2] + the configuration name
-- [4] -> [3] + the project name
--
local function builduniquedirs()
local num_variations = 4
-- Start by listing out each possible object directory for each configuration.
-- Keep a count of how many times each path gets used across the session.
local cfg_dirs = {}
local hit_counts = {}
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
local dirs = { }
dirs[1] = path.getabsolute(path.join(cfg.location, cfg.objdir or cfg.project.objdir or "obj"))
dirs[2] = path.join(dirs[1], iif(cfg.platform == "Native", "", cfg.platform))
dirs[3] = path.join(dirs[2], cfg.name)
dirs[4] = path.join(dirs[3], cfg.project.name)
cfg_dirs[cfg] = dirs
-- configurations other than the root should bias toward a more
-- description path, including the platform or config name
local start = iif(cfg.name, 2, 1)
for v = start, num_variations do
local d = dirs[v]
hit_counts[d] = (hit_counts[d] or 0) + 1
end
end
end
end
-- Now assign an object directory to each configuration, skipping those
-- that are in use somewhere else in the session
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
local dir
local start = iif(cfg.name, 2, 1)
for v = start, num_variations do
dir = cfg_dirs[cfg][v]
if hit_counts[dir] == 1 then break end
end
cfg.objectsdir = path.getrelative(cfg.location, dir)
end
end
end
end
--
-- Pre-computes the build and link targets for a configuration.
--
local function buildtargets()
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
for _, cfg in pairs(prj.__configs) do
-- determine which conventions the target should follow for this config
local pathstyle = premake.getpathstyle(cfg)
local namestyle = premake.getnamestyle(cfg)
-- build the targets
cfg.buildtarget = premake.gettarget(cfg, "build", pathstyle, namestyle, cfg.system)
cfg.linktarget = premake.gettarget(cfg, "link", pathstyle, namestyle, cfg.system)
if pathstyle == "windows" then
cfg.objectsdir = path.translate(cfg.objectsdir, "\\")
end
end
end
end
end
--
-- Takes the configuration information stored in solution->project->block
-- hierarchy and flattens it all down into one object per configuration.
-- These objects are cached with the project, and can be retrieved by
-- calling the getconfig() or the eachconfig() iterator function.
--
function premake.buildconfigs()
-- convert project path fields to be relative to project location
for sln in premake.solution.each() do
for _, prj in ipairs(sln.projects) do
prj.location = prj.location or sln.location or prj.basedir
adjustpaths(prj.location, prj)
for _, blk in ipairs(prj.blocks) do
adjustpaths(prj.location, blk)
end
end
sln.location = sln.location or sln.basedir
end
-- collapse configuration blocks, so that there is only one block per build
-- configuration/platform pair, filtered to the current operating environment
for sln in premake.solution.each() do
local basis = collapse(sln)
for _, prj in ipairs(sln.projects) do
prj.__configs = collapse(prj, basis)
for _, cfg in pairs(prj.__configs) do
postprocess(prj, cfg)
end
end
end
-- assign unique object directories to each configuration
builduniquedirs()
-- walk it again and build the targets and unique directories
buildtargets(cfg)
end

View File

@ -0,0 +1,145 @@
--
-- globals.lua
-- Global tables and variables, replacements and extensions to Lua's global functions.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
-- A top-level namespace for support functions
premake = { }
-- The list of supported platforms; also update list in cmdline.lua
premake.platforms =
{
Native =
{
cfgsuffix = "",
},
x32 =
{
cfgsuffix = "32",
},
x64 =
{
cfgsuffix = "64",
},
Universal =
{
cfgsuffix = "univ",
},
Universal32 =
{
cfgsuffix = "univ32",
},
Universal64 =
{
cfgsuffix = "univ64",
},
PS3 =
{
cfgsuffix = "ps3",
iscrosscompiler = true,
nosharedlibs = true,
namestyle = "PS3",
},
Xbox360 =
{
cfgsuffix = "xbox360",
iscrosscompiler = true,
namestyle = "windows",
},
}
--
-- A replacement for Lua's built-in dofile() function, this one sets the
-- current working directory to the script's location, enabling script-relative
-- referencing of other files and resources.
--
local builtin_dofile = dofile
function dofile(fname)
-- remember the current working directory and file; I'll restore it shortly
local oldcwd = os.getcwd()
local oldfile = _SCRIPT
-- if the file doesn't exist, check the search path
if (not os.isfile(fname)) then
local path = os.pathsearch(fname, _OPTIONS["scripts"], os.getenv("PREMAKE_PATH"))
if (path) then
fname = path.."/"..fname
end
end
-- use the absolute path to the script file, to avoid any file name
-- ambiguity if an error should arise
_SCRIPT = path.getabsolute(fname)
-- switch the working directory to the new script location
local newcwd = path.getdirectory(_SCRIPT)
os.chdir(newcwd)
-- run the chunk. How can I catch variable return values?
local a, b, c, d, e, f = builtin_dofile(_SCRIPT)
-- restore the previous working directory when done
_SCRIPT = oldfile
os.chdir(oldcwd)
return a, b, c, d, e, f
end
--
-- "Immediate If" - returns one of the two values depending on the value of expr.
--
function iif(expr, trueval, falseval)
if (expr) then
return trueval
else
return falseval
end
end
--
-- A shortcut for including another "premake4.lua" file, often used for projects.
--
function include(fname)
return dofile(fname .. "/premake4.lua")
end
--
-- A shortcut for printing formatted output.
--
function printf(msg, ...)
print(string.format(msg, unpack(arg)))
end
--
-- An extension to type() to identify project object types by reading the
-- "__type" field from the metatable.
--
local builtin_type = type
function type(t)
local mt = getmetatable(t)
if (mt) then
if (mt.__type) then
return mt.__type
end
end
return builtin_type(t)
end

View File

@ -0,0 +1,51 @@
--
-- help.lua
-- User help, displayed on /help option.
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
--
function premake.showhelp()
-- display the basic usage
printf("Premake %s, a build script generator", _PREMAKE_VERSION)
printf(_PREMAKE_COPYRIGHT)
printf("%s %s", _VERSION, _COPYRIGHT)
printf("")
printf("Usage: premake4 [options] action [arguments]")
printf("")
-- display all options
printf("OPTIONS")
printf("")
for option in premake.option.each() do
local trigger = option.trigger
local description = option.description
if (option.value) then trigger = trigger .. "=" .. option.value end
if (option.allowed) then description = description .. "; one of:" end
printf(" --%-15s %s", trigger, description)
if (option.allowed) then
for _, value in ipairs(option.allowed) do
printf(" %-14s %s", value[1], value[2])
end
end
printf("")
end
-- display all actions
printf("ACTIONS")
printf("")
for action in premake.action.each() do
printf(" %-17s %s", action.trigger, action.description)
end
printf("")
-- see more
printf("For additional information, see http://industriousone.com/premake")
end

View File

@ -0,0 +1,81 @@
--
-- io.lua
-- Additions to the I/O namespace.
-- Copyright (c) 2008-2009 Jason Perkins and the Premake project
--
--
-- Prepare to capture the output from all subsequent calls to io.printf(),
-- used for automated testing of the generators.
--
function io.capture()
io.captured = ''
end
--
-- Returns the captured text and stops capturing.
--
function io.endcapture()
local captured = io.captured
io.captured = nil
return captured
end
--
-- Open an overload of the io.open() function, which will create any missing
-- subdirectories in the filename if "mode" is set to writeable.
--
local builtin_open = io.open
function io.open(fname, mode)
if (mode) then
if (mode:find("w")) then
local dir = path.getdirectory(fname)
ok, err = os.mkdir(dir)
if (not ok) then
error(err, 0)
end
end
end
return builtin_open(fname, mode)
end
--
-- A shortcut for printing formatted output to an output stream.
--
function io.printf(msg, ...)
if (not io.eol) then
io.eol = "\n"
end
local s
if type(msg) == "number" then
s = string.rep("\t", msg) .. string.format(unpack(arg))
else
s = string.format(msg, unpack(arg))
end
if io.captured then
io.captured = io.captured .. s .. io.eol
else
io.write(s)
io.write(io.eol)
end
end
--
-- Because I use io.printf() so often in the generators, create a terse shortcut
-- for it. This saves me typing, and also reduces the size of the executable.
--
_p = io.printf

View File

@ -0,0 +1,107 @@
--
-- option.lua
-- Work with the list of registered options.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.option = { }
--
-- The list of registered options.
--
premake.option.list = { }
--
-- Register a new option.
--
-- @param opt
-- The new option object.
--
function premake.option.add(opt)
-- some sanity checking
local missing
for _, field in ipairs({ "description", "trigger" }) do
if (not opt[field]) then
missing = field
end
end
if (missing) then
error("option needs a " .. missing, 3)
end
-- add it to the master list
premake.option.list[opt.trigger] = opt
end
--
-- Retrieve an option by name.
--
-- @param name
-- The name of the option to retrieve.
-- @returns
-- The requested option, or nil if the option does not exist.
--
function premake.option.get(name)
return premake.option.list[name]
end
--
-- Iterator for the list of options.
--
function premake.option.each()
-- sort the list by trigger
local keys = { }
for _, option in pairs(premake.option.list) do
table.insert(keys, option.trigger)
end
table.sort(keys)
local i = 0
return function()
i = i + 1
return premake.option.list[keys[i]]
end
end
--
-- Validate a list of user supplied key/value pairs against the list of registered options.
--
-- @param values
-- The list of user supplied key/value pairs.
-- @returns
--- True if the list of pairs are valid, false and an error message otherwise.
--
function premake.option.validate(values)
for key, value in pairs(values) do
-- does this option exist
local opt = premake.option.get(key)
if (not opt) then
return false, "invalid option '" .. key .. "'"
end
-- does it need a value?
if (opt.value and value == "") then
return false, "no value specified for option '" .. key .. "'"
end
-- is the value allowed?
if (opt.allowed) then
for _, match in ipairs(opt.allowed) do
if (match[1] == value) then return true end
end
return false, "invalid value '" .. value .. "' for option '" .. key .. "'"
end
end
return true
end

View File

@ -0,0 +1,203 @@
--
-- os.lua
-- Additions to the OS namespace.
-- Copyright (c) 2002-2010 Jason Perkins and the Premake project
--
--
-- Same as os.execute(), but accepts string formatting arguments.
--
function os.executef(cmd, ...)
cmd = string.format(cmd, unpack(arg))
return os.execute(cmd)
end
--
-- Scan the well-known system locations for a particular library.
--
function os.findlib(libname)
local path, formats
-- assemble a search path, depending on the platform
if os.is("windows") then
formats = { "%s.dll", "%s" }
path = os.getenv("PATH")
else
if os.is("macosx") then
formats = { "lib%s.dylib", "%s.dylib" }
path = os.getenv("DYLD_LIBRARY_PATH")
else
formats = { "lib%s.so", "%s.so" }
path = os.getenv("LD_LIBRARY_PATH") or ""
io.input("/etc/ld.so.conf")
if io.input() then
for line in io.lines() do
path = path .. ":" .. line
end
io.input():close()
end
end
table.insert(formats, "%s")
path = (path or "") .. ":/lib:/usr/lib:/usr/local/lib"
end
for _, fmt in ipairs(formats) do
local name = string.format(fmt, libname)
local result = os.pathsearch(name, path)
if result then return result end
end
end
--
-- Retrieve the current operating system ID string.
--
function os.get()
return _OPTIONS.os or _OS
end
--
-- Check the current operating system; may be set with the /os command line flag.
--
function os.is(id)
return (os.get():lower() == id:lower())
end
--
-- The os.matchdirs() and os.matchfiles() functions
--
local function domatch(result, mask, wantfiles)
-- need to remove extraneous path info from the mask to ensure a match
-- against the paths returned by the OS. Haven't come up with a good
-- way to do it yet, so will handle cases as they come up
if mask:startswith("./") then
mask = mask:sub(3)
end
-- strip off any leading directory information to find out
-- where the search should take place
local basedir = mask
local starpos = mask:find("%*")
if starpos then
basedir = basedir:sub(1, starpos - 1)
end
basedir = path.getdirectory(basedir)
if (basedir == ".") then basedir = "" end
-- recurse into subdirectories?
local recurse = mask:find("**", nil, true)
-- convert mask to a Lua pattern
mask = path.wildcards(mask)
local function matchwalker(basedir)
local wildcard = path.join(basedir, "*")
-- retrieve files from OS and test against mask
local m = os.matchstart(wildcard)
while (os.matchnext(m)) do
local isfile = os.matchisfile(m)
if ((wantfiles and isfile) or (not wantfiles and not isfile)) then
local fname = path.join(basedir, os.matchname(m))
if fname:match(mask) == fname then
table.insert(result, fname)
end
end
end
os.matchdone(m)
-- check subdirectories
if recurse then
m = os.matchstart(wildcard)
while (os.matchnext(m)) do
if not os.matchisfile(m) then
local dirname = os.matchname(m)
matchwalker(path.join(basedir, dirname))
end
end
os.matchdone(m)
end
end
matchwalker(basedir)
end
function os.matchdirs(...)
local result = { }
for _, mask in ipairs(arg) do
domatch(result, mask, false)
end
return result
end
function os.matchfiles(...)
local result = { }
for _, mask in ipairs(arg) do
domatch(result, mask, true)
end
return result
end
--
-- An overload of the os.mkdir() function, which will create any missing
-- subdirectories along the path.
--
local builtin_mkdir = os.mkdir
function os.mkdir(p)
local dir = iif(p:startswith("/"), "/", "")
for part in p:gmatch("[^/]+") do
dir = dir .. part
if (part ~= "" and not path.isabsolute(part) and not os.isdir(dir)) then
local ok, err = builtin_mkdir(dir)
if (not ok) then
return nil, err
end
end
dir = dir .. "/"
end
return true
end
--
-- Remove a directory, along with any contained files or subdirectories.
--
local builtin_rmdir = os.rmdir
function os.rmdir(p)
-- recursively remove subdirectories
local dirs = os.matchdirs(p .. "/*")
for _, dname in ipairs(dirs) do
os.rmdir(dname)
end
-- remove any files
local files = os.matchfiles(p .. "/*")
for _, fname in ipairs(files) do
os.remove(fname)
end
-- remove this directory
builtin_rmdir(p)
end

View File

@ -0,0 +1,298 @@
--
-- path.lua
-- Path manipulation functions.
-- Copyright (c) 2002-2010 Jason Perkins and the Premake project
--
--
-- Get the absolute file path from a relative path. The requested
-- file path doesn't actually need to exist.
--
function path.getabsolute(p)
-- normalize the target path
p = path.translate(p, "/")
if (p == "") then p = "." end
-- if the directory is already absolute I don't need to do anything
local result = iif (path.isabsolute(p), nil, os.getcwd())
-- split up the supplied relative path and tackle it bit by bit
for n, part in ipairs(p:explode("/", true)) do
if (part == "" and n == 1) then
result = "/"
elseif (part == "..") then
result = path.getdirectory(result)
elseif (part ~= ".") then
result = path.join(result, part)
end
end
-- if I end up with a trailing slash remove it
result = iif(result:endswith("/"), result:sub(1, -2), result)
return result
end
--
-- Retrieve the filename portion of a path, without any extension.
--
function path.getbasename(p)
local name = path.getname(p)
local i = name:findlast(".", true)
if (i) then
return name:sub(1, i - 1)
else
return name
end
end
--
-- Retrieve the directory portion of a path, or an empty string if
-- the path does not include a directory.
--
function path.getdirectory(p)
local i = p:findlast("/", true)
if (i) then
if i > 1 then i = i - 1 end
return p:sub(1, i)
else
return "."
end
end
--
-- Retrieve the drive letter, if a Windows path.
--
function path.getdrive(p)
local ch1 = p:sub(1,1)
local ch2 = p:sub(2,2)
if ch2 == ":" then
return ch1
end
end
--
-- Retrieve the file extension.
--
function path.getextension(p)
local i = p:findlast(".", true)
if (i) then
return p:sub(i)
else
return ""
end
end
--
-- Retrieve the filename portion of a path.
--
function path.getname(p)
local i = p:findlast("[/\\]")
if (i) then
return p:sub(i + 1)
else
return p
end
end
--
-- Returns the relative path from src to dest.
--
function path.getrelative(src, dst)
-- normalize the two paths
src = path.getabsolute(src)
dst = path.getabsolute(dst)
-- same directory?
if (src == dst) then
return "."
end
-- dollar macro? Can't tell what the real path is; use absolute
-- This enables paths like $(SDK_ROOT)/include to work correctly.
if dst:startswith("$") then
return dst
end
src = src .. "/"
dst = dst .. "/"
-- find the common leading directories
local idx = 0
while (true) do
local tst = src:find("/", idx + 1, true)
if tst then
if src:sub(1,tst) == dst:sub(1,tst) then
idx = tst
else
break
end
else
break
end
end
-- if they have nothing in common return absolute path
local first = src:find("/", 0, true)
if idx <= first then
return dst:sub(1, -2)
end
-- trim off the common directories from the front
src = src:sub(idx + 1)
dst = dst:sub(idx + 1)
-- back up from dst to get to this common parent
local result = ""
idx = src:find("/")
while (idx) do
result = result .. "../"
idx = src:find("/", idx + 1)
end
-- tack on the path down to the dst from here
result = result .. dst
-- remove the trailing slash
return result:sub(1, -2)
end
--
-- Returns true if the filename represents a C/C++ source code file. This check
-- is used to prevent passing non-code files to the compiler in makefiles. It is
-- not foolproof, but it has held up well. I'm open to better suggestions.
--
function path.iscfile(fname)
local extensions = { ".c", ".s", ".m" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
function path.iscppfile(fname)
local extensions = { ".cc", ".cpp", ".cxx", ".c", ".s", ".m", ".mm" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
--
-- Returns true if the filename represents a Windows resource file. This check
-- is used to prevent passing non-resources to the compiler in makefiles.
--
function path.isresourcefile(fname)
local extensions = { ".rc" }
local ext = path.getextension(fname):lower()
return table.contains(extensions, ext)
end
--
-- Join two pieces of a path together into a single path.
--
function path.join(leading, trailing)
leading = leading or ""
if (not trailing) then
return leading
end
if (path.isabsolute(trailing)) then
return trailing
end
if (leading == ".") then
leading = ""
end
if (leading:len() > 0 and not leading:endswith("/")) then
leading = leading .. "/"
end
return leading .. trailing
end
--
-- Takes a path which is relative to one location and makes it relative
-- to another location instead.
--
function path.rebase(p, oldbase, newbase)
p = path.getabsolute(path.join(oldbase, p))
p = path.getrelative(newbase, p)
return p
end
--
-- Convert the separators in a path from one form to another. If `sep`
-- is nil, then a platform-specific separator is used.
--
function path.translate(p, sep)
if (type(p) == "table") then
local result = { }
for _, value in ipairs(p) do
table.insert(result, path.translate(value))
end
return result
else
if (not sep) then
if (os.is("windows")) then
sep = "\\"
else
sep = "/"
end
end
local result = p:gsub("[/\\]", sep)
return result
end
end
--
-- Converts from a simple wildcard syntax, where * is "match any"
-- and ** is "match recursive", to the corresponding Lua pattern.
--
-- @param pattern
-- The wildcard pattern to convert.
-- @returns
-- The corresponding Lua pattern.
--
function path.wildcards(pattern)
-- Escape characters that have special meanings in Lua patterns
pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
-- Replace wildcard patterns with special placeholders so I don't
-- have competing star replacements to worry about
pattern = pattern:gsub("%*%*", "\001")
pattern = pattern:gsub("%*", "\002")
-- Replace the placeholders with their Lua patterns
pattern = pattern:gsub("\001", ".*")
pattern = pattern:gsub("\002", "[^/]*")
return pattern
end

View File

@ -0,0 +1,34 @@
--
-- premake.lua
-- High-level processing functions.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
--
-- Open a file for output, and call a function to actually do the writing.
-- Used by the actions to generate solution and project files.
--
-- @param obj
-- A solution or project object; will be based to the callback function.
-- @param filename
-- The output filename; see the docs for premake.project.getfilename()
-- for the expected format.
-- @param callback
-- The function responsible for writing the file, should take a solution
-- or project as a parameters.
--
function premake.generate(obj, filename, callback)
filename = premake.project.getfilename(obj, filename)
printf("Generating %s...", filename)
local f, err = io.open(filename, "wb")
if (not f) then
error(err, 0)
end
io.output(f)
callback(obj)
f:close()
end

View File

@ -0,0 +1,620 @@
--
-- project.lua
-- Functions for working with the project data.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.project = { }
--
-- Create a tree from a project's list of files, representing the filesystem hierarchy.
--
-- @param prj
-- The project containing the files to map.
-- @returns
-- A new tree object containing a corresponding filesystem hierarchy. The root node
-- contains a reference back to the original project: prj = tr.project.
--
function premake.project.buildsourcetree(prj)
local tr = premake.tree.new(prj.name)
for _, fname in ipairs(prj.files) do
local node = premake.tree.add(tr, fname)
end
premake.tree.sort(tr)
tr.project = prj
return tr
end
--
-- Returns an iterator for a set of build configuration settings. If a platform is
-- specified, settings specific to that platform and build configuration pair are
-- returned.
--
function premake.eachconfig(prj, platform)
-- I probably have the project root config, rather than the actual project
if prj.project then prj = prj.project end
local cfgs = prj.solution.configurations
local i = 0
return function ()
i = i + 1
if i <= #cfgs then
return premake.getconfig(prj, cfgs[i], platform)
end
end
end
--
-- Iterator for a project's files; returns a file configuration object.
--
function premake.eachfile(prj)
-- project root config contains the file config list
if not prj.project then prj = premake.getconfig(prj) end
local i = 0
local t = prj.files
return function ()
i = i + 1
if (i <= #t) then
return prj.__fileconfigs[t[i]]
end
end
end
--
-- Apply XML escaping to a value.
--
function premake.esc(value)
if (type(value) == "table") then
local result = { }
for _,v in ipairs(value) do
table.insert(result, premake.esc(v))
end
return result
else
value = value:gsub('&', "&amp;")
value = value:gsub('"', "&quot;")
value = value:gsub("'", "&apos;")
value = value:gsub('<', "&lt;")
value = value:gsub('>', "&gt;")
value = value:gsub('\r', "&#x0D;")
value = value:gsub('\n', "&#x0A;")
return value
end
end
--
-- Given a map of supported platform identifiers, filters the solution's list
-- of platforms to match. A map takes the form of a table like:
--
-- { x32 = "Win32", x64 = "x64" }
--
-- Only platforms that are listed in both the solution and the map will be
-- included in the results. An optional default platform may also be specified;
-- if the result set would otherwise be empty this platform will be used.
--
function premake.filterplatforms(sln, map, default)
local result = { }
local keys = { }
if sln.platforms then
for _, p in ipairs(sln.platforms) do
if map[p] and not table.contains(keys, map[p]) then
table.insert(result, p)
table.insert(keys, map[p])
end
end
end
if #result == 0 and default then
table.insert(result, default)
end
return result
end
--
-- Locate a project by name; case insensitive.
--
function premake.findproject(name)
for sln in premake.solution.each() do
for prj in premake.solution.eachproject(sln) do
if (prj.name == name) then
return prj
end
end
end
end
--
-- Locate a file in a project with a given extension; used to locate "special"
-- items such as Windows .def files.
--
function premake.findfile(prj, extension)
for _, fname in ipairs(prj.files) do
if fname:endswith(extension) then return fname end
end
end
--
-- Retrieve a configuration for a given project/configuration pairing.
-- @param prj
-- The project to query.
-- @param cfgname
-- The target build configuration; only settings applicable to this configuration
-- will be returned. May be nil to retrieve project-wide settings.
-- @param pltname
-- The target platform; only settings applicable to this platform will be returned.
-- May be nil to retrieve platform-independent settings.
-- @returns
-- A configuration object containing all the settings for the given platform/build
-- configuration pair.
--
function premake.getconfig(prj, cfgname, pltname)
-- might have the root configuration, rather than the actual project
prj = prj.project or prj
-- if platform is not included in the solution, use general settings instead
if pltname == "Native" or not table.contains(prj.solution.platforms or {}, pltname) then
pltname = nil
end
local key = (cfgname or "")
if pltname then key = key .. pltname end
return prj.__configs[key]
end
--
-- Build a name from a build configuration/platform pair. The short name
-- is good for makefiles or anywhere a user will have to type it in. The
-- long name is more readable.
--
function premake.getconfigname(cfgname, platform, useshortname)
if cfgname then
local name = cfgname
if platform and platform ~= "Native" then
if useshortname then
name = name .. premake.platforms[platform].cfgsuffix
else
name = name .. "|" .. platform
end
end
return iif(useshortname, name:lower(), name)
end
end
--
-- Returns a list of sibling projects on which the specified project depends.
-- This is used to list dependencies within a solution or workspace. Must
-- consider all configurations because Visual Studio does not support per-config
-- project dependencies.
--
-- @param prj
-- The project to query.
-- @returns
-- A list of dependent projects, as an array of objects.
--
function premake.getdependencies(prj)
-- make sure I've got the project and not root config
prj = prj.project or prj
local results = { }
for _, cfg in pairs(prj.__configs) do
for _, link in ipairs(cfg.links) do
local dep = premake.findproject(link)
if dep and not table.contains(results, dep) then
table.insert(results, dep)
end
end
end
return results
end
--
-- Uses information from a project (or solution) to format a filename.
--
-- @param prj
-- A project or solution object with the file naming information.
-- @param pattern
-- A naming pattern. The sequence "%%" will be replaced by the
-- project name.
-- @returns
-- A filename matching the specified pattern, with a relative path
-- from the current directory to the project location.
--
function premake.project.getfilename(prj, pattern)
local fname = pattern:gsub("%%%%", prj.name)
fname = path.join(prj.location, fname)
return path.getrelative(os.getcwd(), fname)
end
--
-- Returns a list of link targets. Kind may be one of:
-- siblings - linkable sibling projects
-- system - system (non-sibling) libraries
-- dependencies - all sibling dependencies, including non-linkable
-- all - return everything
--
-- Part may be one of:
-- name - the decorated library name with no directory
-- basename - the undecorated library name
-- directory - just the directory, no name
-- fullpath - full path with decorated name
-- object - return the project object of the dependency
--
function premake.getlinks(cfg, kind, part)
-- if I'm building a list of link directories, include libdirs
local result = iif (part == "directory" and kind == "all", cfg.libdirs, {})
-- am I getting links for a configuration or a project?
local cfgname = iif(cfg.name == cfg.project.name, "", cfg.name)
-- how should files be named?
local pathstyle = premake.getpathstyle(cfg)
local namestyle = premake.getnamestyle(cfg)
local function canlink(source, target)
if (target.kind ~= "SharedLib" and target.kind ~= "StaticLib") then
return false
end
if premake.iscppproject(source) then
return premake.iscppproject(target)
elseif premake.isdotnetproject(source) then
return premake.isdotnetproject(target)
end
end
for _, link in ipairs(cfg.links) do
local item
-- is this a sibling project?
local prj = premake.findproject(link)
if prj and kind ~= "system" then
local prjcfg = premake.getconfig(prj, cfgname, cfg.platform)
if kind == "dependencies" or canlink(cfg, prjcfg) then
if (part == "directory") then
item = path.rebase(prjcfg.linktarget.directory, prjcfg.location, cfg.location)
elseif (part == "basename") then
item = prjcfg.linktarget.basename
elseif (part == "fullpath") then
item = path.rebase(prjcfg.linktarget.fullpath, prjcfg.location, cfg.location)
elseif (part == "object") then
item = prjcfg
end
end
elseif not prj and (kind == "system" or kind == "all") then
if (part == "directory") then
local dir = path.getdirectory(link)
if (dir ~= ".") then
item = dir
end
elseif (part == "fullpath") then
item = link
if namestyle == "windows" then
if premake.iscppproject(cfg) then
item = item .. ".lib"
elseif premake.isdotnetproject(cfg) then
item = item .. ".dll"
end
end
if item:find("/", nil, true) then
item = path.getrelative(cfg.basedir, item)
end
else
item = link
end
end
if item then
if pathstyle == "windows" and part ~= "object" then
item = path.translate(item, "\\")
end
if not table.contains(result, item) then
table.insert(result, item)
end
end
end
return result
end
--
-- Gets the name style for a configuration, indicating what kind of prefix,
-- extensions, etc. should be used in target file names.
--
-- @param cfg
-- The configuration to check.
-- @returns
-- The target naming style, one of "windows", "posix", or "PS3".
--
function premake.getnamestyle(cfg)
return premake.platforms[cfg.platform].namestyle or premake.gettool(cfg).namestyle or "posix"
end
--
-- Gets the path style for a configuration, indicating what kind of path separator
-- should be used in target file names.
--
-- @param cfg
-- The configuration to check.
-- @returns
-- The target path style, one of "windows" or "posix".
--
function premake.getpathstyle(cfg)
if premake.action.current().os == "windows" then
return "windows"
else
return "posix"
end
end
--
-- Assembles a target for a particular tool/system/configuration.
--
-- @param cfg
-- The configuration to be targeted.
-- @param direction
-- One of 'build' for the build target, or 'link' for the linking target.
-- @param pathstyle
-- The path format, one of "windows" or "posix". This comes from the current
-- action: Visual Studio uses "windows", GMake uses "posix", etc.
-- @param namestyle
-- The file naming style, one of "windows" or "posix". This comes from the
-- current tool: GCC uses "posix", MSC uses "windows", etc.
-- @param system
-- The target operating system, which can modify the naming style. For example,
-- shared libraries on Mac OS X use a ".dylib" extension.
-- @returns
-- An object with these fields:
-- basename - the target with no directory or file extension
-- name - the target name and extension, with no directory
-- directory - relative path to the target, with no file name
-- prefix - the file name prefix
-- suffix - the file name suffix
-- fullpath - directory, name, and extension
-- bundlepath - the relative path and file name of the bundle
--
function premake.gettarget(cfg, direction, pathstyle, namestyle, system)
if system == "bsd" or system == "solaris" then
system = "linux"
end
-- Fix things up based on the current system
local kind = cfg.kind
if premake.iscppproject(cfg) then
-- On Windows, shared libraries link against a static import library
if (namestyle == "windows" or system == "windows") and kind == "SharedLib" and direction == "link" then
kind = "StaticLib"
end
-- Posix name conventions only apply to static libs on windows (by user request)
if namestyle == "posix" and system == "windows" and kind ~= "StaticLib" then
namestyle = "windows"
end
end
-- Initialize the target components
local field = iif(direction == "build", "target", "implib")
local name = cfg[field.."name"] or cfg.targetname or cfg.project.name
local dir = cfg[field.."dir"] or cfg.targetdir or path.getrelative(cfg.location, cfg.basedir)
local prefix = ""
local suffix = ""
local ext = ""
local bundlepath, bundlename
if namestyle == "windows" then
if kind == "ConsoleApp" or kind == "WindowedApp" then
ext = ".exe"
elseif kind == "SharedLib" then
ext = ".dll"
elseif kind == "StaticLib" then
ext = ".lib"
end
elseif namestyle == "posix" then
if kind == "WindowedApp" and system == "macosx" then
bundlename = name .. ".app"
bundlepath = path.join(dir, bundlename)
dir = path.join(bundlepath, "Contents/MacOS")
elseif kind == "SharedLib" then
prefix = "lib"
ext = iif(system == "macosx", ".dylib", ".so")
elseif kind == "StaticLib" then
prefix = "lib"
ext = ".a"
end
elseif namestyle == "PS3" then
if kind == "ConsoleApp" or kind == "WindowedApp" then
ext = ".elf"
elseif kind == "StaticLib" then
prefix = "lib"
ext = ".a"
end
end
prefix = cfg[field.."prefix"] or cfg.targetprefix or prefix
suffix = cfg[field.."suffix"] or cfg.targetsuffix or suffix
ext = cfg[field.."extension"] or cfg.targetextension or ext
-- build the results object
local result = { }
result.basename = name .. suffix
result.name = prefix .. name .. suffix .. ext
result.directory = dir
result.prefix = prefix
result.suffix = suffix
result.fullpath = path.join(result.directory, result.name)
result.bundlepath = bundlepath or result.fullpath
if pathstyle == "windows" then
result.directory = path.translate(result.directory, "\\")
result.fullpath = path.translate(result.fullpath, "\\")
end
return result
end
--
-- Return the appropriate tool interface, based on the target language and
-- any relevant command-line options.
--
function premake.gettool(cfg)
if premake.iscppproject(cfg) then
if _OPTIONS.cc then
return premake[_OPTIONS.cc]
end
local action = premake.action.current()
if action.valid_tools then
return premake[action.valid_tools.cc[1]]
end
return premake.gcc
else
return premake.dotnet
end
end
--
-- Returns true if the solution contains at least one C/C++ project.
--
function premake.hascppproject(sln)
for prj in premake.solution.eachproject(sln) do
if premake.iscppproject(prj) then
return true
end
end
end
--
-- Returns true if the solution contains at least one .NET project.
--
function premake.hasdotnetproject(sln)
for prj in premake.solution.eachproject(sln) do
if premake.isdotnetproject(prj) then
return true
end
end
end
--
-- Returns true if the project uses a C/C++ language.
--
function premake.iscppproject(prj)
return (prj.language == "C" or prj.language == "C++")
end
--
-- Returns true if the project uses a .NET language.
--
function premake.isdotnetproject(prj)
return (prj.language == "C#")
end
--
-- Walk the list of source code files, breaking them into "groups" based
-- on the directory hierarchy.
--
local function walksources(cfg, fn, group, nestlevel, finished)
local grouplen = group:len()
local gname = iif(group:endswith("/"), group:sub(1, -2), group)
-- open this new group
if (nestlevel >= 0) then
fn(cfg, gname, "GroupStart", nestlevel)
end
-- scan the list of files for items which belong in this group
for _,fname in ipairs(cfg.files) do
if (fname:startswith(group)) then
-- is there a subgroup within this item?
local _,split = fname:find("[^\.]/", grouplen + 1)
if (split) then
local subgroup = fname:sub(1, split)
if (not finished[subgroup]) then
finished[subgroup] = true
walksources(cfg, fn, subgroup, nestlevel + 1, finished)
end
end
end
end
-- process all files that belong in this group
for _,fname in ipairs(cfg.files) do
if (fname:startswith(group) and not fname:find("[^\.]/", grouplen + 1)) then
fn(cfg, fname, "GroupItem", nestlevel + 1)
end
end
-- close the group
if (nestlevel >= 0) then
fn(cfg, gname, "GroupEnd", nestlevel)
end
end
function premake.walksources(cfg, fn)
walksources(cfg, fn, "", -1, {})
end

View File

@ -0,0 +1,113 @@
--
-- solution.lua
-- Work with the list of solutions loaded from the script.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
premake.solution = { }
-- The list of defined solutions (which contain projects, etc.)
premake.solution.list = { }
--
-- Create a new solution and add it to the session.
--
-- @param name
-- The new solution's name.
--
function premake.solution.new(name)
local sln = { }
-- add to master list keyed by both name and index
table.insert(premake.solution.list, sln)
premake.solution.list[name] = sln
-- attach a type descriptor
setmetatable(sln, { __type="solution" })
sln.name = name
sln.basedir = os.getcwd()
sln.projects = { }
sln.blocks = { }
sln.configurations = { }
return sln
end
--
-- Iterate over the collection of solutions in a session.
--
-- @returns
-- An iterator function.
--
function premake.solution.each()
local i = 0
return function ()
i = i + 1
if i <= #premake.solution.list then
return premake.solution.list[i]
end
end
end
--
-- Iterate over the projects of a solution.
--
-- @param sln
-- The solution.
-- @returns
-- An iterator function.
--
function premake.solution.eachproject(sln)
local i = 0
return function ()
i = i + 1
if (i <= #sln.projects) then
return premake.solution.getproject(sln, i)
end
end
end
--
-- Retrieve a solution by name or index.
--
-- @param key
-- The solution key, either a string name or integer index.
-- @returns
-- The solution with the provided key.
--
function premake.solution.get(key)
return premake.solution.list[key]
end
--
-- Retrieve the project at a particular index.
--
-- @param sln
-- The solution.
-- @param idx
-- An index into the array of projects.
-- @returns
-- The project at the given index.
--
function premake.solution.getproject(sln, idx)
-- retrieve the root configuration of the project, with all of
-- the global (not configuration specific) settings collapsed
local prj = sln.projects[idx]
local cfg = premake.getconfig(prj)
-- root configuration doesn't have a name; use the project's
cfg.name = prj.name
return cfg
end

View File

@ -0,0 +1,50 @@
--
-- string.lua
-- Additions to Lua's built-in string functions.
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
--
--
-- Returns an array of strings, each of which is a substring of s
-- formed by splitting on boundaries formed by `pattern`.
--
function string.explode(s, pattern, plain)
if (pattern == '') then return false end
local pos = 0
local arr = { }
for st,sp in function() return s:find(pattern, pos, plain) end do
table.insert(arr, s:sub(pos, st-1))
pos = sp + 1
end
table.insert(arr, s:sub(pos))
return arr
end
--
-- Find the last instance of a pattern in a string.
--
function string.findlast(s, pattern, plain)
local curr = 0
repeat
local next = s:find(pattern, curr + 1, plain)
if (next) then curr = next end
until (not next)
if (curr > 0) then
return curr
end
end
--
-- Returns true if `haystack` starts with the sequence `needle`.
--
function string.startswith(haystack, needle)
return (haystack:find(needle, 1, true) == 1)
end

View File

@ -0,0 +1,139 @@
--
-- table.lua
-- Additions to Lua's built-in table functions.
-- Copyright (c) 2002-2008 Jason Perkins and the Premake project
--
--
-- Returns true if the table contains the specified value.
--
function table.contains(t, value)
for _,v in pairs(t) do
if (v == value) then
return true
end
end
return false
end
--
-- Enumerates an array of objects and returns a new table containing
-- only the value of one particular field.
--
function table.extract(arr, fname)
local result = { }
for _,v in ipairs(arr) do
table.insert(result, v[fname])
end
return result
end
--
-- Flattens a hierarchy of tables into a single array containing all
-- of the values.
--
function table.flatten(arr)
local result = { }
local function flatten(arr)
for _, v in ipairs(arr) do
if type(v) == "table" then
flatten(v)
else
table.insert(result, v)
end
end
end
flatten(arr)
return result
end
--
-- Merges an array of items into a string.
--
function table.implode(arr, before, after, between)
local result = ""
for _,v in ipairs(arr) do
if (result ~= "" and between) then
result = result .. between
end
result = result .. before .. v .. after
end
return result
end
--
-- Returns true if the table is empty, and contains no indexed or keyed values.
--
function table.isempty(t)
return not next(t)
end
--
-- Adds the values from one array to the end of another and
-- returns the result.
--
function table.join(...)
local result = { }
for _,t in ipairs(arg) do
if type(t) == "table" then
for _,v in ipairs(t) do
table.insert(result, v)
end
else
table.insert(result, t)
end
end
return result
end
--
-- Return a list of all keys used in a table.
--
function table.keys(tbl)
local keys = {}
for k, _ in pairs(tbl) do
table.insert(keys, k)
end
return keys
end
--
-- Translates the values contained in array, using the specified
-- translation table, and returns the results in a new array.
--
function table.translate(arr, translation)
local result = { }
for _, value in ipairs(arr) do
local tvalue
if type(translation) == "function" then
tvalue = translation(value)
else
tvalue = translation[value]
end
if (tvalue) then
table.insert(result, tvalue)
end
end
return result
end

View File

@ -0,0 +1,195 @@
--
-- tree.lua
-- Functions for working with the source code tree.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--
premake.tree = { }
local tree = premake.tree
--
-- Create a new tree.
--
-- @param n
-- The name of the tree, applied to the root node (optional).
--
function premake.tree.new(n)
local t = {
name = n,
children = { }
}
return t
end
--
-- Add a new node to the tree, or returns the current node if it already exists.
--
-- @param tr
-- The tree to contain the new node.
-- @param p
-- The path of the new node.
-- @returns
-- The new tree node.
--
function premake.tree.add(tr, p)
-- Special case "." refers to the current node
if p == "." then
return tr
end
-- Look for the immediate parent for this new node, creating it if necessary.
-- Recurses to create as much of the tree as necessary.
local parentnode = tree.add(tr, path.getdirectory(p))
-- Another special case, ".." refers to the parent node and doesn't create anything
local childname = path.getname(p)
if childname == ".." then
return parentnode
end
-- Create the child if necessary. If two children with the same name appear
-- at the same level, make sure they have the same path to prevent conflicts
-- i.e. ../Common and ../../Common can both appear at the top of the tree
-- yet they have different paths (Bug #3016050)
local childnode = parentnode.children[childname]
if not childnode or childnode.path ~= p then
childnode = tree.insert(parentnode, tree.new(childname))
childnode.path = p
end
return childnode
end
--
-- Insert one tree into another.
--
-- @param parent
-- The parent tree, to contain the child.
-- @param child
-- The child tree, to be inserted.
--
function premake.tree.insert(parent, child)
table.insert(parent.children, child)
if child.name then
parent.children[child.name] = child
end
child.parent = parent
return child
end
--
-- Gets the node's relative path from it's parent. If the parent does not have
-- a path set (it is the root or other container node) returns the full node path.
--
-- @param node
-- The node to query.
--
function premake.tree.getlocalpath(node)
if node.parent.path then
return node.name
else
return node.path
end
end
--
-- Remove a node from a tree.
--
-- @param node
-- The node to remove.
--
function premake.tree.remove(node)
local children = node.parent.children
for i = 1, #children do
if children[i] == node then
table.remove(children, i)
end
end
node.children = {}
end
--
-- Sort the nodes of a tree in-place.
--
-- @param tr
-- The tree to sort.
--
function premake.tree.sort(tr)
tree.traverse(tr, {
onnode = function(node)
table.sort(node.children, function(a,b)
return a.name < b.name
end)
end
}, true)
end
--
-- Traverse a tree.
--
-- @param t
-- The tree to traverse.
-- @param fn
-- A collection of callback functions, which may contain:
--
-- onnode(node, depth) - called on each node encountered
-- onleaf(node, depth) - called only on leaf nodes
-- onbranch(node, depth) - called only on branch nodes
--
-- @param includeroot
-- True to include the root node in the traversal, otherwise it will be skipped.
--
function premake.tree.traverse(t, fn, includeroot)
local donode, dochildren
donode = function(node, fn, depth)
if node.isremoved then
return
end
if fn.onnode then
fn.onnode(node, depth)
end
if #node.children > 0 then
if fn.onbranch then
fn.onbranch(node, depth)
end
dochildren(node, fn, depth + 1)
else
if fn.onleaf then
fn.onleaf(node, depth)
end
end
end
dochildren = function(parent, fn, depth)
-- this goofy iterator allows nodes to be removed during the traversal
local i = 1
while i <= #parent.children do
local node = parent.children[i]
donode(node, fn, depth)
if node == parent.children[i] then
i = i + 1
end
end
end
if includeroot then
donode(t, fn, 0)
else
dochildren(t, fn, 0)
end
end

View File

@ -0,0 +1,91 @@
--
-- validate.lua
-- Tests to validate the run-time environment before starting the action.
-- Copyright (c) 2002-2009 Jason Perkins and the Premake project
--
--
-- Performs a sanity check of all of the solutions and projects
-- in the session to be sure they meet some minimum requirements.
--
function premake.checkprojects()
local action = premake.action.current()
for sln in premake.solution.each() do
-- every solution must have at least one project
if (#sln.projects == 0) then
return nil, "solution '" .. sln.name .. "' needs at least one project"
end
-- every solution must provide a list of configurations
if (#sln.configurations == 0) then
return nil, "solution '" .. sln.name .. "' needs configurations"
end
for prj in premake.solution.eachproject(sln) do
-- every project must have a language
if (not prj.language) then
return nil, "project '" ..prj.name .. "' needs a language"
end
-- and the action must support it
if (action.valid_languages) then
if (not table.contains(action.valid_languages, prj.language)) then
return nil, "the " .. action.shortname .. " action does not support " .. prj.language .. " projects"
end
end
for cfg in premake.eachconfig(prj) do
-- every config must have a kind
if (not cfg.kind) then
return nil, "project '" ..prj.name .. "' needs a kind in configuration '" .. cfg.name .. "'"
end
-- and the action must support it
if (action.valid_kinds) then
if (not table.contains(action.valid_kinds, cfg.kind)) then
return nil, "the " .. action.shortname .. " action does not support " .. cfg.kind .. " projects"
end
end
end
-- some actions have custom validation logic
if action.oncheckproject then
action.oncheckproject(prj)
end
end
end
return true
end
--
-- Check the specified tools (/cc, /dotnet, etc.) against the current action
-- to make sure they are compatible and supported.
--
function premake.checktools()
local action = premake.action.current()
if (not action.valid_tools) then
return true
end
for tool, values in pairs(action.valid_tools) do
if (_OPTIONS[tool]) then
if (not table.contains(values, _OPTIONS[tool])) then
return nil, "the " .. action.shortname .. " action does not support /" .. tool .. "=" .. _OPTIONS[tool] .. " (yet)"
end
else
_OPTIONS[tool] = values[1]
end
end
return true
end

View File

@ -0,0 +1,34 @@
Lua License
-----------
Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost.
For details and rationale, see http://www.lua.org/license.html .
===============================================================================
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
(end of COPYRIGHT)

View File

@ -0,0 +1,183 @@
HISTORY for Lua 5.1
* Changes from version 5.0 to 5.1
-------------------------------
Language:
+ new module system.
+ new semantics for control variables of fors.
+ new semantics for setn/getn.
+ new syntax/semantics for varargs.
+ new long strings and comments.
+ new `mod' operator (`%')
+ new length operator #t
+ metatables for all types
API:
+ new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.
+ user supplies memory allocator (lua_open becomes lua_newstate).
+ luaopen_* functions must be called through Lua.
Implementation:
+ new configuration scheme via luaconf.h.
+ incremental garbage collection.
+ better handling of end-of-line in the lexer.
+ fully reentrant parser (new Lua function `load')
+ better support for 64-bit machines.
+ native loadlib support for Mac OS X.
+ standard distribution in only one library (lualib.a merged into lua.a)
* Changes from version 4.0 to 5.0
-------------------------------
Language:
+ lexical scoping.
+ Lua coroutines.
+ standard libraries now packaged in tables.
+ tags replaced by metatables and tag methods replaced by metamethods,
stored in metatables.
+ proper tail calls.
+ each function can have its own global table, which can be shared.
+ new __newindex metamethod, called when we insert a new key into a table.
+ new block comments: --[[ ... ]].
+ new generic for.
+ new weak tables.
+ new boolean type.
+ new syntax "local function".
+ (f()) returns the first value returned by f.
+ {f()} fills a table with all values returned by f.
+ \n ignored in [[\n .
+ fixed and-or priorities.
+ more general syntax for function definition (e.g. function a.x.y:f()...end).
+ more general syntax for function calls (e.g. (print or write)(9)).
+ new functions (time/date, tmpfile, unpack, require, load*, etc.).
API:
+ chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.
+ introduced lightweight userdata, a simple "void*" without a metatable.
+ new error handling protocol: the core no longer prints error messages;
all errors are reported to the caller on the stack.
+ new lua_atpanic for host cleanup.
+ new, signal-safe, hook scheme.
Implementation:
+ new license: MIT.
+ new, faster, register-based virtual machine.
+ support for external multithreading and coroutines.
+ new and consistent error message format.
+ the core no longer needs "stdio.h" for anything (except for a single
use of sprintf to convert numbers to strings).
+ lua.c now runs the environment variable LUA_INIT, if present. It can
be "@filename", to run a file, or the chunk itself.
+ support for user extensions in lua.c.
sample implementation given for command line editing.
+ new dynamic loading library, active by default on several platforms.
+ safe garbage-collector metamethods.
+ precompiled bytecodes checked for integrity (secure binary dostring).
+ strings are fully aligned.
+ position capture in string.find.
+ read('*l') can read lines with embedded zeros.
* Changes from version 3.2 to 4.0
-------------------------------
Language:
+ new "break" and "for" statements (both numerical and for tables).
+ uniform treatment of globals: globals are now stored in a Lua table.
+ improved error messages.
+ no more '$debug': full speed *and* full debug information.
+ new read form: read(N) for next N bytes.
+ general read patterns now deprecated.
(still available with -DCOMPAT_READPATTERNS.)
+ all return values are passed as arguments for the last function
(old semantics still available with -DLUA_COMPAT_ARGRET)
+ garbage collection tag methods for tables now deprecated.
+ there is now only one tag method for order.
API:
+ New API: fully re-entrant, simpler, and more efficient.
+ New debug API.
Implementation:
+ faster than ever: cleaner virtual machine and new hashing algorithm.
+ non-recursive garbage-collector algorithm.
+ reduced memory usage for programs with many strings.
+ improved treatment for memory allocation errors.
+ improved support for 16-bit machines (we hope).
+ code now compiles unmodified as both ANSI C and C++.
+ numbers in bases other than 10 are converted using strtoul.
+ new -f option in Lua to support #! scripts.
+ luac can now combine text and binaries.
* Changes from version 3.1 to 3.2
-------------------------------
+ redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.
+ increased limit on the number of constants and globals per function
(from 2^16 to 2^24).
+ debugging info (lua_debug and hooks) moved into lua_state and new API
functions provided to get and set this info.
+ new debug lib gives full debugging access within Lua.
+ new table functions "foreachi", "sort", "tinsert", "tremove", "getn".
+ new io functions "flush", "seek".
* Changes from version 3.0 to 3.1
-------------------------------
+ NEW FEATURE: anonymous functions with closures (via "upvalues").
+ new syntax:
- local variables in chunks.
- better scope control with DO block END.
- constructors can now be also written: { record-part; list-part }.
- more general syntax for function calls and lvalues, e.g.:
f(x).y=1
o:f(x,y):g(z)
f"string" is sugar for f("string")
+ strings may now contain arbitrary binary data (e.g., embedded zeros).
+ major code re-organization and clean-up; reduced module interdependecies.
+ no arbitrary limits on the total number of constants and globals.
+ support for multiple global contexts.
+ better syntax error messages.
+ new traversal functions "foreach" and "foreachvar".
+ the default for numbers is now double.
changing it to use floats or longs is easy.
+ complete debug information stored in pre-compiled chunks.
+ sample interpreter now prompts user when run interactively, and also
handles control-C interruptions gracefully.
* Changes from version 2.5 to 3.0
-------------------------------
+ NEW CONCEPT: "tag methods".
Tag methods replace fallbacks as the meta-mechanism for extending the
semantics of Lua. Whereas fallbacks had a global nature, tag methods
work on objects having the same tag (e.g., groups of tables).
Existing code that uses fallbacks should work without change.
+ new, general syntax for constructors {[exp] = exp, ... }.
+ support for handling variable number of arguments in functions (varargs).
+ support for conditional compilation ($if ... $else ... $end).
+ cleaner semantics in API simplifies host code.
+ better support for writing libraries (auxlib.h).
+ better type checking and error messages in the standard library.
+ luac can now also undump.
* Changes from version 2.4 to 2.5
-------------------------------
+ io and string libraries are now based on pattern matching;
the old libraries are still available for compatibility
+ dofile and dostring can now return values (via return statement)
+ better support for 16- and 64-bit machines
+ expanded documentation, with more examples
* Changes from version 2.2 to 2.4
-------------------------------
+ external compiler creates portable binary files that can be loaded faster
+ interface for debugging and profiling
+ new "getglobal" fallback
+ new functions for handling references to Lua objects
+ new functions in standard lib
+ only one copy of each string is stored
+ expanded documentation, with more examples
* Changes from version 2.1 to 2.2
-------------------------------
+ functions now may be declared with any "lvalue" as a name
+ garbage collection of functions
+ support for pipes
* Changes from version 1.1 to 2.1
-------------------------------
+ object-oriented support
+ fallbacks
+ simplified syntax for tables
+ many internal improvements
(end of HISTORY)

View File

@ -0,0 +1,99 @@
INSTALL for Lua 5.1
* Building Lua
------------
Lua is built in the src directory, but the build process can be
controlled from the top-level Makefile.
Building Lua on Unix systems should be very easy. First do "make" and
see if your platform is listed. If so, just do "make xxx", where xxx
is your platform name. The platforms currently supported are:
aix ansi bsd freebsd generic linux macosx mingw posix solaris
If your platform is not listed, try the closest one or posix, generic,
ansi, in this order.
See below for customization instructions and for instructions on how
to build with other Windows compilers.
If you want to check that Lua has been built correctly, do "make test"
after building Lua. Also, have a look at the example programs in test.
* Installing Lua
--------------
Once you have built Lua, you may want to install it in an official
place in your system. In this case, do "make install". The official
place and the way to install files are defined in Makefile. You must
have the right permissions to install files.
If you want to build and install Lua in one step, do "make xxx install",
where xxx is your platform name.
If you want to install Lua locally, then do "make local". This will
create directories bin, include, lib, man, and install Lua there as
follows:
bin: lua luac
include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp
lib: liblua.a
man/man1: lua.1 luac.1
These are the only directories you need for development.
There are man pages for lua and luac, in both nroff and html, and a
reference manual in html in doc, some sample code in test, and some
useful stuff in etc. You don't need these directories for development.
If you want to install Lua locally, but in some other directory, do
"make install INSTALL_TOP=xxx", where xxx is your chosen directory.
See below for instructions for Windows and other systems.
* Customization
-------------
Three things can be customized by editing a file:
- Where and how to install Lua -- edit Makefile.
- How to build Lua -- edit src/Makefile.
- Lua features -- edit src/luaconf.h.
You don't actually need to edit the Makefiles because you may set the
relevant variables when invoking make.
On the other hand, if you need to select some Lua features, you'll need
to edit src/luaconf.h. The edited file will be the one installed, and
it will be used by any Lua clients that you build, to ensure consistency.
We strongly recommend that you enable dynamic loading. This is done
automatically for all platforms listed above that have this feature
(and also Windows). See src/luaconf.h and also src/Makefile.
* Building Lua on Windows and other systems
-----------------------------------------
If you're not using the usual Unix tools, then the instructions for
building Lua depend on the compiler you use. You'll need to create
projects (or whatever your compiler uses) for building the library,
the interpreter, and the compiler, as follows:
library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c
ltable.c ltm.c lundump.c lvm.c lzio.c
lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
ltablib.c lstrlib.c loadlib.c linit.c
interpreter: library, lua.c
compiler: library, luac.c print.c
If you use Visual Studio .NET, you can use etc/luavs.bat in its
"Command Prompt".
If all you want is to build the Lua interpreter, you may put all .c files
in a single project, except for luac.c and print.c. Or just use etc/all.c.
To use Lua as a library in your own programs, you'll need to know how to
create and use libraries with your compiler.
As mentioned above, you may edit luaconf.h to select some features before
building Lua.
(end of INSTALL)

View File

@ -0,0 +1,128 @@
# makefile for installing Lua
# see INSTALL for installation instructions
# see src/Makefile and src/luaconf.h for further customization
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
# Where to install. The installation starts in the src and doc directories,
# so take care if INSTALL_TOP is not an absolute path.
INSTALL_TOP= /usr/local
INSTALL_BIN= $(INSTALL_TOP)/bin
INSTALL_INC= $(INSTALL_TOP)/include
INSTALL_LIB= $(INSTALL_TOP)/lib
INSTALL_MAN= $(INSTALL_TOP)/man/man1
#
# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
# How to install. If your install program does not support "-p", then you
# may have to run ranlib on the installed liblua.a (do "make ranlib").
INSTALL= install -p
INSTALL_EXEC= $(INSTALL) -m 0755
INSTALL_DATA= $(INSTALL) -m 0644
#
# If you don't have install you can use cp instead.
# INSTALL= cp -p
# INSTALL_EXEC= $(INSTALL)
# INSTALL_DATA= $(INSTALL)
# Utilities.
MKDIR= mkdir -p
RANLIB= ranlib
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
# Convenience platforms targets.
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
# What to install.
TO_BIN= lua luac
TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
TO_LIB= liblua.a
TO_MAN= lua.1 luac.1
# Lua version and release.
V= 5.1
R= 5.1.4
all: $(PLAT)
$(PLATS) clean:
cd src && $(MAKE) $@
test: dummy
src/lua test/hello.lua
install: dummy
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
ranlib:
cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)
local:
$(MAKE) install INSTALL_TOP=..
none:
@echo "Please do"
@echo " make PLATFORM"
@echo "where PLATFORM is one of these:"
@echo " $(PLATS)"
@echo "See INSTALL for complete instructions."
# make may get confused with test/ and INSTALL in a case-insensitive OS
dummy:
# echo config parameters
echo:
@echo ""
@echo "These are the parameters currently set in src/Makefile to build Lua $R:"
@echo ""
@cd src && $(MAKE) -s echo
@echo ""
@echo "These are the parameters currently set in Makefile to install Lua $R:"
@echo ""
@echo "PLAT = $(PLAT)"
@echo "INSTALL_TOP = $(INSTALL_TOP)"
@echo "INSTALL_BIN = $(INSTALL_BIN)"
@echo "INSTALL_INC = $(INSTALL_INC)"
@echo "INSTALL_LIB = $(INSTALL_LIB)"
@echo "INSTALL_MAN = $(INSTALL_MAN)"
@echo "INSTALL_LMOD = $(INSTALL_LMOD)"
@echo "INSTALL_CMOD = $(INSTALL_CMOD)"
@echo "INSTALL_EXEC = $(INSTALL_EXEC)"
@echo "INSTALL_DATA = $(INSTALL_DATA)"
@echo ""
@echo "See also src/luaconf.h ."
@echo ""
# echo private config parameters
pecho:
@echo "V = $(V)"
@echo "R = $(R)"
@echo "TO_BIN = $(TO_BIN)"
@echo "TO_INC = $(TO_INC)"
@echo "TO_LIB = $(TO_LIB)"
@echo "TO_MAN = $(TO_MAN)"
# echo config parameters as Lua code
# uncomment the last sed expression if you want nil instead of empty strings
lecho:
@echo "-- installation parameters for Lua $R"
@echo "VERSION = '$V'"
@echo "RELEASE = '$R'"
@$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/'
@echo "-- EOF"
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
# (end of Makefile)

View File

@ -0,0 +1,37 @@
README for Lua 5.1
See INSTALL for installation instructions.
See HISTORY for a summary of changes since the last released 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 is free software.
For complete information, visit Lua's web site at http://www.lua.org/ .
For an executive summary, see http://www.lua.org/about.html .
Lua has been used in many different projects around the world.
For a short list, see http://www.lua.org/uses.html .
* Availability
------------
Lua is freely available for both academic and commercial purposes.
See COPYRIGHT and http://www.lua.org/license.html for details.
Lua can be downloaded at http://www.lua.org/download.html .
* Installation
------------
Lua is implemented in pure ANSI C, and compiles unmodified in all known
platforms that have an ANSI C compiler. In most Unix-like platforms, simply
do "make" with a suitable target. See INSTALL for detailed instructions.
* Origin
------
Lua is developed at Lua.org, a laboratory of the Department of Computer
Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro
in Brazil).
For more information about the authors, see http://www.lua.org/authors.html .
(end of README)

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

View File

@ -0,0 +1,499 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Lua 5.1 Reference Manual - contents</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
<STYLE TYPE="text/css">
ul {
list-style-type: none ;
list-style-position: outside ;
}
</STYLE>
</HEAD>
<BODY>
<HR>
<H1>
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A>
Lua 5.1 Reference Manual
</H1>
This is an online version of
<BLOCKQUOTE>
<A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20">
<IMG SRC="cover.png" ALT="" TITLE="buy from Amazon" BORDER=1 ALIGN="left" HSPACE=12>
</A>
<B>Lua 5.1 Reference Manual</B>
<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes
<BR>Lua.org, August 2006
<BR>ISBN 85-903798-3-3
<BR><A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20">
<IMG SRC="amazon.gif" ALT="[Buy from Amazon]" BORDER=0></A>
<BR CLEAR="all">
</BLOCKQUOTE>
<P>
Buy a copy of this book and
<A HREF="http://www.lua.org/donations.html">help to support</A>
the Lua project.
<P>
The reference manual is the official definition of the Lua language.
For a complete introduction to Lua programming, see the book
<A HREF="http://www.lua.org/docs.html#books">Programming in Lua</A>.
<P>
<A HREF="manual.html">start</A>
&middot;
<A HREF="#contents">contents</A>
&middot;
<A HREF="#index">index</A>
&middot;
<A HREF="http://www.lua.org/manual/5.1/pt/">português</A>
&middot;
<A HREF="http://www.lua.org/manual/5.1/es/">español</A>
<HR>
<SMALL>
Copyright &copy; 2006-2008 Lua.org, PUC-Rio.
Freely available under the terms of the
<a href="http://www.lua.org/license.html#5">Lua license</a>.
</SMALL>
<P>
<H2><A NAME="contents">Contents</A></H2>
<UL style="padding: 0">
<LI><A HREF="manual.html">1 - Introduction</A>
<P>
<LI><A HREF="manual.html#2">2 - The Language</A>
<UL>
<LI><A HREF="manual.html#2.1">2.1 - Lexical Conventions</A>
<LI><A HREF="manual.html#2.2">2.2 - Values and Types</A>
<UL>
<LI><A HREF="manual.html#2.2.1">2.2.1 - Coercion</A>
</UL>
<LI><A HREF="manual.html#2.3">2.3 - Variables</A>
<LI><A HREF="manual.html#2.4">2.4 - Statements</A>
<UL>
<LI><A HREF="manual.html#2.4.1">2.4.1 - Chunks</A>
<LI><A HREF="manual.html#2.4.2">2.4.2 - Blocks</A>
<LI><A HREF="manual.html#2.4.3">2.4.3 - Assignment</A>
<LI><A HREF="manual.html#2.4.4">2.4.4 - Control Structures</A>
<LI><A HREF="manual.html#2.4.5">2.4.5 - For Statement</A>
<LI><A HREF="manual.html#2.4.6">2.4.6 - Function Calls as Statements</A>
<LI><A HREF="manual.html#2.4.7">2.4.7 - Local Declarations</A>
</UL>
<LI><A HREF="manual.html#2.5">2.5 - Expressions</A>
<UL>
<LI><A HREF="manual.html#2.5.1">2.5.1 - Arithmetic Operators</A>
<LI><A HREF="manual.html#2.5.2">2.5.2 - Relational Operators</A>
<LI><A HREF="manual.html#2.5.3">2.5.3 - Logical Operators</A>
<LI><A HREF="manual.html#2.5.4">2.5.4 - Concatenation</A>
<LI><A HREF="manual.html#2.5.5">2.5.5 - The Length Operator</A>
<LI><A HREF="manual.html#2.5.6">2.5.6 - Precedence</A>
<LI><A HREF="manual.html#2.5.7">2.5.7 - Table Constructors</A>
<LI><A HREF="manual.html#2.5.8">2.5.8 - Function Calls</A>
<LI><A HREF="manual.html#2.5.9">2.5.9 - Function Definitions</A>
</UL>
<LI><A HREF="manual.html#2.6">2.6 - Visibility Rules</A>
<LI><A HREF="manual.html#2.7">2.7 - Error Handling</A>
<LI><A HREF="manual.html#2.8">2.8 - Metatables</A>
<LI><A HREF="manual.html#2.9">2.9 - Environments</A>
<LI><A HREF="manual.html#2.10">2.10 - Garbage Collection</A>
<UL>
<LI><A HREF="manual.html#2.10.1">2.10.1 - Garbage-Collection Metamethods</A>
<LI><A HREF="manual.html#2.10.2">2.10.2 - Weak Tables</A>
</UL>
<LI><A HREF="manual.html#2.11">2.11 - Coroutines</A>
</UL>
<P>
<LI><A HREF="manual.html#3">3 - The Application Program Interface</A>
<UL>
<LI><A HREF="manual.html#3.1">3.1 - The Stack</A>
<LI><A HREF="manual.html#3.2">3.2 - Stack Size</A>
<LI><A HREF="manual.html#3.3">3.3 - Pseudo-Indices</A>
<LI><A HREF="manual.html#3.4">3.4 - C Closures</A>
<LI><A HREF="manual.html#3.5">3.5 - Registry</A>
<LI><A HREF="manual.html#3.6">3.6 - Error Handling in C</A>
<LI><A HREF="manual.html#3.7">3.7 - Functions and Types</A>
<LI><A HREF="manual.html#3.8">3.8 - The Debug Interface</A>
</UL>
<P>
<LI><A HREF="manual.html#4">4 - The Auxiliary Library</A>
<UL>
<LI><A HREF="manual.html#4.1">4.1 - Functions and Types</A>
</UL>
<P>
<LI><A HREF="manual.html#5">5 - Standard Libraries</A>
<UL>
<LI><A HREF="manual.html#5.1">5.1 - Basic Functions</A>
<LI><A HREF="manual.html#5.2">5.2 - Coroutine Manipulation</A>
<LI><A HREF="manual.html#5.3">5.3 - Modules</A>
<LI><A HREF="manual.html#5.4">5.4 - String Manipulation</A>
<UL>
<LI><A HREF="manual.html#5.4.1">5.4.1 - Patterns</A>
</UL>
<LI><A HREF="manual.html#5.5">5.5 - Table Manipulation</A>
<LI><A HREF="manual.html#5.6">5.6 - Mathematical Functions</A>
<LI><A HREF="manual.html#5.7">5.7 - Input and Output Facilities</A>
<LI><A HREF="manual.html#5.8">5.8 - Operating System Facilities</A>
<LI><A HREF="manual.html#5.9">5.9 - The Debug Library</A>
</UL>
<P>
<LI><A HREF="manual.html#6">6 - Lua Stand-alone</A>
<P>
<LI><A HREF="manual.html#7">7 - Incompatibilities with the Previous Version</A>
<UL>
<LI><A HREF="manual.html#7.1">7.1 - Changes in the Language</A>
<LI><A HREF="manual.html#7.2">7.2 - Changes in the Libraries</A>
<LI><A HREF="manual.html#7.3">7.3 - Changes in the API</A>
</UL>
<P>
<LI><A HREF="manual.html#8">8 - The Complete Syntax of Lua</A>
</UL>
<H2><A NAME="index">Index</A></H2>
<TABLE WIDTH="100%">
<TR VALIGN="top">
<TD>
<H3><A NAME="functions">Lua functions</A></H3>
<A HREF="manual.html#pdf-_G">_G</A><BR>
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
<A HREF="manual.html#pdf-assert">assert</A><BR>
<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR>
<A HREF="manual.html#pdf-dofile">dofile</A><BR>
<A HREF="manual.html#pdf-error">error</A><BR>
<A HREF="manual.html#pdf-getfenv">getfenv</A><BR>
<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR>
<A HREF="manual.html#pdf-ipairs">ipairs</A><BR>
<A HREF="manual.html#pdf-load">load</A><BR>
<A HREF="manual.html#pdf-loadfile">loadfile</A><BR>
<A HREF="manual.html#pdf-loadstring">loadstring</A><BR>
<A HREF="manual.html#pdf-module">module</A><BR>
<A HREF="manual.html#pdf-next">next</A><BR>
<A HREF="manual.html#pdf-pairs">pairs</A><BR>
<A HREF="manual.html#pdf-pcall">pcall</A><BR>
<A HREF="manual.html#pdf-print">print</A><BR>
<A HREF="manual.html#pdf-rawequal">rawequal</A><BR>
<A HREF="manual.html#pdf-rawget">rawget</A><BR>
<A HREF="manual.html#pdf-rawset">rawset</A><BR>
<A HREF="manual.html#pdf-require">require</A><BR>
<A HREF="manual.html#pdf-select">select</A><BR>
<A HREF="manual.html#pdf-setfenv">setfenv</A><BR>
<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR>
<A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
<A HREF="manual.html#pdf-tostring">tostring</A><BR>
<A HREF="manual.html#pdf-type">type</A><BR>
<A HREF="manual.html#pdf-unpack">unpack</A><BR>
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
<P>
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR>
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
<P>
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
<A HREF="manual.html#pdf-debug.getfenv">debug.getfenv</A><BR>
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
<A HREF="manual.html#pdf-debug.setfenv">debug.setfenv</A><BR>
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
</TD>
<TD>
<H3>&nbsp;</H3>
<A HREF="manual.html#pdf-file:close">file:close</A><BR>
<A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
<A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
<A HREF="manual.html#pdf-file:read">file:read</A><BR>
<A HREF="manual.html#pdf-file:seek">file:seek</A><BR>
<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR>
<A HREF="manual.html#pdf-file:write">file:write</A><BR>
<P>
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
<A HREF="manual.html#pdf-io.lines">io.lines</A><BR>
<A HREF="manual.html#pdf-io.open">io.open</A><BR>
<A HREF="manual.html#pdf-io.output">io.output</A><BR>
<A HREF="manual.html#pdf-io.popen">io.popen</A><BR>
<A HREF="manual.html#pdf-io.read">io.read</A><BR>
<A HREF="manual.html#pdf-io.stderr">io.stderr</A><BR>
<A HREF="manual.html#pdf-io.stdin">io.stdin</A><BR>
<A HREF="manual.html#pdf-io.stdout">io.stdout</A><BR>
<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
<A HREF="manual.html#pdf-io.type">io.type</A><BR>
<A HREF="manual.html#pdf-io.write">io.write</A><BR>
<P>
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR>
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR>
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
<A HREF="manual.html#pdf-math.log10">math.log10</A><BR>
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
<A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
<A HREF="manual.html#pdf-math.pow">math.pow</A><BR>
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR>
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR>
<P>
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
<A HREF="manual.html#pdf-os.execute">os.execute</A><BR>
<A HREF="manual.html#pdf-os.exit">os.exit</A><BR>
<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR>
<A HREF="manual.html#pdf-os.remove">os.remove</A><BR>
<A HREF="manual.html#pdf-os.rename">os.rename</A><BR>
<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR>
<A HREF="manual.html#pdf-os.time">os.time</A><BR>
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
<P>
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
<A HREF="manual.html#pdf-package.loaders">package.loaders</A><BR>
<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR>
<A HREF="manual.html#pdf-package.path">package.path</A><BR>
<A HREF="manual.html#pdf-package.preload">package.preload</A><BR>
<A HREF="manual.html#pdf-package.seeall">package.seeall</A><BR>
<P>
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR>
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
<P>
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
<A HREF="manual.html#pdf-table.maxn">table.maxn</A><BR>
<A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
<A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
</TD>
<TD>
<H3>C API</H3>
<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
<A HREF="manual.html#lua_State">lua_State</A><BR>
<A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
<P>
<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR>
<A HREF="manual.html#lua_call">lua_call</A><BR>
<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR>
<A HREF="manual.html#lua_close">lua_close</A><BR>
<A HREF="manual.html#lua_concat">lua_concat</A><BR>
<A HREF="manual.html#lua_cpcall">lua_cpcall</A><BR>
<A HREF="manual.html#lua_createtable">lua_createtable</A><BR>
<A HREF="manual.html#lua_dump">lua_dump</A><BR>
<A HREF="manual.html#lua_equal">lua_equal</A><BR>
<A HREF="manual.html#lua_error">lua_error</A><BR>
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
<A HREF="manual.html#lua_getfenv">lua_getfenv</A><BR>
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
<A HREF="manual.html#lua_getstack">lua_getstack</A><BR>
<A HREF="manual.html#lua_gettable">lua_gettable</A><BR>
<A HREF="manual.html#lua_gettop">lua_gettop</A><BR>
<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR>
<A HREF="manual.html#lua_insert">lua_insert</A><BR>
<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
<A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
<A HREF="manual.html#lua_isnone">lua_isnone</A><BR>
<A HREF="manual.html#lua_isnoneornil">lua_isnoneornil</A><BR>
<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR>
<A HREF="manual.html#lua_isstring">lua_isstring</A><BR>
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
<A HREF="manual.html#lua_lessthan">lua_lessthan</A><BR>
<A HREF="manual.html#lua_load">lua_load</A><BR>
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
<A HREF="manual.html#lua_newtable">lua_newtable</A><BR>
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
<A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR>
<A HREF="manual.html#lua_next">lua_next</A><BR>
<A HREF="manual.html#lua_objlen">lua_objlen</A><BR>
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR>
<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR>
<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR>
<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR>
<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR>
<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR>
<A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR>
<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR>
<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR>
<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
<A HREF="manual.html#lua_rawget">lua_rawget</A><BR>
<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR>
<A HREF="manual.html#lua_rawset">lua_rawset</A><BR>
<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR>
<A HREF="manual.html#lua_register">lua_register</A><BR>
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
<A HREF="manual.html#lua_setfenv">lua_setfenv</A><BR>
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
<A HREF="manual.html#lua_settable">lua_settable</A><BR>
<A HREF="manual.html#lua_settop">lua_settop</A><BR>
<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
<A HREF="manual.html#lua_status">lua_status</A><BR>
<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>
<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR>
<A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
<A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
<A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
<A HREF="manual.html#lua_type">lua_type</A><BR>
<A HREF="manual.html#lua_typename">lua_typename</A><BR>
<A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR>
<A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
<A HREF="manual.html#lua_yield">lua_yield</A><BR>
</TD>
<TD>
<H3>auxiliary library</H3>
<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
<P>
<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR>
<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
<A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR>
<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR>
<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
<A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR>
<A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR>
<A HREF="manual.html#luaL_error">luaL_error</A><BR>
<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR>
<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR>
<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR>
<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR>
<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR>
<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR>
<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
<A HREF="manual.html#luaL_optint">luaL_optint</A><BR>
<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
<A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR>
<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
<A HREF="manual.html#luaL_ref">luaL_ref</A><BR>
<A HREF="manual.html#luaL_register">luaL_register</A><BR>
<A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
<A HREF="manual.html#luaL_typerror">luaL_typerror</A><BR>
<A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
<A HREF="manual.html#luaL_where">luaL_where</A><BR>
</TD>
</TR>
</TABLE>
<P>
<HR>
<SMALL>
Last update:
Sat Jan 19 13:24:29 BRST 2008
</SMALL>
<!--
Last change: revised for Lua 5.1.3
-->
</BODY>
</HTML>

BIN
build/premake/premake4/src/host/lua-5.1.4/doc/cover.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,163 @@
.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
lua \- Lua interpreter
.SH SYNOPSIS
.B lua
[
.I options
]
[
.I script
[
.I args
]
]
.SH DESCRIPTION
.B lua
is the stand-alone Lua interpreter.
It loads and executes Lua programs,
either in textual source form or
in precompiled binary form.
(Precompiled binaries are output by
.BR luac ,
the Lua compiler.)
.B lua
can be used as a batch interpreter and also interactively.
.LP
The given
.I options
(see below)
are executed and then
the Lua program in file
.I script
is loaded and executed.
The given
.I args
are available to
.I script
as strings in a global table named
.BR arg .
If these arguments contain spaces or other characters special to the shell,
then they should be quoted
(but note that the quotes will be removed by the shell).
The arguments in
.B arg
start at 0,
which contains the string
.RI ' script '.
The index of the last argument is stored in
.BR arg.n .
The arguments given in the command line before
.IR script ,
including the name of the interpreter,
are available in negative indices in
.BR arg .
.LP
At the very start,
before even handling the command line,
.B lua
executes the contents of the environment variable
.BR LUA_INIT ,
if it is defined.
If the value of
.B LUA_INIT
is of the form
.RI '@ filename ',
then
.I filename
is executed.
Otherwise, the string is assumed to be a Lua statement and is executed.
.LP
Options start with
.B '\-'
and are described below.
You can use
.B "'\--'"
to signal the end of options.
.LP
If no arguments are given,
then
.B "\-v \-i"
is assumed when the standard input is a terminal;
otherwise,
.B "\-"
is assumed.
.LP
In interactive mode,
.B lua
prompts the user,
reads lines from the standard input,
and executes them as they are read.
If a line does not contain a complete statement,
then a secondary prompt is displayed and
lines are read until a complete statement is formed or
a syntax error is found.
So, one way to interrupt the reading of an incomplete statement is
to force a syntax error:
adding a
.B ';'
in the middle of a statement is a sure way of forcing a syntax error
(except inside multiline strings and comments; these must be closed explicitly).
If a line starts with
.BR '=' ,
then
.B lua
displays the values of all the expressions in the remainder of the
line. The expressions must be separated by commas.
The primary prompt is the value of the global variable
.BR _PROMPT ,
if this value is a string;
otherwise, the default prompt is used.
Similarly, the secondary prompt is the value of the global variable
.BR _PROMPT2 .
So,
to change the prompts,
set the corresponding variable to a string of your choice.
You can do that after calling the interpreter
or on the command line
(but in this case you have to be careful with quotes
if the prompt string contains a space; otherwise you may confuse the shell.)
The default prompts are "> " and ">> ".
.SH OPTIONS
.TP
.B \-
load and execute the standard input as a file,
that is,
not interactively,
even when the standard input is a terminal.
.TP
.BI \-e " stat"
execute statement
.IR stat .
You need to quote
.I stat
if it contains spaces, quotes,
or other characters special to the shell.
.TP
.B \-i
enter interactive mode after
.I script
is executed.
.TP
.BI \-l " name"
call
.BI require(' name ')
before executing
.IR script .
Typically used to load libraries.
.TP
.B \-v
show version information.
.SH "SEE ALSO"
.BR luac (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
R. Ierusalimschy,
L. H. de Figueiredo,
and
W. Celes
.\" EOF

View File

@ -0,0 +1,41 @@
body {
color: #000000 ;
background-color: #FFFFFF ;
font-family: sans-serif ;
text-align: justify ;
margin-right: 20px ;
margin-left: 20px ;
}
h1, h2, h3, h4 {
font-weight: normal ;
font-style: italic ;
}
a:link {
color: #000080 ;
background-color: inherit ;
text-decoration: none ;
}
a:visited {
background-color: inherit ;
text-decoration: none ;
}
a:link:hover, a:visited:hover {
color: #000080 ;
background-color: #E0E0FF ;
}
a:link:active, a:visited:active {
color: #FF0000 ;
}
hr {
border: 0 ;
height: 1px ;
color: #a0a0a0 ;
background-color: #a0a0a0 ;
}

View File

@ -0,0 +1,172 @@
<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->
<HTML>
<HEAD>
<TITLE>LUA man page</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<H2>NAME</H2>
lua - Lua interpreter
<H2>SYNOPSIS</H2>
<B>lua</B>
[
<I>options</I>
]
[
<I>script</I>
[
<I>args</I>
]
]
<H2>DESCRIPTION</H2>
<B>lua</B>
is the stand-alone Lua interpreter.
It loads and executes Lua programs,
either in textual source form or
in precompiled binary form.
(Precompiled binaries are output by
<B>luac</B>,
the Lua compiler.)
<B>lua</B>
can be used as a batch interpreter and also interactively.
<P>
The given
<I>options</I>
(see below)
are executed and then
the Lua program in file
<I>script</I>
is loaded and executed.
The given
<I>args</I>
are available to
<I>script</I>
as strings in a global table named
<B>arg</B>.
If these arguments contain spaces or other characters special to the shell,
then they should be quoted
(but note that the quotes will be removed by the shell).
The arguments in
<B>arg</B>
start at 0,
which contains the string
'<I>script</I>'.
The index of the last argument is stored in
<B>arg.n</B>.
The arguments given in the command line before
<I>script</I>,
including the name of the interpreter,
are available in negative indices in
<B>arg</B>.
<P>
At the very start,
before even handling the command line,
<B>lua</B>
executes the contents of the environment variable
<B>LUA_INIT</B>,
if it is defined.
If the value of
<B>LUA_INIT</B>
is of the form
'@<I>filename</I>',
then
<I>filename</I>
is executed.
Otherwise, the string is assumed to be a Lua statement and is executed.
<P>
Options start with
<B>'-'</B>
and are described below.
You can use
<B>'--'</B>
to signal the end of options.
<P>
If no arguments are given,
then
<B>"-v -i"</B>
is assumed when the standard input is a terminal;
otherwise,
<B>"-"</B>
is assumed.
<P>
In interactive mode,
<B>lua</B>
prompts the user,
reads lines from the standard input,
and executes them as they are read.
If a line does not contain a complete statement,
then a secondary prompt is displayed and
lines are read until a complete statement is formed or
a syntax error is found.
So, one way to interrupt the reading of an incomplete statement is
to force a syntax error:
adding a
<B>';'</B>
in the middle of a statement is a sure way of forcing a syntax error
(except inside multiline strings and comments; these must be closed explicitly).
If a line starts with
<B>'='</B>,
then
<B>lua</B>
displays the values of all the expressions in the remainder of the
line. The expressions must be separated by commas.
The primary prompt is the value of the global variable
<B>_PROMPT</B>,
if this value is a string;
otherwise, the default prompt is used.
Similarly, the secondary prompt is the value of the global variable
<B>_PROMPT2</B>.
So,
to change the prompts,
set the corresponding variable to a string of your choice.
You can do that after calling the interpreter
or on the command line
(but in this case you have to be careful with quotes
if the prompt string contains a space; otherwise you may confuse the shell.)
The default prompts are "&gt; " and "&gt;&gt; ".
<H2>OPTIONS</H2>
<P>
<B>-</B>
load and execute the standard input as a file,
that is,
not interactively,
even when the standard input is a terminal.
<P>
<B>-e </B><I>stat</I>
execute statement
<I>stat</I>.
You need to quote
<I>stat </I>
if it contains spaces, quotes,
or other characters special to the shell.
<P>
<B>-i</B>
enter interactive mode after
<I>script</I>
is executed.
<P>
<B>-l </B><I>name</I>
call
<B>require</B>('<I>name</I>')
before executing
<I>script</I>.
Typically used to load libraries.
<P>
<B>-v</B>
show version information.
<H2>SEE ALSO</H2>
<B>luac</B>(1)
<BR>
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
<H2>DIAGNOSTICS</H2>
Error messages should be self explanatory.
<H2>AUTHORS</H2>
R. Ierusalimschy,
L. H. de Figueiredo,
and
W. Celes
<!-- EOF -->
</BODY>
</HTML>

View File

@ -0,0 +1,136 @@
.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
luac \- Lua compiler
.SH SYNOPSIS
.B luac
[
.I options
] [
.I filenames
]
.SH DESCRIPTION
.B luac
is the Lua compiler.
It translates programs written in the Lua programming language
into binary files that can be later loaded and executed.
.LP
The main advantages of precompiling chunks are:
faster loading,
protecting source code from accidental user changes,
and
off-line syntax checking.
.LP
Pre-compiling does not imply faster execution
because in Lua chunks are always compiled into bytecodes before being executed.
.B luac
simply allows those bytecodes to be saved in a file for later execution.
.LP
Pre-compiled chunks are not necessarily smaller than the corresponding source.
The main goal in pre-compiling is faster loading.
.LP
The binary files created by
.B luac
are portable only among architectures with the same word size and byte order.
.LP
.B luac
produces a single output file containing the bytecodes
for all source files given.
By default,
the output file is named
.BR luac.out ,
but you can change this with the
.B \-o
option.
.LP
In the command line,
you can mix
text files containing Lua source and
binary files containing precompiled chunks.
This is useful to combine several precompiled chunks,
even from different (but compatible) platforms,
into a single precompiled chunk.
.LP
You can use
.B "'\-'"
to indicate the standard input as a source file
and
.B "'\--'"
to signal the end of options
(that is,
all remaining arguments will be treated as files even if they start with
.BR "'\-'" ).
.LP
The internal format of the binary files produced by
.B luac
is likely to change when a new version of Lua is released.
So,
save the source files of all Lua programs that you precompile.
.LP
.SH OPTIONS
Options must be separate.
.TP
.B \-l
produce a listing of the compiled bytecode for Lua's virtual machine.
Listing bytecodes is useful to learn about Lua's virtual machine.
If no files are given, then
.B luac
loads
.B luac.out
and lists its contents.
.TP
.BI \-o " file"
output to
.IR file ,
instead of the default
.BR luac.out .
(You can use
.B "'\-'"
for standard output,
but not on platforms that open standard output in text mode.)
The output file may be a source file because
all files are loaded before the output file is written.
Be careful not to overwrite precious files.
.TP
.B \-p
load files but do not generate any output file.
Used mainly for syntax checking and for testing precompiled chunks:
corrupted files will probably generate errors when loaded.
Lua always performs a thorough integrity test on precompiled chunks.
Bytecode that passes this test is completely safe,
in the sense that it will not break the interpreter.
However,
there is no guarantee that such code does anything sensible.
(None can be given, because the halting problem is unsolvable.)
If no files are given, then
.B luac
loads
.B luac.out
and tests its contents.
No messages are displayed if the file passes the integrity test.
.TP
.B \-s
strip debug information before writing the output file.
This saves some space in very large chunks,
but if errors occur when running a stripped chunk,
then the error messages may not contain the full information they usually do.
For instance,
line numbers and names of local variables are lost.
.TP
.B \-v
show version information.
.SH FILES
.TP 15
.B luac.out
default output file
.SH "SEE ALSO"
.BR lua (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
L. H. de Figueiredo,
R. Ierusalimschy and
W. Celes
.\" EOF

View File

@ -0,0 +1,145 @@
<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->
<HTML>
<HEAD>
<TITLE>LUAC man page</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<H2>NAME</H2>
luac - Lua compiler
<H2>SYNOPSIS</H2>
<B>luac</B>
[
<I>options</I>
] [
<I>filenames</I>
]
<H2>DESCRIPTION</H2>
<B>luac</B>
is the Lua compiler.
It translates programs written in the Lua programming language
into binary files that can be later loaded and executed.
<P>
The main advantages of precompiling chunks are:
faster loading,
protecting source code from accidental user changes,
and
off-line syntax checking.
<P>
Precompiling does not imply faster execution
because in Lua chunks are always compiled into bytecodes before being executed.
<B>luac</B>
simply allows those bytecodes to be saved in a file for later execution.
<P>
Precompiled chunks are not necessarily smaller than the corresponding source.
The main goal in precompiling is faster loading.
<P>
The binary files created by
<B>luac</B>
are portable only among architectures with the same word size and byte order.
<P>
<B>luac</B>
produces a single output file containing the bytecodes
for all source files given.
By default,
the output file is named
<B>luac.out</B>,
but you can change this with the
<B>-o</B>
option.
<P>
In the command line,
you can mix
text files containing Lua source and
binary files containing precompiled chunks.
This is useful because several precompiled chunks,
even from different (but compatible) platforms,
can be combined into a single precompiled chunk.
<P>
You can use
<B>'-'</B>
to indicate the standard input as a source file
and
<B>'--'</B>
to signal the end of options
(that is,
all remaining arguments will be treated as files even if they start with
<B>'-'</B>).
<P>
The internal format of the binary files produced by
<B>luac</B>
is likely to change when a new version of Lua is released.
So,
save the source files of all Lua programs that you precompile.
<P>
<H2>OPTIONS</H2>
Options must be separate.
<P>
<B>-l</B>
produce a listing of the compiled bytecode for Lua's virtual machine.
Listing bytecodes is useful to learn about Lua's virtual machine.
If no files are given, then
<B>luac</B>
loads
<B>luac.out</B>
and lists its contents.
<P>
<B>-o </B><I>file</I>
output to
<I>file</I>,
instead of the default
<B>luac.out</B>.
(You can use
<B>'-'</B>
for standard output,
but not on platforms that open standard output in text mode.)
The output file may be a source file because
all files are loaded before the output file is written.
Be careful not to overwrite precious files.
<P>
<B>-p</B>
load files but do not generate any output file.
Used mainly for syntax checking and for testing precompiled chunks:
corrupted files will probably generate errors when loaded.
Lua always performs a thorough integrity test on precompiled chunks.
Bytecode that passes this test is completely safe,
in the sense that it will not break the interpreter.
However,
there is no guarantee that such code does anything sensible.
(None can be given, because the halting problem is unsolvable.)
If no files are given, then
<B>luac</B>
loads
<B>luac.out</B>
and tests its contents.
No messages are displayed if the file passes the integrity test.
<P>
<B>-s</B>
strip debug information before writing the output file.
This saves some space in very large chunks,
but if errors occur when running a stripped chunk,
then the error messages may not contain the full information they usually do.
For instance,
line numbers and names of local variables are lost.
<P>
<B>-v</B>
show version information.
<H2>FILES</H2>
<P>
<B>luac.out</B>
default output file
<H2>SEE ALSO</H2>
<B>lua</B>(1)
<BR>
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
<H2>DIAGNOSTICS</H2>
Error messages should be self explanatory.
<H2>AUTHORS</H2>
L. H. de Figueiredo,
R. Ierusalimschy and
W. Celes
<!-- EOF -->
</BODY>
</HTML>

View File

@ -0,0 +1,13 @@
h3 code {
font-family: inherit ;
}
pre {
font-size: 105% ;
}
span.apii {
float: right ;
font-family: inherit ;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
<HTML>
<HEAD>
<TITLE>Lua documentation</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
</HEAD>
<BODY>
<HR>
<H1>
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A>
Documentation
</H1>
This is the documentation included in the source distribution of Lua 5.1.4.
<UL>
<LI><A HREF="contents.html">Reference manual</A>
<LI><A HREF="lua.html">lua man page</A>
<LI><A HREF="luac.html">luac man page</A>
<LI><A HREF="../README">lua/README</A>
<LI><A HREF="../etc/README">lua/etc/README</A>
<LI><A HREF="../test/README">lua/test/README</A>
</UL>
Lua's
<A HREF="http://www.lua.org/">official web site</A>
contains updated documentation,
especially the
<A HREF="http://www.lua.org/manual/5.1/">reference manual</A>.
<P>
<HR>
<SMALL>
Last update:
Tue Aug 12 14:46:07 BRT 2008
</SMALL>
</BODY>
</HTML>

View File

@ -0,0 +1,44 @@
# makefile for Lua etc
TOP= ..
LIB= $(TOP)/src
INC= $(TOP)/src
BIN= $(TOP)/src
SRC= $(TOP)/src
TST= $(TOP)/test
CC= gcc
CFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS)
MYCFLAGS=
MYLDFLAGS= -Wl,-E
MYLIBS= -lm
#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses
RM= rm -f
default:
@echo 'Please choose a target: min noparser one strict clean'
min: min.c
$(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS)
echo 'print"Hello there!"' | ./a.out
noparser: noparser.o
$(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS)
$(BIN)/luac $(TST)/hello.lua
-./a.out luac.out
-./a.out -e'a=1'
one:
$(CC) $(CFLAGS) all.c $(MYLIBS)
./a.out $(TST)/hello.lua
strict:
-$(BIN)/lua -e 'print(a);b=2'
-$(BIN)/lua -lstrict -e 'print(a)'
-$(BIN)/lua -e 'function f() b=2 end f()'
-$(BIN)/lua -lstrict -e 'function f() b=2 end f()'
clean:
$(RM) a.out core core.* *.o luac.out
.PHONY: default min noparser one strict clean

View File

@ -0,0 +1,37 @@
This directory contains some useful files and code.
Unlike the code in ../src, everything here is in the public domain.
If any of the makes fail, you're probably not using the same libraries
used to build Lua. Set MYLIBS in Makefile accordingly.
all.c
Full Lua interpreter in a single file.
Do "make one" for a demo.
lua.hpp
Lua header files for C++ using 'extern "C"'.
lua.ico
A Lua icon for Windows (and web sites: save as favicon.ico).
Drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.
lua.pc
pkg-config data for Lua
luavs.bat
Script to build Lua under "Visual Studio .NET Command Prompt".
Run it from the toplevel as etc\luavs.bat.
min.c
A minimal Lua interpreter.
Good for learning and for starting your own.
Do "make min" for a demo.
noparser.c
Linking with noparser.o avoids loading the parsing modules in lualib.a.
Do "make noparser" for a demo.
strict.lua
Traps uses of undeclared global variables.
Do "make strict" for a demo.

View File

@ -0,0 +1,38 @@
/*
* all.c -- Lua core, libraries and interpreter in a single file
*/
#define luaall_c
#include "lapi.c"
#include "lcode.c"
#include "ldebug.c"
#include "ldo.c"
#include "ldump.c"
#include "lfunc.c"
#include "lgc.c"
#include "llex.c"
#include "lmem.c"
#include "lobject.c"
#include "lopcodes.c"
#include "lparser.c"
#include "lstate.c"
#include "lstring.c"
#include "ltable.c"
#include "ltm.c"
#include "lundump.c"
#include "lvm.c"
#include "lzio.c"
#include "lauxlib.c"
#include "lbaselib.c"
#include "ldblib.c"
#include "liolib.c"
#include "linit.c"
#include "lmathlib.c"
#include "loadlib.c"
#include "loslib.c"
#include "lstrlib.c"
#include "ltablib.c"
#include "lua.c"

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,31 @@
# lua.pc -- pkg-config data for Lua
# vars from install Makefile
# grep '^V=' ../Makefile
V= 5.1
# grep '^R=' ../Makefile
R= 5.1.4
# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'
prefix= /usr/local
INSTALL_BIN= ${prefix}/bin
INSTALL_INC= ${prefix}/include
INSTALL_LIB= ${prefix}/lib
INSTALL_MAN= ${prefix}/man/man1
INSTALL_LMOD= ${prefix}/share/lua/${V}
INSTALL_CMOD= ${prefix}/lib/lua/${V}
# canonical vars
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: Lua
Description: An Extensible Extension Language
Version: ${R}
Requires:
Libs: -L${libdir} -llua -lm
Cflags: -I${includedir}
# (end of lua.pc)

View File

@ -0,0 +1,28 @@
@rem Script to build Lua under "Visual Studio .NET Command Prompt".
@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat .
@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.
@rem (contributed by David Manura and Mike Pall)
@setlocal
@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE
@set MYLINK=link /nologo
@set MYMT=mt /nologo
cd src
%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c
del lua.obj luac.obj
%MYLINK% /DLL /out:lua51.dll l*.obj
if exist lua51.dll.manifest^
%MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2
%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c
%MYLINK% /out:lua.exe lua.obj lua51.lib
if exist lua.exe.manifest^
%MYMT% -manifest lua.exe.manifest -outputresource:lua.exe
%MYCOMPILE% l*.c print.c
del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^
loslib.obj ltablib.obj lstrlib.obj loadlib.obj
%MYLINK% /out:luac.exe *.obj
if exist luac.exe.manifest^
%MYMT% -manifest luac.exe.manifest -outputresource:luac.exe
del *.obj *.manifest
cd ..

View File

@ -0,0 +1,39 @@
/*
* min.c -- a minimal Lua interpreter
* loads stdin only with minimal error handling.
* no interaction, and no standard library, only a "print" function.
*/
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
static int print(lua_State *L)
{
int n=lua_gettop(L);
int i;
for (i=1; i<=n; i++)
{
if (i>1) printf("\t");
if (lua_isstring(L,i))
printf("%s",lua_tostring(L,i));
else if (lua_isnil(L,i))
printf("%s","nil");
else if (lua_isboolean(L,i))
printf("%s",lua_toboolean(L,i) ? "true" : "false");
else
printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
}
printf("\n");
return 0;
}
int main(void)
{
lua_State *L=lua_open();
lua_register(L,"print",print);
if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
lua_close(L);
return 0;
}

View File

@ -0,0 +1,50 @@
/*
* The code below can be used to make a Lua core that does not contain the
* parsing modules (lcode, llex, lparser), which represent 35% of the total core.
* You'll only be able to load binary files and strings, precompiled with luac.
* (Of course, you'll have to build luac with the original parsing modules!)
*
* To use this module, simply compile it ("make noparser" does that) and list
* its object file before the Lua libraries. The linker should then not load
* the parsing modules. To try it, do "make luab".
*
* If you also want to avoid the dump module (ldump.o), define NODUMP.
* #define NODUMP
*/
#define LUA_CORE
#include "llex.h"
#include "lparser.h"
#include "lzio.h"
LUAI_FUNC void luaX_init (lua_State *L) {
UNUSED(L);
}
LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
UNUSED(z);
UNUSED(buff);
UNUSED(name);
lua_pushliteral(L,"parser not loaded");
lua_error(L);
return NULL;
}
#ifdef NODUMP
#include "lundump.h"
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) {
UNUSED(f);
UNUSED(w);
UNUSED(data);
UNUSED(strip);
#if 1
UNUSED(L);
return 0;
#else
lua_pushliteral(L,"dumper not loaded");
lua_error(L);
#endif
}
#endif

View File

@ -0,0 +1,41 @@
--
-- strict.lua
-- checks uses of undeclared global variables
-- All global variables must be 'declared' through a regular assignment
-- (even assigning nil will do) in a main chunk before being used
-- anywhere or assigned to inside a function.
--
local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
mt.__declared = {}
local function what ()
local d = getinfo(3, "S")
return d and d.what or "C"
end
mt.__newindex = function (t, n, v)
if not mt.__declared[n] then
local w = what()
if w ~= "main" and w ~= "C" then
error("assign to undeclared variable '"..n.."'", 2)
end
mt.__declared[n] = true
end
rawset(t, n, v)
end
mt.__index = function (t, n)
if not mt.__declared[n] and what() ~= "C" then
error("variable '"..n.."' is not declared", 2)
end
return rawget(t, n)
end

View File

@ -0,0 +1,182 @@
# makefile for building Lua
# see ../INSTALL for installation instructions
# see ../Makefile and luaconf.h for further customization
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
CC= gcc
CFLAGS= -O2 -Wall $(MYCFLAGS)
AR= ar rcu
RANLIB= ranlib
RM= rm -f
LIBS= -lm $(MYLIBS)
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
LUA_A= liblua.a
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
lundump.o lvm.o lzio.o
LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
lstrlib.o loadlib.o linit.o
LUA_T= lua
LUA_O= lua.o
LUAC_T= luac
LUAC_O= luac.o print.o
ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
default: $(PLAT)
all: $(ALL_T)
o: $(ALL_O)
a: $(ALL_A)
$(LUA_A): $(CORE_O) $(LIB_O)
$(AR) $@ $?
$(RANLIB) $@
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
$(LUAC_T): $(LUAC_O) $(LUA_A)
$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
clean:
$(RM) $(ALL_T) $(ALL_O)
depend:
@$(CC) $(CFLAGS) -MM l*.c print.c
echo:
@echo "PLAT = $(PLAT)"
@echo "CC = $(CC)"
@echo "CFLAGS = $(CFLAGS)"
@echo "AR = $(AR)"
@echo "RANLIB = $(RANLIB)"
@echo "RM = $(RM)"
@echo "MYCFLAGS = $(MYCFLAGS)"
@echo "MYLDFLAGS = $(MYLDFLAGS)"
@echo "MYLIBS = $(MYLIBS)"
# convenience targets for popular platforms
none:
@echo "Please choose a platform:"
@echo " $(PLATS)"
aix:
$(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall"
ansi:
$(MAKE) all MYCFLAGS=-DLUA_ANSI
bsd:
$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
freebsd:
$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
generic:
$(MAKE) all MYCFLAGS=
linux:
$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
macosx:
$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
# use this on Mac OS X 10.3-
# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
mingw:
$(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
"MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe
$(MAKE) "LUAC_T=luac.exe" luac.exe
posix:
$(MAKE) all MYCFLAGS=-DLUA_USE_POSIX
solaris:
$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl"
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all $(PLATS) default o a clean depend echo none
# DO NOT DELETE
lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \
lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \
lundump.h lvm.h
lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \
ltable.h
ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \
llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \
lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \
ltable.h lundump.h lvm.h
ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \
lstate.h ltm.h lzio.h
lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \
lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h
lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
ltm.h lzio.h lmem.h ldo.h
loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \
lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h
lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
ltm.h lzio.h lstring.h lgc.h
lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h
ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
lmem.h lstring.h lgc.h ltable.h
lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \
lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \
lundump.h
lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h
lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
lzio.h
print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
ltm.h lzio.h lmem.h lopcodes.h lundump.h
# (end of Makefile)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
/*
** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "lobject.h"
LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
#endif

View File

@ -0,0 +1,652 @@
/*
** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* This file uses only the official API of Lua.
** Any function declared here could be written as an application function.
*/
#define lauxlib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#define FREELIST_REF 0 /* free list of references */
/* 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;
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
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 " LUA_QS " on bad self (%s)",
ar.name, extramsg);
}
if (ar.name == NULL)
ar.name = "?";
return luaL_error(L, "bad argument #%d to " LUA_QS " (%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, luaL_typename(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, "Sl", &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_checkoption (lua_State *L, int narg, const char *def,
const char *const lst[]) {
const char *name = (def) ? luaL_optstring(L, narg, def) :
luaL_checkstring(L, narg);
int i;
for (i=0; lst[i]; i++)
if (strcmp(lst[i], name) == 0)
return i;
return luaL_argerror(L, narg,
lua_pushfstring(L, "invalid option " LUA_QS, name));
}
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* 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_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
return 1;
}
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
void *p = lua_touserdata(L, ud);
if (p != NULL) { /* value is a userdata? */
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
lua_pop(L, 2); /* remove both metatables */
return p;
}
}
}
luaL_typerror(L, ud, tname); /* else error */
return NULL; /* to avoid warnings */
}
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_tolstring(L, narg, len);
if (!s) tag_error(L, narg, LUA_TSTRING);
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) {
return luaL_opt(L, luaL_checknumber, narg, def);
}
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
lua_Integer d = lua_tointeger(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_Integer luaL_optinteger (lua_State *L, int narg,
lua_Integer def) {
return luaL_opt(L, luaL_checkinteger, narg, def);
}
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_register) (lua_State *L, const char *libname,
const luaL_Reg *l) {
luaI_openlib(L, libname, l, 0);
}
static int libsize (const luaL_Reg *l) {
int size = 0;
for (; l->name; l++) size++;
return size;
}
LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
const luaL_Reg *l, int nup) {
if (libname) {
int size = libsize(l);
/* check whether lib already exists */
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
if (!lua_istable(L, -1)) { /* not found? */
lua_pop(L, 1); /* remove previous result */
/* try global variable (and create one if it does not exist) */
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
luaL_error(L, "name conflict for module " LUA_QS, libname);
lua_pushvalue(L, -1);
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
}
lua_remove(L, -2); /* remove _LOADED table */
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
}
for (; l->name; l++) {
int i;
for (i=0; i<nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup);
lua_setfield(L, -(nup+2), l->name);
}
lua_pop(L, nup); /* remove upvalues */
}
/*
** {======================================================
** getn-setn: size for arrays
** =======================================================
*/
#if defined(LUA_COMPAT_GETN)
static int checkint (lua_State *L, int topop) {
int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
lua_pop(L, topop);
return n;
}
static void getsizes (lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
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, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
}
}
LUALIB_API 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_pushinteger(L, n);
lua_rawset(L, t);
}
else { /* use `sizes' */
getsizes(L);
lua_pushvalue(L, t);
lua_pushinteger(L, n);
lua_rawset(L, -3); /* sizes[t] = n */
lua_pop(L, 1); /* remove `sizes' */
}
}
LUALIB_API 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;
return (int)lua_objlen(L, t);
}
#endif
/* }====================================================== */
LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
const char *r) {
const char *wild;
size_t l = strlen(p);
luaL_Buffer b;
luaL_buffinit(L, &b);
while ((wild = strstr(s, p)) != NULL) {
luaL_addlstring(&b, s, wild - s); /* push prefix */
luaL_addstring(&b, r); /* push replacement in place of pattern */
s = wild + l; /* continue after `p' */
}
luaL_addstring(&b, s); /* push last suffix */
luaL_pushresult(&b);
return lua_tostring(L, -1);
}
LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
const char *fname, int szhint) {
const char *e;
lua_pushvalue(L, idx);
do {
e = strchr(fname, '.');
if (e == NULL) e = fname + strlen(fname);
lua_pushlstring(L, fname, e - fname);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) { /* no such field? */
lua_pop(L, 1); /* remove this nil */
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
lua_pushlstring(L, fname, e - fname);
lua_pushvalue(L, -2);
lua_settable(L, -4); /* set new table into field */
}
else if (!lua_istable(L, -1)) { /* field has a non-table value? */
lua_pop(L, 2); /* remove table and value */
return fname; /* return problematic part of the name */
}
lua_remove(L, -2); /* remove previous table */
fname = e + 1;
} while (*e == '.');
return NULL;
}
/*
** {======================================================
** 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_addchar(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;
const char *s = lua_tolstring(L, -1, &vl);
if (vl <= bufffree(B)) { /* fit into buffer? */
memcpy(B->p, s, 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_tointeger(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 = (int)lua_objlen(L, t);
ref++; /* create new reference */
}
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_pushinteger(L, ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
/*
** {======================================================
** Load functions
** =======================================================
*/
typedef struct LoadF {
int extraline;
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 (lf->extraline) {
lf->extraline = 0;
*size = 1;
return "\n";
}
if (feof(lf->f)) return NULL;
*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
return (*size > 0) ? lf->buff : NULL;
}
static int errfile (lua_State *L, const char *what, int fnameindex) {
const char *serr = strerror(errno);
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
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 */
lf.extraline = 0;
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, "open", fnameindex);
}
c = getc(lf.f);
if (c == '#') { /* Unix exec. file? */
lf.extraline = 1;
while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
if (c == '\n') c = getc(lf.f);
}
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
lf.extraline = 0;
}
ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
return errfile(L, "read", 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);
}
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
return luaL_loadbuffer(L, s, strlen(s), s);
}
/* }====================================================== */
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
if (nsize == 0) {
free(ptr);
return NULL;
}
else
return realloc(ptr, nsize);
}
static int panic (lua_State *L) {
(void)L; /* to avoid warnings */
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
lua_tostring(L, -1));
return 0;
}
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (L) lua_atpanic(L, &panic);
return L;
}

View File

@ -0,0 +1,174 @@
/*
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
#if defined(LUA_COMPAT_GETN)
LUALIB_API int (luaL_getn) (lua_State *L, int t);
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
#else
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
#define luaL_setn(L,i,j) ((void)0) /* no op! */
#endif
#if defined(LUA_COMPAT_OPENLIB)
#define luaI_openlib luaL_openlib
#endif
/* extra error code for `luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
const luaL_Reg *l);
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 lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def);
LUALIB_API 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_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
const char *const lst[]);
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
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);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
const char *fname, int szhint);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
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_addchar(B,c) \
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))
/* compatibility only */
#define luaL_putchar(B,c) luaL_addchar(B,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 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))
#define luaL_reg luaL_Reg
#endif

View File

@ -0,0 +1,653 @@
/*
** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lbaselib_c
#define LUA_LIB
#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, LUA_QL("tostring") " must return a string to "
LUA_QL("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);
lua_settop(L, 1);
if (lua_isstring(L, 1) && level > 0) { /* 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, int opt) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar;
int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 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 luaB_getfenv (lua_State *L) {
getfunc(L, 1);
if (lua_iscfunction(L, -1)) /* is a C function? */
lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
else
lua_getfenv(L, -1);
return 1;
}
static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
getfunc(L, 0);
lua_pushvalue(L, 2);
if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
/* change environment of current thread */
lua_pushthread(L);
lua_insert(L, -2);
lua_setfenv(L, -2);
return 0;
}
else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
luaL_error(L,
LUA_QL("setfenv") " cannot change environment of given object");
return 1;
}
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_settop(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_settop(L, 3);
lua_rawset(L, 1);
return 1;
}
static int luaB_gcinfo (lua_State *L) {
lua_pushinteger(L, lua_getgccount(L));
return 1;
}
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
int o = luaL_checkoption(L, 1, "collect", opts);
int ex = luaL_optint(L, 2, 0);
int res = lua_gc(L, optsnum[o], ex);
switch (optsnum[o]) {
case LUA_GCCOUNT: {
int b = lua_gc(L, LUA_GCCOUNTB, 0);
lua_pushnumber(L, res + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
lua_pushboolean(L, res);
return 1;
}
default: {
lua_pushnumber(L, res);
return 1;
}
}
}
static int luaB_type (lua_State *L) {
luaL_checkany(L, 1);
lua_pushstring(L, luaL_typename(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_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
return 3;
}
static int ipairsaux (lua_State *L) {
int i = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
i++; /* next value */
lua_pushinteger(L, i);
lua_rawgeti(L, 1, i);
return (lua_isnil(L, -1)) ? 0 : 2;
}
static int luaB_ipairs (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushinteger(L, 0); /* and initial value */
return 3;
}
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));
}
/*
** Reader for generic `load' function: `lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)ud; /* to avoid warnings */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
*size = 0;
return NULL;
}
else if (lua_isstring(L, -1)) {
lua_replace(L, 3); /* save string in a reserved stack slot */
return lua_tolstring(L, 3, size);
}
else luaL_error(L, "reader function must return a string");
return NULL; /* to avoid warnings */
}
static int luaB_load (lua_State *L) {
int status;
const char *cname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, 3); /* function, eventual name, plus one reserved slot */
status = lua_load(L, generic_reader, NULL, cname);
return load_aux(L, status);
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
int n = lua_gettop(L);
if (luaL_loadfile(L, fname) != 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!"));
return lua_gettop(L);
}
static int luaB_unpack (lua_State *L) {
int i, e, n;
luaL_checktype(L, 1, LUA_TTABLE);
i = luaL_optint(L, 2, 1);
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
if (i > e) return 0; /* empty range */
n = e - i + 1; /* number of elements */
if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
return luaL_error(L, "too many results to unpack");
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
while (i++ < e) /* push arg[i + 1...e] */
lua_rawgeti(L, 1, i);
return n;
}
static int luaB_select (lua_State *L) {
int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
lua_pushinteger(L, n-1);
return 1;
}
else {
int i = luaL_checkint(L, 1);
if (i < 0) i = n + i;
else if (i > n) i = n;
luaL_argcheck(L, 1 <= i, 1, "index out of range");
return n - i;
}
}
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) {
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));
break;
case LUA_TSTRING:
lua_pushvalue(L, 1);
break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
break;
default:
lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
break;
}
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;
}
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"gcinfo", luaB_gcinfo},
{"getfenv", luaB_getfenv},
{"getmetatable", luaB_getmetatable},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
{"loadstring", luaB_loadstring},
{"next", luaB_next},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"rawequal", luaB_rawequal},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"select", luaB_select},
{"setfenv", luaB_setfenv},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"unpack", luaB_unpack},
{"xpcall", luaB_xpcall},
{NULL, NULL}
};
/*
** {======================================================
** Coroutine library
** =======================================================
*/
#define CO_RUN 0 /* running */
#define CO_SUS 1 /* suspended */
#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */
#define CO_DEAD 3
static const char *const statnames[] =
{"running", "suspended", "normal", "dead"};
static int costatus (lua_State *L, lua_State *co) {
if (L == co) return CO_RUN;
switch (lua_status(co)) {
case LUA_YIELD:
return CO_SUS;
case 0: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
return CO_NOR; /* it is running */
else if (lua_gettop(co) == 0)
return CO_DEAD;
else
return CO_SUS; /* initial state */
}
default: /* some error occured */
return CO_DEAD;
}
}
static int luaB_costatus (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argcheck(L, co, 1, "coroutine expected");
lua_pushstring(L, statnames[costatus(L, co)]);
return 1;
}
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status = costatus(L, co);
if (!lua_checkstack(co, narg))
luaL_error(L, "too many arguments to resume");
if (status != CO_SUS) {
lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
return -1; /* error flag */
}
lua_xmove(L, co, narg);
lua_setlevel(L, co);
status = lua_resume(co, narg);
if (status == 0 || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres + 1))
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_corunning (lua_State *L) {
if (lua_pushthread(L))
lua_pushnil(L); /* main thread is not a coroutine */
return 1;
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{NULL, NULL}
};
/* }====================================================== */
static void auxopen (lua_State *L, const char *name,
lua_CFunction f, lua_CFunction u) {
lua_pushcfunction(L, u);
lua_pushcclosure(L, f, 1);
lua_setfield(L, -2, name);
}
static void base_open (lua_State *L) {
/* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setglobal(L, "_G");
/* open lib into global table */
luaL_register(L, "_G", base_funcs);
lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next);
/* `newproxy' needs a weaktable as upvalue */
lua_createtable(L, 0, 1); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
lua_setglobal(L, "newproxy"); /* set global `newproxy' */
}
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
}

View File

@ -0,0 +1,839 @@
/*
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
#define lcode_c
#define LUA_CORE
#include "lua.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.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)
static int isnumeral(expdesc *e) {
return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
}
void luaK_nil (FuncState *fs, int from, int n) {
Instruction *previous;
if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
if (fs->pc == 0) { /* function start? */
if (from >= fs->nactvar)
return; /* positions are already clean */
}
else {
previous = &fs->f->code[fs->pc-1];
if (GET_OPCODE(*previous) == 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;
}
void luaK_ret (FuncState *fs, int first, int nret) {
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
}
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
luaK_codeABC(fs, op, A, B, C);
return luaK_jump(fs);
}
static void 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 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 && testTMode(GET_OPCODE(*(pi-1))))
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) {
for (; list != NO_JUMP; list = getjump(fs, list)) {
Instruction i = *getjumpcontrol(fs, list);
if (GET_OPCODE(i) != OP_TESTSET) return 1;
}
return 0; /* not found */
}
static int patchtestreg (FuncState *fs, int node, int reg) {
Instruction *i = getjumpcontrol(fs, node);
if (GET_OPCODE(*i) != OP_TESTSET)
return 0; /* cannot patch other instructions */
if (reg != NO_REG && reg != GETARG_B(*i))
SETARG_A(*i, reg);
else /* no register to put value or register already has the value */
*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
return 1;
}
static void removevalues (FuncState *fs, int list) {
for (; list != NO_JUMP; list = getjump(fs, list))
patchtestreg(fs, list, NO_REG);
}
static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
int dtarget) {
while (list != NO_JUMP) {
int next = getjump(fs, list);
if (patchtestreg(fs, list, reg))
fixjump(fs, list, vtarget);
else
fixjump(fs, list, dtarget); /* jump to default target */
list = next;
}
}
static void dischargejpc (FuncState *fs) {
patchlistaux(fs, fs->jpc, 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);
patchlistaux(fs, list, 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 = getjump(fs, list)) != NO_JUMP) /* find last element */
list = next;
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_byte(newstack);
}
}
void luaK_reserveregs (FuncState *fs, int n) {
luaK_checkstack(fs, n);
fs->freereg += n;
}
static void freereg (FuncState *fs, int reg) {
if (!ISK(reg) && reg >= fs->nactvar) {
fs->freereg--;
lua_assert(reg == fs->freereg);
}
}
static void freeexp (FuncState *fs, expdesc *e) {
if (e->k == VNONRELOC)
freereg(fs, e->u.s.info);
}
static int addk (FuncState *fs, TValue *k, TValue *v) {
lua_State *L = fs->L;
TValue *idx = luaH_set(L, fs->h, k);
Proto *f = fs->f;
int oldsize = f->sizek;
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 */
setnvalue(idx, cast_num(fs->nk));
luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
MAXARG_Bx, "constant table overflow");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
setobj(L, &f->k[fs->nk], v);
luaC_barrier(L, f, v);
return fs->nk++;
}
}
int luaK_stringK (FuncState *fs, TString *s) {
TValue o;
setsvalue(fs->L, &o, s);
return addk(fs, &o, &o);
}
int luaK_numberK (FuncState *fs, lua_Number r) {
TValue o;
setnvalue(&o, r);
return addk(fs, &o, &o);
}
static int boolK (FuncState *fs, int b) {
TValue o;
setbvalue(&o, b);
return addk(fs, &o, &o);
}
static int nilK (FuncState *fs) {
TValue k, v;
setnilvalue(&v);
/* cannot use nil as key; instead use table itself to represent nil */
sethvalue(fs->L, &k, fs->h);
return addk(fs, &k, &v);
}
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
if (e->k == VCALL) { /* expression is an open function call? */
SETARG_C(getcode(fs, e), nresults+1);
}
else if (e->k == VVARARG) {
SETARG_B(getcode(fs, e), nresults+1);
SETARG_A(getcode(fs, e), fs->freereg);
luaK_reserveregs(fs, 1);
}
}
void luaK_setoneret (FuncState *fs, expdesc *e) {
if (e->k == VCALL) { /* expression is an open function call? */
e->k = VNONRELOC;
e->u.s.info = GETARG_A(getcode(fs, e));
}
else if (e->k == VVARARG) {
SETARG_B(getcode(fs, e), 2);
e->k = VRELOCABLE; /* can relocate its simple result */
}
}
void luaK_dischargevars (FuncState *fs, expdesc *e) {
switch (e->k) {
case VLOCAL: {
e->k = VNONRELOC;
break;
}
case VUPVAL: {
e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
e->k = VRELOCABLE;
break;
}
case VGLOBAL: {
e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
e->k = VRELOCABLE;
break;
}
case VINDEXED: {
freereg(fs, e->u.s.aux);
freereg(fs, e->u.s.info);
e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
e->k = VRELOCABLE;
break;
}
case VVARARG:
case VCALL: {
luaK_setoneret(fs, e);
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->u.s.info);
break;
}
case VKNUM: {
luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
break;
}
case VRELOCABLE: {
Instruction *pc = &getcode(fs, e);
SETARG_A(*pc, reg);
break;
}
case VNONRELOC: {
if (reg != e->u.s.info)
luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
break;
}
default: {
lua_assert(e->k == VVOID || e->k == VJMP);
return; /* nothing to do... */
}
}
e->u.s.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 exp2reg (FuncState *fs, expdesc *e, int reg) {
discharge2reg(fs, e, reg);
if (e->k == VJMP)
luaK_concat(fs, &e->t, e->u.s.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) || need_value(fs, e->f)) {
int fj = (e->k == VJMP) ? NO_JUMP : 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);
patchlistaux(fs, e->f, final, reg, p_f);
patchlistaux(fs, e->t, final, reg, p_t);
}
e->f = e->t = NO_JUMP;
e->u.s.info = reg;
e->k = VNONRELOC;
}
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e);
freeexp(fs, e);
luaK_reserveregs(fs, 1);
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->u.s.info; /* exp is already in a register */
if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
exp2reg(fs, e, e->u.s.info); /* put value on it */
return e->u.s.info;
}
}
luaK_exp2nextreg(fs, e); /* default */
return e->u.s.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 VKNUM:
case VTRUE:
case VFALSE:
case VNIL: {
if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
e->u.s.info = (e->k == VNIL) ? nilK(fs) :
(e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
boolK(fs, (e->k == VTRUE));
e->k = VK;
return RKASK(e->u.s.info);
}
else break;
}
case VK: {
if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
return RKASK(e->u.s.info);
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 *ex) {
switch (var->k) {
case VLOCAL: {
freeexp(fs, ex);
exp2reg(fs, ex, var->u.s.info);
return;
}
case VUPVAL: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
break;
}
case VGLOBAL: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
break;
}
case VINDEXED: {
int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
break;
}
default: {
lua_assert(0); /* invalid var kind to store */
break;
}
}
freeexp(fs, ex);
}
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->u.s.info, luaK_exp2RK(fs, key));
freeexp(fs, key);
e->u.s.info = func;
e->k = VNONRELOC;
}
static void invertjump (FuncState *fs, expdesc *e) {
Instruction *pc = getjumpcontrol(fs, e->u.s.info);
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
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 condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
}
/* else go through */
}
discharge2anyreg(fs, e);
freeexp(fs, e);
return condjump(fs, OP_TESTSET, NO_REG, e->u.s.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 VKNUM: 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->u.s.info;
break;
}
default: {
pc = jumponcond(fs, e, 0);
break;
}
}
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
luaK_patchtohere(fs, e->t);
e->t = NO_JUMP;
}
static 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->u.s.info;
break;
}
default: {
pc = jumponcond(fs, e, 1);
break;
}
}
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
luaK_patchtohere(fs, e->f);
e->f = NO_JUMP;
}
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 VKNUM: case VTRUE: {
e->k = VFALSE;
break;
}
case VJMP: {
invertjump(fs, e);
break;
}
case VRELOCABLE:
case VNONRELOC: {
discharge2anyreg(fs, e);
freeexp(fs, e);
e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.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; }
removevalues(fs, e->f);
removevalues(fs, e->t);
}
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
t->u.s.aux = luaK_exp2RK(fs, k);
t->k = VINDEXED;
}
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
lua_Number v1, v2, r;
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
v1 = e1->u.nval;
v2 = e2->u.nval;
switch (op) {
case OP_ADD: r = luai_numadd(v1, v2); break;
case OP_SUB: r = luai_numsub(v1, v2); break;
case OP_MUL: r = luai_nummul(v1, v2); break;
case OP_DIV:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_numdiv(v1, v2); break;
case OP_MOD:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_nummod(v1, v2); break;
case OP_POW: r = luai_numpow(v1, v2); break;
case OP_UNM: r = luai_numunm(v1); break;
case OP_LEN: return 0; /* no constant folding for 'len' */
default: lua_assert(0); r = 0; break;
}
if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
e1->u.nval = r;
return 1;
}
static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
if (constfolding(op, e1, e2))
return;
else {
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
int o1 = luaK_exp2RK(fs, e1);
if (o1 > o2) {
freeexp(fs, e1);
freeexp(fs, e2);
}
else {
freeexp(fs, e2);
freeexp(fs, e1);
}
e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
e1->k = VRELOCABLE;
}
}
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
expdesc *e2) {
int o1 = luaK_exp2RK(fs, e1);
int o2 = luaK_exp2RK(fs, e2);
freeexp(fs, e2);
freeexp(fs, e1);
if (cond == 0 && op != OP_EQ) {
int temp; /* exchange args to replace by `<' or `<=' */
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
cond = 1;
}
e1->u.s.info = condjump(fs, op, cond, o1, o2);
e1->k = VJMP;
}
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
switch (op) {
case OPR_MINUS: {
if (!isnumeral(e))
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OP_UNM, e, &e2);
break;
}
case OPR_NOT: codenot(fs, e); break;
case OPR_LEN: {
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
codearith(fs, OP_LEN, e, &e2);
break;
}
default: lua_assert(0);
}
}
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
switch (op) {
case OPR_AND: {
luaK_goiftrue(fs, v);
break;
}
case OPR_OR: {
luaK_goiffalse(fs, v);
break;
}
case OPR_CONCAT: {
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
break;
}
case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
case OPR_MOD: case OPR_POW: {
if (!isnumeral(v)) luaK_exp2RK(fs, v);
break;
}
default: {
luaK_exp2RK(fs, v);
break;
}
}
}
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, &e2->f, e1->f);
*e1 = *e2;
break;
}
case OPR_OR: {
lua_assert(e1->f == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2);
luaK_concat(fs, &e2->t, e1->t);
*e1 = *e2;
break;
}
case OPR_CONCAT: {
luaK_exp2val(fs, e2);
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
freeexp(fs, e1);
SETARG_B(getcode(fs, e2), e1->u.s.info);
e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
}
else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
codearith(fs, OP_CONCAT, e1, e2);
}
break;
}
case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
default: lua_assert(0);
}
}
void luaK_fixline (FuncState *fs, int line) {
fs->f->lineinfo[fs->pc - 1] = line;
}
static int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f;
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);
lua_assert(getBMode(o) != OpArgN || b == 0);
lua_assert(getCMode(o) != OpArgN || c == 0);
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);
lua_assert(getCMode(o) == OpArgN);
return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
}
void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
int b = (tostore == LUA_MULTRET) ? 0 : tostore;
lua_assert(tostore != 0);
if (c <= MAXARG_C)
luaK_codeABC(fs, OP_SETLIST, base, b, c);
else {
luaK_codeABC(fs, OP_SETLIST, base, b, 0);
luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
}
fs->freereg = base + 1; /* free registers with list values */
}

View File

@ -0,0 +1,76 @@
/*
** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 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_MUL, OPR_DIV, OPR_MOD, OPR_POW,
OPR_CONCAT,
OPR_NE, OPR_EQ,
OPR_LT, OPR_LE, OPR_GT, OPR_GE,
OPR_AND, OPR_OR,
OPR_NOBINOPR
} BinOpr;
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_jump (FuncState *fs);
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
#endif

View File

@ -0,0 +1,397 @@
/*
** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ldblib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
return 1;
}
static int db_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
lua_settop(L, 2);
lua_pushboolean(L, lua_setmetatable(L, 1));
return 1;
}
static int db_getfenv (lua_State *L) {
lua_getfenv(L, 1);
return 1;
}
static int db_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2);
if (lua_setfenv(L, 1) == 0)
luaL_error(L, LUA_QL("setfenv")
" cannot change environment of given object");
return 1;
}
static void settabss (lua_State *L, const char *i, const char *v) {
lua_pushstring(L, v);
lua_setfield(L, -2, i);
}
static void settabsi (lua_State *L, const char *i, int v) {
lua_pushinteger(L, v);
lua_setfield(L, -2, i);
}
static lua_State *getthread (lua_State *L, int *arg) {
if (lua_isthread(L, 1)) {
*arg = 1;
return lua_tothread(L, 1);
}
else {
*arg = 0;
return L;
}
}
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
if (L == L1) {
lua_pushvalue(L, -2);
lua_remove(L, -3);
}
else
lua_xmove(L1, L, 1);
lua_setfield(L, -2, fname);
}
static int db_getinfo (lua_State *L) {
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnSu");
if (lua_isnumber(L, arg+1)) {
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
else if (lua_isfunction(L, arg+1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
lua_pushvalue(L, arg+1);
lua_xmove(L, L1, 1);
}
else
return luaL_argerror(L, arg+1, "function or level expected");
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option");
lua_createtable(L, 0, 2);
if (strchr(options, 'S')) {
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u'))
settabsi(L, "nups", ar.nups);
if (strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
}
static int db_getlocal (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
if (name) {
lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
}
else {
lua_pushnil(L);
return 1;
}
}
static int db_setlocal (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
luaL_checkany(L, arg+3);
lua_settop(L, arg+3);
lua_xmove(L, L1, 1);
lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+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 db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
static int db_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);
lua_pushlightuserdata(L, L);
lua_rawget(L, -2);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0)
lua_pushinteger(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
}
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 void gethooktable (lua_State *L) {
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
lua_createtable(L, 0, 1);
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
}
static int db_sethook (lua_State *L) {
int arg, mask, count;
lua_Hook func;
lua_State *L1 = getthread(L, &arg);
if (lua_isnoneornil(L, arg+1)) {
lua_settop(L, arg+1);
func = NULL; mask = 0; count = 0; /* turn off hooks */
}
else {
const char *smask = luaL_checkstring(L, arg+2);
luaL_checktype(L, arg+1, LUA_TFUNCTION);
count = luaL_optint(L, arg+3, 0);
func = hookf; mask = makemask(smask, count);
}
gethooktable(L);
lua_pushlightuserdata(L, L1);
lua_pushvalue(L, arg+1);
lua_rawset(L, -3); /* set new hook */
lua_pop(L, 1); /* remove hook table */
lua_sethook(L1, func, mask, count); /* set hooks */
return 0;
}
static int db_gethook (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
gethooktable(L);
lua_pushlightuserdata(L, L1);
lua_rawget(L, -2); /* get hook */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff));
lua_pushinteger(L, lua_gethookcount(L1));
return 3;
}
static int db_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;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0)) {
fputs(lua_tostring(L, -1), stderr);
fputs("\n", stderr);
}
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 db_errorfb (lua_State *L) {
int level;
int firstpart = 1; /* still before eventual `...' */
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
if (lua_isnumber(L, arg+2)) {
level = (int)lua_tointeger(L, arg+2);
lua_pop(L, 1);
}
else
level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (!lua_getstack(L1, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
lua_getinfo(L1, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
if (*ar.namewhat != '\0') /* is there a name? */
lua_pushfstring(L, " in function " LUA_QS, ar.name);
else {
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) - arg);
}
lua_concat(L, lua_gettop(L) - arg);
return 1;
}
static const luaL_Reg dblib[] = {
{"debug", db_debug},
{"getfenv", db_getfenv},
{"gethook", db_gethook},
{"getinfo", db_getinfo},
{"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
{"setfenv", db_setfenv},
{"sethook", db_sethook},
{"setlocal", db_setlocal},
{"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue},
{"traceback", db_errorfb},
{NULL, NULL}
};
LUALIB_API int luaopen_debug (lua_State *L) {
luaL_register(L, LUA_DBLIBNAME, dblib);
return 1;
}

View File

@ -0,0 +1,638 @@
/*
** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#define ldebug_c
#define LUA_CORE
#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 (lua_State *L, CallInfo *ci, const char **name);
static int currentpc (lua_State *L, CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
if (ci == L->ci)
ci->savedpc = L->savedpc;
return pcRel(ci->savedpc, ci_func(ci)->l.p);
}
static int currentline (lua_State *L, CallInfo *ci) {
int pc = currentpc(L, ci);
if (pc < 0)
return -1; /* only active lua functions have current-line information */
else
return getline(ci_func(ci)->l.p, pc);
}
/*
** 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_byte(mask);
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 (f_isLua(ci)) /* Lua function? */
level -= ci->tailcalls; /* skip lost tail calls */
}
if (level == 0 && ci > L->base_ci) { /* level found? */
status = 1;
ar->i_ci = cast_int(ci - L->base_ci);
}
else if (level < 0) { /* level is of a lost tail call? */
status = 1;
ar->i_ci = 0;
}
else status = 0; /* no such level */
lua_unlock(L);
return status;
}
static Proto *getluaproto (CallInfo *ci) {
return (isLua(ci) ? ci_func(ci)->l.p : NULL);
}
static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
const char *name;
Proto *fp = getluaproto(ci);
if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
return name; /* is a local variable in a Lua function */
else {
StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
return "(*temporary)";
else
return NULL;
}
}
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
CallInfo *ci = L->base_ci + ar->i_ci;
const char *name = findlocal(L, ci, n);
lua_lock(L);
if (name)
luaA_pushobject(L, ci->base + (n - 1));
lua_unlock(L);
return name;
}
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
CallInfo *ci = L->base_ci + ar->i_ci;
const char *name = findlocal(L, ci, n);
lua_lock(L);
if (name)
setobjs2s(L, ci->base + (n - 1), L->top - 1);
L->top--; /* pop value */
lua_unlock(L);
return name;
}
static void funcinfo (lua_Debug *ar, Closure *cl) {
if (cl->c.isC) {
ar->source = "=[C]";
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
else {
ar->source = getstr(cl->l.p->source);
ar->linedefined = cl->l.p->linedefined;
ar->lastlinedefined = cl->l.p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
}
static void info_tailcall (lua_Debug *ar) {
ar->name = ar->namewhat = "";
ar->what = "tail";
ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
ar->source = "=(tail call)";
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
ar->nups = 0;
}
static void collectvalidlines (lua_State *L, Closure *f) {
if (f == NULL || f->c.isC) {
setnilvalue(L->top);
}
else {
Table *t = luaH_new(L, 0, 0);
int *lineinfo = f->l.p->lineinfo;
int i;
for (i=0; i<f->l.p->sizelineinfo; i++)
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
sethvalue(L, L->top, t);
}
incr_top(L);
}
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, CallInfo *ci) {
int status = 1;
if (f == NULL) {
info_tailcall(ar);
return status;
}
for (; *what; what++) {
switch (*what) {
case 'S': {
funcinfo(ar, f);
break;
}
case 'l': {
ar->currentline = (ci) ? currentline(L, ci) : -1;
break;
}
case 'u': {
ar->nups = f->c.nupvalues;
break;
}
case 'n': {
ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */
ar->name = NULL;
}
break;
}
case 'L':
case 'f': /* handled by lua_getinfo */
break;
default: status = 0; /* invalid option */
}
}
return status;
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status;
Closure *f = NULL;
CallInfo *ci = NULL;
lua_lock(L);
if (*what == '>') {
StkId func = L->top - 1;
luai_apicheck(L, ttisfunction(func));
what++; /* skip the '>' */
f = clvalue(func);
L->top--; /* pop function */
}
else if (ar->i_ci != 0) { /* no tail call? */
ci = L->base_ci + ar->i_ci;
lua_assert(ttisfunction(ci->func));
f = clvalue(ci->func);
}
status = auxgetinfo(L, what, ar, f, ci);
if (strchr(what, 'f')) {
if (f == NULL) setnilvalue(L->top);
else setclvalue(L, L->top, f);
incr_top(L);
}
if (strchr(what, 'L'))
collectvalidlines(L, f);
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->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
check(!(pt->is_vararg & VARARG_NEEDSARG) ||
(pt->is_vararg & VARARG_HASARG));
check(pt->sizeupvalues <= pt->nups);
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
return 1;
}
#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
int luaG_checkopenop (Instruction i) {
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL:
case OP_RETURN:
case OP_SETLIST: {
check(GETARG_B(i) == 0);
return 1;
}
default: return 0; /* invalid instruction after an open call */
}
}
static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
switch (mode) {
case OpArgN: check(r == 0); break;
case OpArgU: break;
case OpArgR: checkreg(pt, r); break;
case OpArgK:
check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
break;
}
return 1;
}
static Instruction 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++) {
Instruction i = pt->code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
int b = 0;
int c = 0;
check(op < NUM_OPCODES);
checkreg(pt, a);
switch (getOpMode(op)) {
case iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
check(checkArgMode(pt, b, getBMode(op)));
check(checkArgMode(pt, c, getCMode(op)));
break;
}
case iABx: {
b = GETARG_Bx(i);
if (getBMode(op) == OpArgK) check(b < pt->sizek);
break;
}
case iAsBx: {
b = GETARG_sBx(i);
if (getBMode(op) == OpArgR) {
int dest = pc+1+b;
check(0 <= dest && dest < pt->sizecode);
if (dest > 0) {
int j;
/* check that it does not jump to a setlist count; this
is tricky, because the count from a previous setlist may
have the same value of an invalid setlist; so, we must
go all the way back to the first of them (if any) */
for (j = 0; j < dest; j++) {
Instruction d = pt->code[dest-1-j];
if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
}
/* if 'j' is even, previous value is not a setlist (even if
it looks like one) */
check((j&1) == 0);
}
}
break;
}
}
if (testAMode(op)) {
if (a == reg) last = pc; /* change register `a' */
}
if (testTMode(op)) {
check(pc+2 < pt->sizecode); /* check skip */
check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
}
switch (op) {
case OP_LOADBOOL: {
if (c == 1) { /* does it jump? */
check(pc+2 < pt->sizecode); /* check its jump */
check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
GETARG_C(pt->code[pc+1]) != 0);
}
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: {
check(b < c); /* at least two operands */
break;
}
case OP_TFORLOOP: {
check(c >= 1); /* at least one result (control variable) */
checkreg(pt, a+2+c); /* space for results */
if (reg >= a+2) last = pc; /* affect all regs above its base */
break;
}
case OP_FORLOOP:
case OP_FORPREP:
checkreg(pt, a+3);
/* go through */
case OP_JMP: {
int dest = pc+1+b;
/* 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: {
if (b > 0) checkreg(pt, a + b);
if (c == 0) {
pc++;
check(pc < pt->sizecode - 1);
}
break;
}
case OP_CLOSURE: {
int nup, j;
check(b < pt->sizep);
nup = pt->p[b]->nups;
check(pc + nup < pt->sizecode);
for (j = 1; j <= nup; j++) {
OpCode op1 = GET_OPCODE(pt->code[pc + j]);
check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
}
if (reg != NO_REG) /* tracing? */
pc += nup; /* do not 'execute' these pseudo-instructions */
break;
}
case OP_VARARG: {
check((pt->is_vararg & VARARG_ISVARARG) &&
!(pt->is_vararg & VARARG_NEEDSARG));
b--;
if (b == LUA_MULTRET) check(checkopenop(pt, pc));
checkreg(pt, a+b-1);
break;
}
default: break;
}
}
return pt->code[last];
}
#undef check
#undef checkjump
#undef checkreg
/* }====================================================== */
int luaG_checkcode (const Proto *pt) {
return (symbexec(pt, pt->sizecode, NO_REG) != 0);
}
static const char *kname (Proto *p, int c) {
if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
return svalue(&p->k[INDEXK(c)]);
else
return "?";
}
static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
const char **name) {
if (isLua(ci)) { /* a Lua function? */
Proto *p = ci_func(ci)->l.p;
int pc = currentpc(L, ci);
Instruction i;
*name = luaF_getlocalname(p, stackpos+1, pc);
if (*name) /* is a local? */
return "local";
i = 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(L, 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_GETUPVAL: {
int u = GETARG_B(i); /* upvalue index */
*name = p->upvalues ? getstr(p->upvalues[u]) : "?";
return "upvalue";
}
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 (lua_State *L, CallInfo *ci, const char **name) {
Instruction i;
if ((isLua(ci) && ci->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(L, ci)];
if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
GET_OPCODE(i) == OP_TFORLOOP)
return getobjname(L, 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 TValue *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 TValue *o, const char *op) {
const char *name = NULL;
const char *t = luaT_typenames[ttype(o)];
const char *kind = (isinstack(L->ci, o)) ?
getobjname(L, L->ci, cast_int(o - L->base), &name) :
NULL;
if (kind)
luaG_runerror(L, "attempt to %s %s " LUA_QS " (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) || ttisnumber(p1)) p1 = p2;
lua_assert(!ttisstring(p1) && !ttisnumber(p1));
luaG_typeerror(L, p1, "concatenate");
}
void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
TValue 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 TValue *p1, const TValue *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(L, 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, L->top, L->top - 1); /* move argument */
setobjs2s(L, 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);
}

View File

@ -0,0 +1,33 @@
/*
** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 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)
LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaG_errormsg (lua_State *L);
LUAI_FUNC int luaG_checkcode (const Proto *pt);
LUAI_FUNC int luaG_checkopenop (Instruction i);
#endif

View File

@ -0,0 +1,518 @@
/*
** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#define ldo_c
#define LUA_CORE
#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
** =======================================================
*/
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
luai_jmpbuf b;
volatile int status; /* error code */
};
void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: {
setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
break;
}
case LUA_ERRERR: {
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
case LUA_ERRSYNTAX:
case LUA_ERRRUN: {
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break;
}
}
L->top = oldtop + 1;
}
static void restore_stack_limit (lua_State *L) {
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
int inuse = cast_int(L->ci - L->base_ci);
if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
luaD_reallocCI(L, LUAI_MAXCALLS);
}
}
static void resetstack (lua_State *L, int status) {
L->ci = L->base_ci;
L->base = L->ci->base;
luaF_close(L, L->base); /* close eventual pending closures */
luaD_seterrorobj(L, status, L->base);
L->nCcalls = L->baseCcalls;
L->allowhook = 1;
restore_stack_limit(L);
L->errfunc = 0;
L->errorJmp = NULL;
}
void luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
LUAI_THROW(L, L->errorJmp);
}
else {
L->status = cast_byte(errcode);
if (G(L)->panic) {
resetstack(L, errcode);
lua_unlock(L);
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;
LUAI_TRY(L, &lj,
(*f)(L, ud);
);
L->errorJmp = lj.previous; /* restore old error handler */
return lj.status;
}
/* }====================================================== */
static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
GCObject *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next)
gco2uv(up)->v = (gco2uv(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;
ci->func = (ci->func - oldstack) + L->stack;
}
L->base = (L->base - oldstack) + L->stack;
}
void luaD_reallocstack (lua_State *L, int newsize) {
TValue *oldstack = L->stack;
int realsize = newsize + 1 + EXTRA_STACK;
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
L->stacksize = realsize;
L->stack_last = L->stack+newsize;
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 = newsize;
L->ci = (L->ci - oldci) + L->base_ci;
L->end_ci = L->base_ci + L->size_ci - 1;
}
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);
}
static CallInfo *growCI (lua_State *L) {
if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
luaD_throw(L, LUA_ERRERR);
else {
luaD_reallocCI(L, 2*L->size_ci);
if (L->size_ci > LUAI_MAXCALLS)
luaG_runerror(L, "stack overflow");
}
return ++L->ci;
}
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 = cast_int(L->ci - L->base_ci);
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
L->ci->top = L->top + LUA_MINSTACK;
lua_assert(L->ci->top <= L->stack_last);
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 StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i;
int nfixargs = p->numparams;
Table *htab = NULL;
StkId base, fixed;
for (; actual < nfixargs; ++actual)
setnilvalue(L->top++);
#if defined(LUA_COMPAT_VARARG)
if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
int nvar = actual - nfixargs; /* number of extra arguments */
lua_assert(p->is_vararg & VARARG_HASARG);
luaC_checkGC(L);
htab = luaH_new(L, nvar, 1); /* create `arg' table */
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
/* store counter in field `n' */
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
}
#endif
/* move fixed parameters to final position */
fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */
for (i=0; i<nfixargs; i++) {
setobjs2s(L, L->top++, fixed+i);
setnilvalue(fixed+i);
}
/* add `arg' parameter */
if (htab) {
sethvalue(L, L->top++, htab);
lua_assert(iswhite(obj2gco(htab)));
}
return base;
}
static StkId tryfuncTM (lua_State *L, StkId func) {
const TValue *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(L, p, p-1);
incr_top(L);
func = restorestack(L, funcr); /* previous call may change stack */
setobj2s(L, func, tm); /* tag method is the new function to be called */
return func;
}
#define inc_ci(L) \
((L->ci == L->end_ci) ? growCI(L) : \
(condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl;
ptrdiff_t funcr;
if (!ttisfunction(func)) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */
funcr = savestack(L, func);
cl = &clvalue(func)->l;
L->ci->savedpc = L->savedpc;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
StkId st, base;
Proto *p = cl->p;
luaD_checkstack(L, p->maxstacksize);
func = restorestack(L, funcr);
if (!p->is_vararg) { /* no varargs? */
base = func + 1;
if (L->top > base + p->numparams)
L->top = base + p->numparams;
}
else { /* vararg function */
int nargs = cast_int(L->top - func) - 1;
base = adjust_varargs(L, p, nargs);
func = restorestack(L, funcr); /* previous call may change the stack */
}
ci = inc_ci(L); /* now `enter' new function */
ci->func = func;
L->base = ci->base = base;
ci->top = L->base + p->maxstacksize;
lua_assert(ci->top <= L->stack_last);
L->savedpc = p->code; /* starting point */
ci->tailcalls = 0;
ci->nresults = nresults;
for (st = L->top; st < ci->top; st++)
setnilvalue(st);
L->top = ci->top;
if (L->hookmask & LUA_MASKCALL) {
L->savedpc++; /* hooks assume 'pc' is already incremented */
luaD_callhook(L, LUA_HOOKCALL, -1);
L->savedpc--; /* correct 'pc' */
}
return PCRLUA;
}
else { /* if is a C function, call it */
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci = inc_ci(L); /* now `enter' new function */
ci->func = restorestack(L, funcr);
L->base = ci->base = ci->func + 1;
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->nresults = nresults;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L);
if (n < 0) /* yielding? */
return PCRYIELD;
else {
luaD_poscall(L, L->top - n);
return PCRC;
}
}
}
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 (f_isLua(L->ci)) { /* Lua function? */
while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
}
int luaD_poscall (lua_State *L, StkId firstResult) {
StkId res;
int wanted, i;
CallInfo *ci;
if (L->hookmask & LUA_MASKRET)
firstResult = callrethooks(L, firstResult);
ci = L->ci--;
res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults;
L->base = (ci - 1)->base; /* restore base */
L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--)
setobjs2s(L, res++, firstResult++);
while (i-- > 0)
setnilvalue(res++);
L->top = res;
return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
}
/*
** 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) {
if (++L->nCcalls >= LUAI_MAXCCALLS) {
if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
luaV_execute(L, 1); /* call it */
L->nCcalls--;
luaC_checkGC(L);
}
static void resume (lua_State *L, void *ud) {
StkId firstArg = cast(StkId, ud);
CallInfo *ci = L->ci;
if (L->status == 0) { /* start coroutine? */
lua_assert(ci == L->base_ci && firstArg > L->base);
if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
return;
}
else { /* resuming from previous yield */
lua_assert(L->status == LUA_YIELD);
L->status = 0;
if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
if (luaD_poscall(L, firstArg)) /* complete it... */
L->top = L->ci->top; /* and correct top if not multiple results */
}
else /* yielded inside a hook: just continue its execution */
L->base = L->ci->base;
}
luaV_execute(L, cast_int(L->ci - L->base_ci));
}
static int resume_error (lua_State *L, const char *msg) {
L->top = L->ci->base;
setsvalue2s(L, 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;
lua_lock(L);
if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
return resume_error(L, "cannot resume non-suspended coroutine");
if (L->nCcalls >= LUAI_MAXCCALLS)
return resume_error(L, "C stack overflow");
luai_userstateresume(L, nargs);
lua_assert(L->errfunc == 0);
L->baseCcalls = ++L->nCcalls;
status = luaD_rawrunprotected(L, resume, L->top - nargs);
if (status != 0) { /* error? */
L->status = cast_byte(status); /* mark thread as `dead' */
luaD_seterrorobj(L, status, L->top);
L->ci->top = L->top;
}
else {
lua_assert(L->nCcalls == L->baseCcalls);
status = L->status;
}
--L->nCcalls;
lua_unlock(L);
return status;
}
LUA_API int lua_yield (lua_State *L, int nresults) {
luai_userstateyield(L, nresults);
lua_lock(L);
if (L->nCcalls > L->baseCcalls)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
L->base = L->top - nresults; /* protect stack slots below */
L->status = LUA_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 */
luaD_seterrorobj(L, status, oldtop);
L->nCcalls = oldnCcalls;
L->ci = restoreci(L, old_ci);
L->base = L->ci->base;
L->savedpc = L->ci->savedpc;
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 */
const char *name;
};
static void f_parser (lua_State *L, void *ud) {
int i;
Proto *tf;
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
cl->l.p = tf;
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
cl->l.upvals[i] = luaF_newupval(L);
setclvalue(L, L->top, cl);
incr_top(L);
}
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
struct SParser p;
int status;
p.z = z; p.name = name;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
return status;
}

View File

@ -0,0 +1,57 @@
/*
** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 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"
#define luaD_checkstack(L,n) \
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
luaD_growstack(L, n); \
else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
/* results from luaD_precall */
#define PCRLUA 0 /* initiated a call to a Lua function */
#define PCRC 1 /* did a call to a C function */
#define PCRYIELD 2 /* C funtion yielded */
/* type of protected functions, to be ran by `runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
#endif

View File

@ -0,0 +1,164 @@
/*
** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#include <stddef.h>
#define ldump_c
#define LUA_CORE
#include "lua.h"
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
typedef struct {
lua_State* L;
lua_Writer writer;
void* data;
int strip;
int status;
} DumpState;
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
static void DumpBlock(const void* b, size_t size, DumpState* D)
{
if (D->status==0)
{
lua_unlock(D->L);
D->status=(*D->writer)(D->L,b,size,D->data);
lua_lock(D->L);
}
}
static void DumpChar(int y, DumpState* D)
{
char x=(char)y;
DumpVar(x,D);
}
static void DumpInt(int x, DumpState* D)
{
DumpVar(x,D);
}
static void DumpNumber(lua_Number x, DumpState* D)
{
DumpVar(x,D);
}
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
DumpInt(n,D);
DumpMem(b,n,size,D);
}
static void DumpString(const TString* s, DumpState* D)
{
if (s==NULL || getstr(s)==NULL)
{
size_t size=0;
DumpVar(size,D);
}
else
{
size_t size=s->tsv.len+1; /* include trailing '\0' */
DumpVar(size,D);
DumpBlock(getstr(s),size,D);
}
}
#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D)
{
int i,n=f->sizek;
DumpInt(n,D);
for (i=0; i<n; i++)
{
const TValue* o=&f->k[i];
DumpChar(ttype(o),D);
switch (ttype(o))
{
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpChar(bvalue(o),D);
break;
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
DumpString(rawtsvalue(o),D);
break;
default:
lua_assert(0); /* cannot happen */
break;
}
}
n=f->sizep;
DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
}
static void DumpDebug(const Proto* f, DumpState* D)
{
int i,n;
n= (D->strip) ? 0 : f->sizelineinfo;
DumpVector(f->lineinfo,n,sizeof(int),D);
n= (D->strip) ? 0 : f->sizelocvars;
DumpInt(n,D);
for (i=0; i<n; i++)
{
DumpString(f->locvars[i].varname,D);
DumpInt(f->locvars[i].startpc,D);
DumpInt(f->locvars[i].endpc,D);
}
n= (D->strip) ? 0 : f->sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
}
static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
{
DumpString((f->source==p || D->strip) ? NULL : f->source,D);
DumpInt(f->linedefined,D);
DumpInt(f->lastlinedefined,D);
DumpChar(f->nups,D);
DumpChar(f->numparams,D);
DumpChar(f->is_vararg,D);
DumpChar(f->maxstacksize,D);
DumpCode(f,D);
DumpConstants(f,D);
DumpDebug(f,D);
}
static void DumpHeader(DumpState* D)
{
char h[LUAC_HEADERSIZE];
luaU_header(h);
DumpBlock(h,LUAC_HEADERSIZE,D);
}
/*
** dump Lua function as precompiled chunk
*/
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
{
DumpState D;
D.L=L;
D.writer=w;
D.data=data;
D.strip=strip;
D.status=0;
DumpHeader(&D);
DumpFunction(f,NULL,&D);
return D.status;
}

View File

@ -0,0 +1,174 @@
/*
** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#include <stddef.h>
#define lfunc_c
#define LUA_CORE
#include "lua.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->c.isC = 1;
c->c.env = e;
c->c.nupvalues = cast_byte(nelems);
return c;
}
Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->l.isC = 0;
c->l.env = e;
c->l.nupvalues = cast_byte(nelems);
while (nelems--) c->l.upvals[nelems] = NULL;
return c;
}
UpVal *luaF_newupval (lua_State *L) {
UpVal *uv = luaM_new(L, UpVal);
luaC_link(L, obj2gco(uv), LUA_TUPVAL);
uv->v = &uv->u.value;
setnilvalue(uv->v);
return uv;
}
UpVal *luaF_findupval (lua_State *L, StkId level) {
global_State *g = G(L);
GCObject **pp = &L->openupval;
UpVal *p;
UpVal *uv;
while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
lua_assert(p->v != &p->u.value);
if (p->v == level) { /* found a corresponding upvalue? */
if (isdead(g, obj2gco(p))) /* is it dead? */
changewhite(obj2gco(p)); /* ressurect it */
return p;
}
pp = &p->next;
}
uv = luaM_new(L, UpVal); /* not found: create a new one */
uv->tt = LUA_TUPVAL;
uv->marked = luaC_white(g);
uv->v = level; /* current value lives in the stack */
uv->next = *pp; /* chain it in the proper position */
*pp = obj2gco(uv);
uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
uv->u.l.next = g->uvhead.u.l.next;
uv->u.l.next->u.l.prev = uv;
g->uvhead.u.l.next = uv;
lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
return uv;
}
static void unlinkupval (UpVal *uv) {
lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
uv->u.l.prev->u.l.next = uv->u.l.next;
}
void luaF_freeupval (lua_State *L, UpVal *uv) {
if (uv->v != &uv->u.value) /* is it open? */
unlinkupval(uv); /* remove from open list */
luaM_free(L, uv); /* free upvalue */
}
void luaF_close (lua_State *L, StkId level) {
UpVal *uv;
global_State *g = G(L);
while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
GCObject *o = obj2gco(uv);
lua_assert(!isblack(o) && uv->v != &uv->u.value);
L->openupval = uv->next; /* remove from `open' list */
if (isdead(g, o))
luaF_freeupval(L, uv); /* free upvalue */
else {
unlinkupval(uv);
setobj(L, &uv->u.value, uv->v);
uv->v = &uv->u.value; /* now current value lives here */
luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
}
}
}
Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto);
luaC_link(L, obj2gco(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->lastlinedefined = 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, TValue);
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_free(L, f);
}
void luaF_freeclosure (lua_State *L, Closure *c) {
int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
sizeLclosure(c->l.nupvalues);
luaM_freemem(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; i<f->sizelocvars && 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 */
}

View File

@ -0,0 +1,34 @@
/*
** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#ifndef lfunc_h
#define lfunc_h
#include "lobject.h"
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
cast(int, sizeof(TValue)*((n)-1)))
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1)))
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
int pc);
#endif

View File

@ -0,0 +1,711 @@
/*
** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#include <string.h>
#define lgc_c
#define LUA_CORE
#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"
#define GCSTEPSIZE 1024u
#define GCSWEEPMAX 40
#define GCSWEEPCOST 10
#define GCFINALIZECOST 100
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
#define makewhite(g,x) \
((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
#define KEYWEAK bitmask(KEYWEAKBIT)
#define VALUEWEAK bitmask(VALUEWEAKBIT)
#define markvalue(g,o) { checkconsistency(o); \
if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
#define markobject(g,t) { if (iswhite(obj2gco(t))) \
reallymarkobject(g, obj2gco(t)); }
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
if (iscollectable(gkey(n)))
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
}
static void reallymarkobject (global_State *g, GCObject *o) {
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
switch (o->gch.tt) {
case LUA_TSTRING: {
return;
}
case LUA_TUSERDATA: {
Table *mt = gco2u(o)->metatable;
gray2black(o); /* udata are never gray */
if (mt) markobject(g, mt);
markobject(g, gco2u(o)->env);
return;
}
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
markvalue(g, uv->v);
if (uv->v == &uv->u.value) /* closed? */
gray2black(o); /* open upvalues are never black */
return;
}
case LUA_TFUNCTION: {
gco2cl(o)->c.gclist = g->gray;
g->gray = o;
break;
}
case LUA_TTABLE: {
gco2h(o)->gclist = g->gray;
g->gray = o;
break;
}
case LUA_TTHREAD: {
gco2th(o)->gclist = g->gray;
g->gray = o;
break;
}
case LUA_TPROTO: {
gco2p(o)->gclist = g->gray;
g->gray = o;
break;
}
default: lua_assert(0);
}
}
static void marktmu (global_State *g) {
GCObject *u = g->tmudata;
if (u) {
do {
u = u->gch.next;
makewhite(g, u); /* may be marked, if left from previous GC */
reallymarkobject(g, u);
} while (u != g->tmudata);
}
}
/* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L, int all) {
global_State *g = G(L);
size_t deadmem = 0;
GCObject **p = &g->mainthread->next;
GCObject *curr;
while ((curr = *p) != NULL) {
if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
p = &curr->gch.next; /* don't bother with them */
else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
markfinalized(gco2u(curr)); /* don't need finalization */
p = &curr->gch.next;
}
else { /* must call its gc method */
deadmem += sizeudata(gco2u(curr));
markfinalized(gco2u(curr));
*p = curr->gch.next;
/* link `curr' at the end of `tmudata' list */
if (g->tmudata == NULL) /* list is empty? */
g->tmudata = curr->gch.next = curr; /* creates a circular list */
else {
curr->gch.next = g->tmudata->gch.next;
g->tmudata->gch.next = curr;
g->tmudata = curr;
}
}
}
return deadmem;
}
static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
int weakvalue = 0;
const TValue *mode;
if (h->metatable)
markobject(g, h->metatable);
mode = gfasttm(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? */
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
(weakvalue << VALUEWEAKBIT));
h->gclist = g->weak; /* must be cleared after GC, ... */
g->weak = obj2gco(h); /* ... so put in the appropriate list */
}
}
if (weakkey && weakvalue) return 1;
if (!weakvalue) {
i = h->sizearray;
while (i--)
markvalue(g, &h->array[i]);
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
if (ttisnil(gval(n)))
removeentry(n); /* remove empty entries */
else {
lua_assert(!ttisnil(gkey(n)));
if (!weakkey) markvalue(g, gkey(n));
if (!weakvalue) markvalue(g, gval(n));
}
}
return weakkey || weakvalue;
}
/*
** All marks are conditional because a GC may happen while the
** prototype is still being created
*/
static void traverseproto (global_State *g, Proto *f) {
int i;
if (f->source) stringmark(f->source);
for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
if (f->upvalues[i])
stringmark(f->upvalues[i]);
}
for (i=0; i<f->sizep; i++) { /* mark nested protos */
if (f->p[i])
markobject(g, f->p[i]);
}
for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
if (f->locvars[i].varname)
stringmark(f->locvars[i].varname);
}
}
static void traverseclosure (global_State *g, Closure *cl) {
markobject(g, cl->c.env);
if (cl->c.isC) {
int i;
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
markvalue(g, &cl->c.upvalue[i]);
}
else {
int i;
lua_assert(cl->l.nupvalues == cl->l.p->nups);
markobject(g, cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
markobject(g, cl->l.upvals[i]);
}
}
static void checkstacksizes (lua_State *L, StkId max) {
int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
int s_used = cast_int(max - L->stack); /* part of stack in use */
if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
return; /* do not touch the stacks */
if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
condhardstacktests(luaD_reallocCI(L, ci_used + 1));
if (4*s_used < L->stacksize &&
2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
condhardstacktests(luaD_reallocstack(L, s_used));
}
static void traversestack (global_State *g, lua_State *l) {
StkId o, lim;
CallInfo *ci;
markvalue(g, gt(l));
lim = l->top;
for (ci = l->base_ci; ci <= l->ci; ci++) {
lua_assert(ci->top <= l->stack_last);
if (lim < ci->top) lim = ci->top;
}
for (o = l->stack; o < l->top; o++)
markvalue(g, o);
for (; o <= lim; o++)
setnilvalue(o);
checkstacksizes(l, lim);
}
/*
** traverse one gray object, turning it to black.
** Returns `quantity' traversed.
*/
static l_mem propagatemark (global_State *g) {
GCObject *o = g->gray;
lua_assert(isgray(o));
gray2black(o);
switch (o->gch.tt) {
case LUA_TTABLE: {
Table *h = gco2h(o);
g->gray = h->gclist;
if (traversetable(g, h)) /* table is weak? */
black2gray(o); /* keep it gray */
return sizeof(Table) + sizeof(TValue) * h->sizearray +
sizeof(Node) * sizenode(h);
}
case LUA_TFUNCTION: {
Closure *cl = gco2cl(o);
g->gray = cl->c.gclist;
traverseclosure(g, cl);
return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
sizeLclosure(cl->l.nupvalues);
}
case LUA_TTHREAD: {
lua_State *th = gco2th(o);
g->gray = th->gclist;
th->gclist = g->grayagain;
g->grayagain = o;
black2gray(o);
traversestack(g, th);
return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
sizeof(CallInfo) * th->size_ci;
}
case LUA_TPROTO: {
Proto *p = gco2p(o);
g->gray = p->gclist;
traverseproto(g, p);
return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
sizeof(Proto *) * p->sizep +
sizeof(TValue) * p->sizek +
sizeof(int) * p->sizelineinfo +
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues;
}
default: lua_assert(0); return 0;
}
}
static size_t propagateall (global_State *g) {
size_t m = 0;
while (g->gray) m += propagatemark(g);
return m;
}
/*
** The next function tells whether a key or value can be cleared from
** a weak table. Non-collectable objects are never removed from weak
** tables. Strings behave as `values', so are never removed too. for
** other objects: if really collected, cannot keep them; for userdata
** being finalized, keep them in keys, but not in values
*/
static int iscleared (const TValue *o, int iskey) {
if (!iscollectable(o)) return 0;
if (ttisstring(o)) {
stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
return 0;
}
return iswhite(gcvalue(o)) ||
(ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}
/*
** clear collected entries from weaktables
*/
static void cleartable (GCObject *l) {
while (l) {
Table *h = gco2h(l);
int i = h->sizearray;
lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
testbit(h->marked, KEYWEAKBIT));
if (testbit(h->marked, VALUEWEAKBIT)) {
while (i--) {
TValue *o = &h->array[i];
if (iscleared(o, 0)) /* value was collected? */
setnilvalue(o); /* remove value */
}
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
if (!ttisnil(gval(n)) && /* non-empty entry? */
(iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(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, gco2p(o)); break;
case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
case LUA_TTHREAD: {
lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
luaE_freethread(L, gco2th(o));
break;
}
case LUA_TSTRING: {
G(L)->strt.nuse--;
luaM_freemem(L, o, sizestring(gco2ts(o)));
break;
}
case LUA_TUSERDATA: {
luaM_freemem(L, o, sizeudata(gco2u(o)));
break;
}
default: lua_assert(0);
}
}
#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
GCObject *curr;
global_State *g = G(L);
int deadmask = otherwhite(g);
while ((curr = *p) != NULL && count-- > 0) {
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, &gco2th(curr)->openupval);
if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
makewhite(g, curr); /* make it white (for next cycle) */
p = &curr->gch.next;
}
else { /* must erase `curr' */
lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
*p = curr->gch.next;
if (curr == g->rootgc) /* is the first element of the list? */
g->rootgc = curr->gch.next; /* adjust first */
freeobj(L, curr);
}
}
return p;
}
static void checkSizes (lua_State *L) {
global_State *g = G(L);
/* check size of string hash */
if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
g->strt.size > MINSTRTABSIZE*2)
luaS_resize(L, g->strt.size/2); /* table is too big */
/* check size of buffer */
if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
luaZ_resizebuffer(L, &g->buff, newsize);
}
}
static void GCTM (lua_State *L) {
global_State *g = G(L);
GCObject *o = g->tmudata->gch.next; /* get first element */
Udata *udata = rawgco2u(o);
const TValue *tm;
/* remove udata from `tmudata' */
if (o == g->tmudata) /* last element? */
g->tmudata = NULL;
else
g->tmudata->gch.next = udata->uv.next;
udata->uv.next = g->mainthread->next; /* return it to `root' list */
g->mainthread->next = o;
makewhite(g, o);
tm = fasttm(L, udata->uv.metatable, TM_GC);
if (tm != NULL) {
lu_byte oldah = L->allowhook;
lu_mem oldt = g->GCthreshold;
L->allowhook = 0; /* stop debug hooks during GC tag method */
g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
setobj2s(L, L->top, tm);
setuvalue(L, L->top+1, udata);
L->top += 2;
luaD_call(L, L->top - 2, 0);
L->allowhook = oldah; /* restore hooks */
g->GCthreshold = oldt; /* restore threshold */
}
}
/*
** Call all GC tag methods
*/
void luaC_callGCTM (lua_State *L) {
while (G(L)->tmudata)
GCTM(L);
}
void luaC_freeall (lua_State *L) {
global_State *g = G(L);
int i;
g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */
sweepwholelist(L, &g->rootgc);
for (i = 0; i < g->strt.size; i++) /* free all string lists */
sweepwholelist(L, &g->strt.hash[i]);
}
static void markmt (global_State *g) {
int i;
for (i=0; i<NUM_TAGS; i++)
if (g->mt[i]) markobject(g, g->mt[i]);
}
/* mark root set */
static void markroot (lua_State *L) {
global_State *g = G(L);
g->gray = NULL;
g->grayagain = NULL;
g->weak = NULL;
markobject(g, g->mainthread);
/* make global table be traversed before main stack */
markvalue(g, gt(g->mainthread));
markvalue(g, registry(L));
markmt(g);
g->gcstate = GCSpropagate;
}
static void remarkupvals (global_State *g) {
UpVal *uv;
for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
if (isgray(obj2gco(uv)))
markvalue(g, uv->v);
}
}
static void atomic (lua_State *L) {
global_State *g = G(L);
size_t udsize; /* total size of userdata to be finalized */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
/* traverse objects cautch by write barrier and by 'remarkupvals' */
propagateall(g);
/* remark weak tables */
g->gray = g->weak;
g->weak = NULL;
lua_assert(!iswhite(obj2gco(g->mainthread)));
markobject(g, L); /* mark running thread */
markmt(g); /* mark basic metatables (again) */
propagateall(g);
/* remark gray again */
g->gray = g->grayagain;
g->grayagain = NULL;
propagateall(g);
udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
marktmu(g); /* mark `preserved' userdata */
udsize += propagateall(g); /* remark, to propagate `preserveness' */
cleartable(g->weak); /* remove collected objects from weak tables */
/* flip current white */
g->currentwhite = cast_byte(otherwhite(g));
g->sweepstrgc = 0;
g->sweepgc = &g->rootgc;
g->gcstate = GCSsweepstring;
g->estimate = g->totalbytes - udsize; /* first estimate */
}
static l_mem singlestep (lua_State *L) {
global_State *g = G(L);
/*lua_checkmemory(L);*/
switch (g->gcstate) {
case GCSpause: {
markroot(L); /* start a new collection */
return 0;
}
case GCSpropagate: {
if (g->gray)
return propagatemark(g);
else { /* no more `gray' objects */
atomic(L); /* finish mark phase */
return 0;
}
}
case GCSsweepstring: {
lu_mem old = g->totalbytes;
sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
g->gcstate = GCSsweep; /* end sweep-string phase */
lua_assert(old >= g->totalbytes);
g->estimate -= old - g->totalbytes;
return GCSWEEPCOST;
}
case GCSsweep: {
lu_mem old = g->totalbytes;
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
if (*g->sweepgc == NULL) { /* nothing more to sweep? */
checkSizes(L);
g->gcstate = GCSfinalize; /* end sweep phase */
}
lua_assert(old >= g->totalbytes);
g->estimate -= old - g->totalbytes;
return GCSWEEPMAX*GCSWEEPCOST;
}
case GCSfinalize: {
if (g->tmudata) {
GCTM(L);
if (g->estimate > GCFINALIZECOST)
g->estimate -= GCFINALIZECOST;
return GCFINALIZECOST;
}
else {
g->gcstate = GCSpause; /* end collection */
g->gcdept = 0;
return 0;
}
}
default: lua_assert(0); return 0;
}
}
void luaC_step (lua_State *L) {
global_State *g = G(L);
l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
if (lim == 0)
lim = (MAX_LUMEM-1)/2; /* no limit */
g->gcdept += g->totalbytes - g->GCthreshold;
do {
lim -= singlestep(L);
if (g->gcstate == GCSpause)
break;
} while (lim > 0);
if (g->gcstate != GCSpause) {
if (g->gcdept < GCSTEPSIZE)
g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/
else {
g->gcdept -= GCSTEPSIZE;
g->GCthreshold = g->totalbytes;
}
}
else {
lua_assert(g->totalbytes >= g->estimate);
setthreshold(g);
}
}
void luaC_fullgc (lua_State *L) {
global_State *g = G(L);
if (g->gcstate <= GCSpropagate) {
/* reset sweep marks to sweep all elements (returning them to white) */
g->sweepstrgc = 0;
g->sweepgc = &g->rootgc;
/* reset other collector lists */
g->gray = NULL;
g->grayagain = NULL;
g->weak = NULL;
g->gcstate = GCSsweepstring;
}
lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
/* finish any pending sweep phase */
while (g->gcstate != GCSfinalize) {
lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
singlestep(L);
}
markroot(L);
while (g->gcstate != GCSpause) {
singlestep(L);
}
setthreshold(g);
}
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
lua_assert(ttype(&o->gch) != LUA_TTABLE);
/* must keep invariant? */
if (g->gcstate == GCSpropagate)
reallymarkobject(g, v); /* restore invariant */
else /* don't mind */
makewhite(g, o); /* mark as white just to avoid other barriers */
}
void luaC_barrierback (lua_State *L, Table *t) {
global_State *g = G(L);
GCObject *o = obj2gco(t);
lua_assert(isblack(o) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
black2gray(o); /* make table gray (again) */
t->gclist = g->grayagain;
g->grayagain = o;
}
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
global_State *g = G(L);
o->gch.next = g->rootgc;
g->rootgc = o;
o->gch.marked = luaC_white(g);
o->gch.tt = tt;
}
void luaC_linkupval (lua_State *L, UpVal *uv) {
global_State *g = G(L);
GCObject *o = obj2gco(uv);
o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
g->rootgc = o;
if (isgray(o)) {
if (g->gcstate == GCSpropagate) {
gray2black(o); /* closed upvalues need barrier */
luaC_barrier(L, uv, uv->v);
}
else { /* sweep phase: sweep it (turning it into white) */
makewhite(g, o);
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
}
}
}

Some files were not shown because too many files have changed in this diff Show More