sweet_parser-2012.08.14

This commit is contained in:
Charles Baker 2012-12-09 20:05:47 +13:00
parent 8fd418086d
commit 80b907b34e
203 changed files with 4130 additions and 1622 deletions

View file

@ -2,7 +2,7 @@
Library {
id = "assert";
Cc {
Source {
pch = "stdafx.hpp";
"assert.cpp"
}

View file

@ -1,10 +1,17 @@
//
// assert.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"
#include "assert.hpp"
#include <sweet/build.hpp>
#include <stdlib.h>
#include <stdio.h>
#if defined(BUILD_OS_WINDOWS)
#include <windows.h>
#endif
namespace sweet
{
@ -12,6 +19,16 @@ namespace sweet
namespace assert
{
/**
// Break in the debugger.
*/
void sweet_break()
{
#if defined(BUILD_OS_WINDOWS)
DebugBreak();
#endif
}
/**
// If \e expression isn't true then print \e file, \e line, and
// \e description to the debug console and stderr.
@ -27,18 +44,17 @@ namespace assert
*/
void sweet_assert( bool expression, const char* description, const char* file, int line )
{
#if defined(BUILD_OS_WINDOWS)
int error = ::GetLastError();
if ( !expression )
{
char message [1024];
_snprintf( message, sizeof(message), "%s(%i) : %s\n", file, line, description );
message[sizeof(message) - 1] = 0;
::OutputDebugStringA( message );
::fputs( message, stderr );
}
::SetLastError( error );
#endif
}
}

View file

@ -1,6 +1,6 @@
//
// assert.hpp
// Copyright (c) 2006 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2006 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ASSERT_ASSERT_HPP_INCLUDED
@ -38,12 +38,19 @@ namespace sweet
namespace assert
{
SWEET_ASSERT_DECLSPEC void sweet_break();
SWEET_ASSERT_DECLSPEC void sweet_assert( bool expression, const char* description, const char* file, int line );
}
}
#ifdef _MSC_VER
#define SWEET_BREAK() __debugbreak()
#else
#define SWEET_BREAK() sweet::assert::sweet_break()
#endif
#ifdef SWEET_ASSERT_ENABLED
#define SWEET_ASSERT( x ) \
@ -51,7 +58,7 @@ do { \
if ( !(x) ) \
{ \
sweet::assert::sweet_assert( false, #x, __FILE__, __LINE__ ); \
__debugbreak(); \
SWEET_BREAK(); \
} \
} while ( false )

View file

@ -7,9 +7,3 @@
#define NOMINMAX
#define _WIN32_WINNT 0x500
#define WINVER 0x500
#include <sweet/build.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <dbghelp.h>

View file

@ -1,6 +1,6 @@
//
// atomic.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ATOMIC_ATOMIC_HPP_INCLUDED

View file

@ -1,6 +1,6 @@
//
// atomic.ipp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ATOMIC_ATOMIC_IPP_INCLUDED
@ -8,7 +8,7 @@
#include <sweet/assert/assert.hpp>
#if defined(BUILD_PLATFORM_MSVC)
#if defined(BUILD_OS_WINDOWS)
#include <windows.h>
#endif
@ -29,11 +29,13 @@ namespace atomic
*/
inline int atomic_increment( volatile int* destination )
{
#if defined(BUILD_PLATFORM_MSVC)
#if defined(BUILD_OS_WINDOWS)
SWEET_ASSERT( destination );
return static_cast<int>( ::InterlockedIncrement(reinterpret_cast<volatile long*>(destination)) );
#elif defined(BUILD_OS_MACOSX)
return static_cast<int>( __sync_add_and_fetch(destination, 1) );
#else
#error "The function 'sweet::atomic::atomic_increment()' is not implemened for this platform."
#error "The function 'sweet::atomic::atomic_increment()' is not implemented for this platform."
#endif
}
@ -48,11 +50,13 @@ inline int atomic_increment( volatile int* destination )
*/
inline int atomic_decrement( volatile int* destination )
{
#if defined(BUILD_PLATFORM_MSVC)
#if defined(BUILD_OS_WINDOWS)
SWEET_ASSERT( destination );
return static_cast<int>( ::InterlockedDecrement(reinterpret_cast<volatile long*>(destination)) );
#elif defined(BUILD_OS_MACOSX)
return static_cast<int>( __sync_sub_and_fetch(destination, 1) );
#else
#error "The function 'sweet::atomic::atomic_decrement()' is not implemened for this platform."
#error "The function 'sweet::atomic::atomic_decrement()' is not implemented for this platform."
#endif
}
@ -70,11 +74,15 @@ inline int atomic_decrement( volatile int* destination )
*/
inline int atomic_exchange( volatile int* destination, int exchange )
{
#if defined(BUILD_PLATFORM_MSVC)
#if defined(BUILD_OS_WINDOWS)
SWEET_ASSERT( destination );
return static_cast<int>( ::InterlockedExchange(reinterpret_cast<volatile long*>(destination), exchange) );
#elif defined(BUILD_OS_MACOSX)
int result = static_cast<int>( __sync_lock_test_and_set(destination, exchange) );
__sync_lock_release( destination );
return result;
#else
#error "The function 'sweet::atomic::atomic_exchange()' is not implemened for this platform."
#error "The function 'sweet::atomic::atomic_exchange()' is not implemented for this platform."
#endif
}
@ -85,12 +93,12 @@ inline int atomic_exchange( volatile int* destination, int exchange )
// \e destination is exchanged with \e exchange.
//
@code
int original_value = *value;
int original = *value;
if ( *value == comparand )
{
*value = exchange;
}
return original_value;
return original;
@endcode
//
// The \e destination pointer is assumed not to be null and to be aligned on
@ -110,11 +118,13 @@ return original_value;
*/
inline int atomic_compare_exchange( volatile int* destination, int exchange, int comparand )
{
#if defined(BUILD_PLATFORM_MSVC)
#if defined(BUILD_OS_WINDOWS)
SWEET_ASSERT( destination );
return static_cast<int>( ::InterlockedCompareExchange(reinterpret_cast<volatile long*>(destination), exchange, comparand) );
#elif defined(BUILD_OS_MACOSX)
return static_cast<int>( __sync_val_compare_and_swap(destination, comparand, exchange) );
#else
#error "The function 'sweet::atomic::atomic_compare_exchange()' is not implemened for this platform."
#error "The function 'sweet::atomic::atomic_compare_exchange()' is not implemented for this platform."
#endif
}

View file

@ -1,45 +1,68 @@
command = command or "build";
platform = platform or "msvc";
source = source or "";
target = target or "";
variant = variant or "debug";
version = version or os.date( "%Y.%m.%d %H:%M:%S "..platform.." "..variant );
jobs = jobs or 4;
package.path = root("build/lua/?.lua")..";"..root("build/lua/?/init.lua");
require "build";
require "build/llvmgcc";
require "build/mingw";
require "build/msvc";
require "build/boost";
require "build/Parser";
require "build/visual_studio";
require "build/xcode";
setup {
bin = root( "../bin" );
lib = root( "../lib" );
obj = root( "../obj" );
include_directories = {
root( ".." ),
"C:/boost/include/boost-1_43"
function initialize()
platform = platform or build.switch { operating_system(); windows = "msvc"; macosx = "llvmgcc" };
variant = variant or "debug";
version = version or os.date( "%Y.%m.%d %H:%M:%S "..platform.." "..variant );
goal = goal or "";
jobs = jobs or 4;
local boost_include_directory, boost_library_directory;
if operating_system() == "windows" then
boost_include_directory = "C:/boost/include/boost-1_43";
boost_library_directory = "C:/boost/lib";
elseif operating_system() == "macosx" then
boost_include_directory = home( "boost/include/boost-1_43" );
boost_library_directory = home( "boost/lib" );
end
local settings = build.initialize {
bin = root( "../bin" );
lib = root( "../lib" );
obj = root( "../obj" );
include_directories = {
root( ".." ),
boost_include_directory
};
library_directories = {
boost_library_directory
};
sln = root( "../sweet_parser.sln" );
xcodeproj = root( "../sweet_parser.xcodeproj" );
};
library_directories = {
"C:/boost/lib"
};
};
buildfile "assert/assert.build";
buildfile "atomic/atomic.build";
buildfile "cmdline/cmdline.build";
buildfile "debug/debug.build";
buildfile "error/error.build";
buildfile "lexer/lexer.build";
buildfile "lua/lua.build";
buildfile "parser/parser.build";
buildfile "pointer/pointer.build";
buildfile "rtti/rtti.build";
buildfile "traits/traits.build";
buildfile "utility/utility.build";
buildfile "unit/unit.build";
if operating_system() == "windows" then
mingw.initialize( settings );
msvc.initialize( settings );
visual_studio.initialize( settings );
elseif operating_system() == "macosx" then
llvmgcc.initialize( settings );
xcode.initialize( settings );
end
boost.initialize( settings );
parser.initialize( settings );
end
AsciiDoc {
id = "parser.html";
"parser.txt"
}
build {};
function buildfiles()
buildfile( "assert/assert.build" );
buildfile( "atomic/atomic.build" );
buildfile( "cmdline/cmdline.build" );
buildfile( "error/error.build" );
buildfile( "lexer/lexer.build" );
buildfile( "lua/lua.build" );
buildfile( "parser/parser.build" );
buildfile( "pointer/pointer.build" );
buildfile( "rtti/rtti.build" );
buildfile( "traits/traits.build" );
buildfile( "utility/utility.build" );
buildfile( "unit/unit.build" );
end

BIN
sweet/build/build Normal file

Binary file not shown.

View file

@ -0,0 +1,46 @@
ArchivePrototype = TargetPrototype { "Archive", BIND_GENERATED_FILE };
function ArchivePrototype.load( archive )
local definition = archive.definition;
if build.built_for_platform_and_variant(definition) then
archive.architecture = archive.architecture or "";
archive:set_filename( archive:path() );
end
end;
function ArchivePrototype.static_depend( archive )
local definition = archive.definition;
if build.built_for_platform_and_variant(definition) then
archive:add_dependency( Directory(branch(archive:get_filename())) );
for _, value in ipairs(definition) do
if type(value) == "table" then
assert( value.clone and type(value.clone) == "function", "Tables with integer keys in Archives must be clonable targets" );
local target = value:clone();
target.architecture = archive.architecture;
target.module = archive.module;
archive:add_dependency( target );
end
end
end
end;
function ArchivePrototype.build( archive )
local definition = archive.definition;
if archive:is_outdated() and build.built_for_platform_and_variant(definition) then
build_library( archive, definition );
end
end;
function ArchivePrototype.clean( archive )
local definition = archive.definition;
if build.built_for_platform_and_variant(definition) then
clean_library( archive, definition );
end
end;
function Archive( id, definition )
assert( type(definition) == "table" );
return target( id, ArchivePrototype, {definition = definition} );
end

View file

@ -1,21 +1,24 @@
CcScanner = Scanner {
[ [[^#include "([^"\n\r]*)"]] ] = function( target, match )
local header = HeaderFile( target:directory()..match );
local function local_include( target, match )
local header = HeaderFile( "%s%s" % {target:directory(), match} );
target:add_dependency( header );
if header:get_bind_type() ~= BIND_INTERMEDIATE_FILE then
scan( header, CcScanner );
end
end
local function global_include( target, match )
local filename = root( "../%s" % match );
if exists(filename) then
local header = HeaderFile( filename );
target:add_dependency( header );
if header:get_bind_type() ~= BIND_INTERMEDIATE_FILE then
scan( header, CcScanner );
end
end;
end
end
[ [[^#include <([^>\n\r]*)>]] ] = function( target, match )
local filename = root( "../"..match );
if exists(filename) then
local header = HeaderFile( filename );
target:add_dependency( header );
if header:get_bind_type() ~= BIND_INTERMEDIATE_FILE then
scan( header, CcScanner );
end
end
end;
CcScanner = Scanner {
[ [[^#include "([^"\n\r]*)"]] ] = local_include;
[ [[^#include <([^>\n\r]*)>]] ] = global_include;
}

View file

@ -0,0 +1,66 @@
CompilePrototype = TargetPrototype { "Compile", BIND_PHONY };
function CompilePrototype.static_depend( compile )
local definition = compile.definition;
if build.built_for_platform_and_variant(definition) then
local directory = Directory( obj_directory(definition) );
local pch = nil;
-- if compile.pch then
-- precompiled_header = PrecompiledHeader( obj_directory(compile)..obj_name(compile.pch) );
-- precompiled_header.header = compile.pch;
-- precompiled_header.unit = compile;
-- precompiled_header:add_dependency( directory );
-- compile:add_dependency( precompiled_header );
-- compile.precompiled_header = precompiled_header;
-- end
for _, value in ipairs(definition) do
local source = SourceFile( value );
source:set_required_to_exist( true );
source.unit = compile;
local object = File( "%s/%s" % {obj_directory(definition), obj_name(value, compile.architecture)} );
object.source = value;
source.object = object;
object:add_dependency( source );
object:add_dependency( directory );
object:add_dependency( pch );
compile:add_dependency( object );
end
end
end;
function CompilePrototype.depend( compile )
local definition = compile.definition;
if build.built_for_platform_and_variant(definition) then
for _, value in ipairs(definition) do
local source = SourceFile( value );
assert( source, "Failed to find source file '%s' for scanning" % tostring(value) );
scan( source, CcScanner );
end
end
end;
function CompilePrototype.build( compile )
local definition = compile.definition;
if compile:is_outdated() and build.built_for_platform_and_variant(definition) then
cc( compile, definition );
end
end;
function CompilePrototype.clean( compile )
local definition = compile.definition;
if build.built_for_platform_and_variant(definition) then
for dependency in compile:get_dependencies() do
if dependency:prototype() == FilePrototype then
rm( dependency:path() );
end
end
end
end;
function Compile( source )
assert( type(source) == "table" and source:prototype() == SourcePrototype );
return target( "", CompilePrototype, {definition = source} );
end

View file

@ -1,8 +1,12 @@
Directory = Rule( "Directory", BIND_DIRECTORY );
DirectoryPrototype = TargetPrototype { "Directory", BIND_DIRECTORY };
function Directory:build()
if self:is_outdated() then
mkdir( self:get_filename() );
function DirectoryPrototype.build( directory )
if directory:is_outdated() then
mkdir( directory:get_filename() );
end
end
function Directory( directory )
return target( directory, DirectoryPrototype );
end

View file

@ -1,39 +1,36 @@
DynamicLibrary = Rule( "DynamicLibrary", BIND_GENERATED_FILE );
DynamicLibraryPrototype = TargetPrototype { "DynamicLibrary", BIND_PHONY };
function DynamicLibrary:load()
load_module( self );
self:set_filename( self.settings.bin.."/"..dll_name(self:id()) );
end
function DynamicLibrary:static_depend()
if built_for_platform_and_variant(self) then
self:add_dependency( Directory(self.settings.lib) );
self:add_dependency( Directory(self.settings.bin) );
local libraries = {};
if self.libraries then
for _, value in ipairs(self.libraries) do
local library = find_target( root(value) );
assert( library, "Failed to find library '"..value.."'" );
if built_for_platform_and_variant(library) then
table.insert( libraries, library );
self:add_dependency( library );
end
end
function DynamicLibraryPrototype.load_windows( dynamic_library )
if build.load_target(dynamic_library) then
if build.built_for_platform_and_variant(dynamic_library) then
local link = Link( dll_name("%s/%s" % {dynamic_library.settings.bin, dynamic_library:id()}), dynamic_library );
link.architecture = "";
link.module = dynamic_library;
link:add_dependency( Directory(dynamic_library.settings.lib) );
dynamic_library:add_dependency( link );
end
self.libraries = libraries;
end
end
function DynamicLibrary:build()
if self:is_outdated() and built_for_platform_and_variant(self) then
build_executable( self );
end
end
function DynamicLibrary:clean()
if built_for_platform_and_variant(self) then
clean_executable( self );
function DynamicLibraryPrototype.load_macosx( dynamic_library )
if build.load_target(dynamic_library) then
if build.built_for_platform_and_variant(dynamic_library) then
local lipo = Lipo( dll_name("%s/%s" % {dynamic_library.settings.bin, dynamic_library:id()}), dynamic_library );
lipo.module = dynamic_library;
dynamic_library:add_dependency( lipo );
end
end
end
function DynamicLibrary( dynamic_library )
local id = dynamic_library.id;
dynamic_library.id = nil;
return target( id, DynamicLibraryPrototype, dynamic_library );
end
if operating_system() == "macosx" then
DynamicLibraryPrototype.load = DynamicLibraryPrototype.load_macosx;
else
DynamicLibraryPrototype.load = DynamicLibraryPrototype.load_windows;
end

View file

@ -1,43 +1,35 @@
Executable = Rule( "Executable", BIND_GENERATED_FILE );
ExecutablePrototype = TargetPrototype { "Executable", BIND_PHONY };
function Executable:load()
load_module( self );
self:set_filename( self.settings.bin.."/"..exe_name(self:id()) );
end
function Executable:static_depend()
if built_for_platform_and_variant(self) then
self:add_dependency( Directory(self.settings.bin) );
local libraries = {};
if self.libraries then
for _, value in ipairs(self.libraries) do
local library = find_target( root(value) );
assert( library, "Failed to find library '"..value.."'" );
if built_for_platform_and_variant(library) then
table.insert( libraries, library );
self:add_dependency( library );
end
end
function ExecutablePrototype.load_windows( executable )
if build.load_target(executable) then
if build.built_for_platform_and_variant(executable) then
local link = Link( exe_name("%s/%s" % {executable.settings.bin, executable:id()}), executable );
link.architecture = "";
link.module = executable;
executable:add_dependency( link );
end
self.libraries = libraries;
end
end
function Executable:build()
if self:is_outdated() and built_for_platform_and_variant(self) then
build_executable( self );
function ExecutablePrototype.load_macosx( executable )
if build.load_target(executable) then
if build.built_for_platform_and_variant(executable) then
local lipo = Lipo( exe_name("%s/%s" % {settings.bin, executable:id()}), executable );
lipo.module = executable;
executable:add_dependency( lipo );
end
end
end
function Executable:clean()
if built_for_platform_and_variant(self) then
clean_executable( self );
end
function Executable( executable )
local id = executable.id;
executable.id = nil;
return target( id, ExecutablePrototype, executable );
end
function Executable:project()
generate_visual_studio_project( self );
if operating_system() == "macosx" then
ExecutablePrototype.load = ExecutablePrototype.load_macosx;
else
ExecutablePrototype.load = ExecutablePrototype.load_windows;
end

View file

@ -1,2 +1,9 @@
File = Rule( "File", BIND_GENERATED_FILE );
FilePrototype = TargetPrototype {
"File", BIND_GENERATED_FILE
}
function File( file )
assert( type(file) == "string" );
return target( file, FilePrototype );
end

View file

@ -1,2 +1,9 @@
HeaderFile = Rule( "HeaderFile", BIND_SOURCE_FILE );
HeaderFilePrototype = TargetPrototype {
"HeaderFile", BIND_SOURCE_FILE
}
function HeaderFile( header_file )
assert( type(header_file) == "string" );
return target( header_file, HeaderFilePrototype );
end

View file

@ -0,0 +1,63 @@
LinkPrototype = TargetPrototype { "Link", BIND_GENERATED_FILE };
function LinkPrototype.load( link )
local definition = link.definition;
if build.built_for_platform_and_variant(definition) then
link.architecture = link.architecture or "";
link:set_filename( link:path() );
end
end;
function LinkPrototype.static_depend( link )
local definition = link.definition;
if build.built_for_platform_and_variant(definition) then
link:add_dependency( Directory(branch(link:get_filename())) );
local libraries = {};
if definition.libraries then
for _, value in ipairs(definition.libraries) do
local library = find_target( root(value) );
assert( library, "Failed to find library '%s'" % value );
if build.built_for_platform_and_variant(library) then
for archive in library:get_dependencies() do
if archive.architecture == link.architecture then
table.insert( libraries, archive );
link:add_dependency( archive );
end
end
end
end
end
link.libraries = libraries;
for _, value in ipairs(definition) do
if type(value) == "table" then
assert( value.clone and type(value.clone) == "function", "Tables with integer keys in Archives must be clonable targets" );
local target = value:clone();
target.architecture = link.architecture;
target.module = link.module;
link:add_dependency( target );
end
end
end
end;
function LinkPrototype.build( link )
local definition = link.definition;
if link:is_outdated() and build.built_for_platform_and_variant(definition) then
build_executable( link, definition );
end
end;
function LinkPrototype.clean( link )
local definition = link.definition;
if build.built_for_platform_and_variant(definition) then
clean_executable( link, definition );
end
end;
function Link( id, definition )
assert( type(definition) == "table" );
return target( id, LinkPrototype, {definition = definition} );
end

View file

@ -0,0 +1,42 @@
LipoPrototype = TargetPrototype { "Lipo", BIND_GENERATED_FILE };
function LipoPrototype.load( lipo )
local definition = lipo.definition;
if build.built_for_platform_and_variant(definition) then
lipo:set_filename( lipo:path() );
local architectures = definition.architectures or definition.settings.architectures;
for _, architecture in ipairs(architectures) do
local link = Link( "%s/%s_%s" % {definition.settings.obj, lipo:id(), architecture}, definition );
link.architecture = architecture;
link.module = lipo.module;
lipo:add_dependency( link );
end
end
end;
function LipoPrototype.static_depend( lipo )
local definition = lipo.definition;
if build.built_for_platform_and_variant(definition) then
lipo:add_dependency( Directory(branch(lipo:get_filename())) );
end
end;
function LipoPrototype.build( lipo )
local definition = lipo.definition;
if lipo:is_outdated() and build.built_for_platform_and_variant(definition) then
lipo_executable( lipo, definition );
end
end;
function LipoPrototype.clean( lipo )
local definition = lipo.definition;
if build.built_for_platform_and_variant(definition) then
clean_executable( lipo );
end
end;
function Lipo( id, definition )
assert( type(definition) == "table" );
return target( id, LipoPrototype, {definition = definition} );
end

View file

@ -1,12 +1,12 @@
Parser = Rule( "Parser", BIND_PHONY );
ParserPrototype = TargetPrototype { "Parser", BIND_PHONY };
function parser( settings )
putenv( "LUA_PATH", settings.parser.lua_path );
function ParserPrototype.clone( self )
return self;
end
function Parser:static_depend()
if built_for_platform_and_variant(self) then
function ParserPrototype.static_depend( self )
if build.built_for_platform_and_variant(self) then
for _, value in ipairs(self) do
local grammar = SourceFile( value );
grammar:set_required_to_exist( true );
@ -21,8 +21,8 @@ function Parser:static_depend()
end
end
function Parser:build()
if self:is_outdated() and built_for_platform_and_variant(self) then
function ParserPrototype.build( self )
if self:is_outdated() and build.built_for_platform_and_variant(self) then
local parser = self.settings.parser.executable;
for dependency in self:get_dependencies() do
if dependency:is_outdated() then
@ -36,12 +36,46 @@ function Parser:build()
end
end
function Parser:clean()
if built_for_platform_and_variant(self) then
function ParserPrototype.generate( self )
self:build();
end
function ParserPrototype.clean( self )
if build.built_for_platform_and_variant(self) and exists(settings.parser.executable) then
for dependency in self:get_dependencies() do
if dependency:rule() == HeaderFile then
if dependency:prototype() == HeaderFilePrototype then
rm( dependency:path() );
end
end
end
end
function Parser( parser )
assert( type(parser) == "table" );
return target( "", ParserPrototype, parser );
end
parser = {};
function parser.configure( settings )
local local_settings = build.local_settings;
if not local_settings.parser then
local_settings.updated = true;
if operating_system() == "windows" then
local_settings.parser = {
executable = "d:/usr/local/bin/parser.exe";
lua_path = "d:/usr/local/lua/?.lua";
};
else
local_settings.parser = {
executable = "/usr/local/bin/parser.exe";
lua_path = "/usr/local/lua/?.lua";
};
end
end
end
function parser.initialize( settings )
parser.configure( settings );
putenv( "LUA_PATH", settings.parser.lua_path );
end

View file

@ -1,14 +1,21 @@
PrecompiledHeader = Rule( "PrecompiledHeader", BIND_GENERATED_FILE );
PrecompiledHeaderPrototype = TargetPrototype {
"PrecompiledHeader", BIND_GENERATED_FILE,
function PrecompiledHeader:depend()
local source = SourceFile( cxx_name(self.header) );
source:set_required_to_exist( true );
source.unit = self.unit;
source.object_file = self;
scan( source, CcScanner );
self.source = source:id();
self:add_dependency( source );
self:add_dependency( directory );
depend = function( self )
local source = SourceFile( cxx_name(self.header) );
source:set_required_to_exist( true );
source.unit = self.unit;
source.object_file = self;
scan( source, CcScanner );
self.source = source:id();
self:add_dependency( source );
self:add_dependency( directory );
end;
}
function PrecompiledHeader( precompiled_header )
assert( type(precompiled_header) == "string" );
return target( precompiled_header, PrecompiledHeaderPrototype );
end

View file

@ -0,0 +1,11 @@
SourcePrototype = TargetPrototype { "Source", BIND_PHONY };
function SourcePrototype.clone( source )
return Compile( source );
end
function Source( source )
assert( source == nil or type(source) == "table" );
return target( "", SourcePrototype, source );
end

View file

@ -1,2 +1,9 @@
SourceFile = Rule( "SourceFile", BIND_SOURCE_FILE );
SourceFilePrototype = TargetPrototype {
"SourceFile", BIND_SOURCE_FILE
}
function SourceFile( source_file )
assert( type(source_file) == "string" );
return target( source_file, SourceFilePrototype );
end

View file

@ -1,25 +1,39 @@
StaticLibrary = Rule( "StaticLibrary", BIND_GENERATED_FILE );
StaticLibraryPrototype = TargetPrototype { "StaticLibrary", BIND_PHONY };
function StaticLibrary:load()
load_module( self );
self:set_filename( self.settings.lib.."/"..lib_name(self:id()) );
end
function StaticLibrary:static_depend()
if built_for_platform_and_variant(self) then
self:add_dependency( Directory(self.settings.lib) );
function StaticLibraryPrototype.load_windows( static_library )
if build.load_target(static_library) then
if build.built_for_platform_and_variant(static_library) then
local archive = Archive( "%s/%s" % {static_library.settings.lib, lib_name(static_library:id())}, static_library );
archive.architecture = "";
archive.module = static_library;
static_library:add_dependency( archive );
end
end
end
function StaticLibrary:build()
if self:is_outdated() and built_for_platform_and_variant(self) then
build_library( self );
end
end
function StaticLibrary:clean()
if built_for_platform_and_variant(self) then
clean_library( self );
function StaticLibraryPrototype.load_macosx( static_library )
if build.load_target(static_library) then
if build.built_for_platform_and_variant(static_library) then
local architectures = static_library.architectures or static_library.settings.architectures;
for _, architecture in ipairs(architectures) do
local archive = Archive( "%s/%s" % {static_library.settings.lib, lib_name("%s_%s" % {static_library:id(), architecture})}, static_library );
archive.architecture = architecture;
archive.module = static_library;
static_library:add_dependency( archive );
end
end
end
end
function StaticLibrary( static_library )
local id = static_library.id;
static_library.id = nil;
return target( id, StaticLibraryPrototype, static_library );
end
if operating_system() == "macosx" then
StaticLibraryPrototype.load = StaticLibraryPrototype.load_macosx;
else
StaticLibraryPrototype.load = StaticLibraryPrototype.load_windows;
end

View file

@ -0,0 +1,83 @@
boost = {};
function boost.configure( settings )
local local_settings = build.local_settings;
if not local_settings.boost then
local_settings.updated = true;
local_settings.boost = {
boost_directory = "";
version = "1.43";
};
if operating_system() == "windows" then
local_settings.boost.boost_directory = "C:/boost";
else
local_settings.boost.boost_directory = home( "boost" );
end
end
end;
function boost.initialize( settings )
boost.configure(settings);
local boost_library_by_platform = {
llvmgcc = boost.llvmgcc_boost_library;
msvc = boost.msvc_boost_library;
mingw = boost.mingw_boost_library;
};
assert( boost_library_by_platform[platform], "No boost_library() implementation for the platform '%s'!" % platform );
boost_library = boost_library_by_platform[platform];
end;
function boost.msvc_boost_library( name )
local toolset = "vc90";
local runtime;
local version = string.gsub( settings.boost.version, "%.", "_" );
if settings.runtime_library == "static" then
runtime = "mt-s";
elseif settings.runtime_library == "static_debug" then
runtime = "mt-sgd";
elseif settings.runtime_library == "dynamic" then
runtime = "mt";
elseif settings.runtime_library == "dynamic_debug" then
runtime = "mt-gd";
end
return "lib%s-%s-%s-%s.lib" % { name, toolset, runtime, version };
end;
function boost.mingw_boost_library( name )
local toolset = "mgw46";
local runtime;
local version = string.gsub( settings.boost.version, "%.", "_" );
if settings.runtime_library == "static" then
runtime = "mt-s";
elseif settings.runtime_library == "static_debug" then
runtime = "mt-sd";
elseif settings.runtime_library == "dynamic" then
runtime = "mt";
elseif settings.runtime_library == "dynamic_debug" then
runtime = "mt-d";
end
return "%s-%s-%s-%s" % { name, toolset, runtime, version };
end;
function boost.llvmgcc_boost_library( name )
local toolset = "xgcc42";
local runtime;
local version = string.gsub( settings.boost.version, "%.", "_" );
if settings.runtime_library == "static" then
runtime = "mt-s";
elseif settings.runtime_library == "static_debug" then
runtime = "mt-sd";
elseif settings.runtime_library == "dynamic" then
runtime = "mt";
elseif settings.runtime_library == "dynamic_debug" then
runtime = "mt-d";
end
return "%s-%s-%s-%s" % { name, toolset, runtime, version };
end;

View file

@ -0,0 +1,86 @@
function default()
build.load();
local all = all or find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
postorder( build.visit("build"), all );
build.save();
print( "build: default (build)=%sms" % tostring(math.ceil(ticks())) );
end
function clean()
build.load();
local all = all or find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
postorder( build.visit("clean"), all );
rm( settings.cache );
print( "build: clean=%sms" % tostring(math.ceil(ticks())) );
end
function generate()
build.load();
local all = all or find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
postorder( build.visit("generate"), all );
print( "build: generate=%sms" % tostring(math.ceil(ticks())) );
end
function compile()
assert( source, "The 'source' variable must be specified for the 'compile' command" );
local source_file = find_target( initial(source) );
assert( source_file, "No compilable source file found at '"..initial(source).."'" );
local object_file = source_file.object;
assert( object_file, "No object file found at '"..obj_directory(source_file.unit)..obj_name(source_file:id()).."'" );
local unit = source_file.unit;
for dependency in unit:get_dependencies() do
if dependency:prototype() == FilePrototype and dependency ~= unit.precompiled_header then
dependency:set_outdated( false );
end
end
unit:set_outdated( true );
object_file:set_outdated( true );
postorder( build.visit("build"), unit );
end
function reconfigure()
build.load();
rm( build.settings.local_settings_filename );
build.load();
build.save();
end
function dependencies()
build.load();
local all = all or find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
print_dependencies( all );
end
function namespace()
build.load();
local all = all or find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
print_namespace( all );
end
function install()
local platforms = build.switch {
operating_system();
windows = { "msvc" };
macosx = { "llvmgcc" };
};
local variants = build.switch {
operating_system();
windows = { "debug", "debug_dll", "release", "release_dll", "shipping", "shipping_dll" };
macosx = { "debug", "release", "shipping" };
};
for _, platform in ipairs(platforms) do
for _, variant in ipairs(variants) do
_G.platform = platform;
_G.variant = variant;
default();
end
end
end

View file

@ -0,0 +1,207 @@
return {
bin = root();
lib = root();
obj = root();
root = root();
user_settings_filename = home( "user_settings.lua" );
local_settings_filename = root( "local_settings.lua" );
include_directories = {
};
library_directories = {
};
platforms = build.switch {
operating_system();
windows = { "msvc", "mingw" };
macosx = { "llvmgcc" };
};
variants = {
};
settings_by_platform = {
["llvmgcc"] = {
architectures = {
"x86_64"
};
variants = {
"debug", "release", "shipping"
};
};
["mingw"] = {
architectures = {
"x86_64"
};
variants = {
"debug", "debug_dll", "release", "release_dll", "shipping", "shipping_dll"
};
};
["msvc"] = {
architectures = {
"x86_64"
};
variants = {
"debug", "debug_dll", "release", "release_dll", "shipping", "shipping_dll"
};
};
};
settings_by_variant = {
["debug"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = false;
generate_map_file = true;
incremental_linking = true;
library_type = "static";
link_time_code_generation = false;
minimal_rebuild = true;
optimization = false;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = true;
runtime_library = "static_debug";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["debug_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = false;
generate_map_file = true;
incremental_linking = true;
library_type = "dynamic";
link_time_code_generation = false;
minimal_rebuild = true;
optimization = false;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = true;
runtime_library = "dynamic_debug";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["release"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = true;
generate_map_file = true;
incremental_linking = false;
library_type = "static";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = false;
runtime_library = "static";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["release_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = true;
generate_map_file = true;
incremental_linking = false;
library_type = "dynamic";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = false;
runtime_library = "dynamic";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["shipping"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = true;
generate_map_file = true;
incremental_linking = false;
library_type = "static";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = true;
run_time_checks = false;
runtime_library = "static";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = true;
subsystem = "CONSOLE";
verbose_linking = false;
};
["shipping_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
fast_floating_point = true;
generate_map_file = true;
incremental_linking = false;
library_type = "dynamic";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = true;
run_time_checks = false;
runtime_library = "dynamic";
run_time_type_info = true;
sse2 = true;
stack_size = 1048576;
string_pooling = false;
strip = true;
subsystem = "CONSOLE";
verbose_linking = false;
};
};
}

View file

@ -1,21 +1,4 @@
require "build/Cc";
require "build/Parser";
require "build/File";
require "build/SourceFile";
require "build/HeaderFile";
require "build/PrecompiledHeader";
require "build/Directory";
require "build/StaticLibrary";
require "build/DynamicLibrary";
require "build/Executable";
require "build/CcScanner";
require "build/QtMoc";
require "build/AsciiDoc";
require "build/Project";
require "build/msvc";
require "build/visual_studio";
-- Provide python like syntax for string interpolation.
getmetatable("").__mod = function( format, args )
if args then
@ -29,199 +12,61 @@ getmetatable("").__mod = function( format, args )
end
end
-- Setup the build system.
function setup( settings )
command = command or "build";
platform = platform or "msvc";
source = source or "";
target = target or "";
require "build/File";
require "build/SourceFile";
require "build/HeaderFile";
require "build/PrecompiledHeader";
require "build/Directory";
require "build/Compile";
require "build/Archive";
require "build/Link";
require "build/Lipo";
require "build/Source";
require "build/StaticLibrary";
require "build/DynamicLibrary";
require "build/Executable";
require "build/CcScanner";
require "build/commands";
build = {};
-- Perform per run initialization of the build system.
function build.initialize( project_settings )
platform = platform or build.switch { operating_system(); windows = "msvc"; macosx = "llvmgcc" };
variant = variant or "debug";
version = version or os.date( "%Y.%m.%d %H:%M:%S "..platform.." "..variant );
version = version or "%s %s %s" % { os.date("%Y.%m.%d %H:%M:%S"), platform, variant };
goal = goal or "";
jobs = jobs or 4;
set_maximum_parallel_jobs( jobs );
local default_settings = {
bin = root();
lib = root();
obj = root();
local default_settings = build.default_settings;
build.merge_settings( default_settings, project_settings );
msvc = {
visual_studio_directory = autodetect_visual_studio_directory() or "C:/Program Files/Microsoft Visual Studio 9.0";
windows_sdk_directory = autodetect_windows_sdk_directory() or "C:/Program Files/Microsoft SDKs/Windows/v6.0A";
};
local local_settings = {};
setmetatable( local_settings, {__index = default_settings} );
parser = {
executable = "d:/usr/local/bin/parser.exe";
lua_path = "d:/usr/local/lua/?.lua";
};
python = {
executable = "c:/Python26/python.exe";
};
asciidoc = {
executable = "c:/asciidoc/asciidoc.py";
conf_file = root( "build/lua/build/sweet.conf" );
};
include_directories = {
};
library_directories = {
};
platforms = {
"msvc"
};
variants = {
["debug"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = true;
library_type = "static";
link_time_code_generation = false;
minimal_rebuild = true;
optimization = false;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = true;
runtime_library = "static_debug";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["debug_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = true;
library_type = "dynamic";
link_time_code_generation = false;
minimal_rebuild = true;
optimization = false;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = true;
runtime_library = "dynamic_debug";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["release"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = false;
library_type = "static";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = false;
runtime_library = "static";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["release_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = false;
library_type = "dynamic";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = false;
run_time_checks = false;
runtime_library = "dynamic";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["shipping"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = false;
library_type = "static";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = true;
run_time_checks = false;
runtime_library = "static";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
["shipping_dll"] = {
compile_as_c = false;
debug = true;
exceptions = true;
generate_map_file = true;
incremental_linking = false;
library_type = "dynamic";
link_time_code_generation = true;
minimal_rebuild = false;
optimization = true;
pre_compiled_headers = true;
preprocess = false;
profiling = true;
run_time_checks = false;
runtime_library = "dynamic";
run_time_type_info = true;
stack_size = 1048576;
string_pooling = false;
subsystem = "CONSOLE";
verbose_linking = false;
};
};
};
if settings then
setmetatable( settings, {__index = default_settings} );
else
settings = default_settings;
local user_settings_filename = default_settings.user_settings_filename;
if exists(user_settings_filename) then
build.merge_settings( local_settings, dofile(user_settings_filename) );
end
local variant_settings = settings.variants[variant];
assert( variant_settings, "The variant '"..tostring(variant).."' is not supported" );
for key, value in pairs(variant_settings) do
settings[key] = value;
local local_settings_filename = default_settings.local_settings_filename;
if exists(local_settings_filename) then
build.merge_settings( local_settings, dofile(local_settings_filename) );
end
local settings = {};
setmetatable( settings, {__index = local_settings} );
local platform_settings = settings.settings_by_platform[platform];
assert( platform_settings, "The platform '%s' is not supported" % platform );
build.merge_settings( settings, platform_settings );
local variant_settings = settings.settings_by_variant[variant];
assert( variant_settings, "The variant '%s' is not supported" % variant );
build.merge_settings( settings, variant_settings );
if settings.library_type == "static" then
Library = StaticLibrary;
elseif settings.library_type == "dynamic" then
@ -230,70 +75,16 @@ function setup( settings )
error( string.format("The library type '%s' is not 'static' or 'dynamic'", settings.library_type) );
end
default_settings.root = root();
default_settings.cache = root( "%s/%s_%s.cache" % {settings.obj, platform, variant} );
load_binary( settings.cache, initial(target) );
build.default_settings.cache = root( "%s/%s_%s.cache" % {settings.obj, platform, variant} );
_G.settings = settings;
end
function build()
local total_start = 0;
parser( settings );
msvc( settings );
local load_start = ticks();
load_project( project );
local load_finish = ticks();
local bind_start = ticks();
local all = find_target( initial(target) );
assert( all, "No target found at '"..tostring(initial(target)).."'" );
preorder( visit("depend"), all );
bind( all );
local bind_finish = ticks();
local build_start = ticks();
if command == "build" then
postorder( visit("build"), all );
elseif command == "generate" then
postorder( visit("generate"), all );
elseif command == "document" then
postorder( visit("document"), all );
elseif command == "clean" then
postorder( visit("clean"), all );
rm( settings.cache );
elseif command == "compile" then
compile( source );
elseif command == "projects" then
postorder( visit("projects"), all );
elseif command == "dependencies" then
print_dependencies( all );
elseif command == "namespace" then
print_namespace( all );
end
local build_finish = ticks();
local save_start = ticks();
if command == "build" then
mkdir( branch(settings.cache) );
save_binary( settings.cache );
end
local save_finish = ticks();
local total_finish = ticks();
local load_time = load_finish - load_start;
local bind_time = bind_finish - bind_start;
local build_time = build_finish - build_start;
local save_time = save_finish - save_start;
local total_time = total_finish - total_start;
local unknown_time = total_time - (load_time + bind_time + build_time + save_time);
print( "build: load="..tostring(load_time).."ms, bind="..tostring(bind_time).."ms, build="..tostring(build_time).."ms, save="..tostring(save_time).."ms, unknown="..tostring(unknown_time).."ms, total="..tostring(total_time).."ms" );
build.default_settings = default_settings;
build.local_settings = local_settings;
build.settings = settings;
return settings;
end
-- Visit a target by calling a member function /pass/ if it has one.
function visit( pass, ... )
function build.visit( pass, ... )
local args = {...};
return function( target )
local fn = target[pass];
@ -309,7 +100,7 @@ end
--
-- @return
-- True if \e target should be built otherwise false.
function built_for_platform_and_variant( target )
function build.built_for_platform_and_variant( target )
function contains( value, values )
for _, v in ipairs(values) do
if v == value then
@ -318,36 +109,24 @@ function built_for_platform_and_variant( target )
end
return false;
end
return (target.settings.platforms == nil or contains(platform, target.settings.platforms)) and (target.settings.variants == nil or target.settings.variants[variant]);
end
-- Compile the single source file /source/ in /graph/.
function compile( source )
local source_file = find_target( initial(source) );
assert( source_file, "No compilable source file found at '"..initial(source).."'" );
local object_file = source_file.object;
assert( object_file, "No object file found at '"..obj_directory(source_file.unit)..obj_name(source_file:id()).."'" );
local unit = source_file.unit;
for dependency in unit:get_dependencies() do
if dependency:rule() == File and dependency ~= unit.precompiled_header then
dependency:set_outdated( false );
end
end
unit:set_outdated( true );
object_file:set_outdated( true );
postorder( visit("build"), unit );
return (target.settings.platforms == nil or contains(platform, target.settings.platforms)) and (target.settings.variants == nil or contains(variant, target.settings.variants));
end
-- Execute command with arguments and optional filter and raise an error if
-- it doesn't return 0.
function system( command, arguments, filter )
function build.system( command, arguments, filter )
if execute(command, arguments, filter) ~= 0 then
error( arguments.." failed" );
error( arguments.." failed", 0 );
end
end
-- Return a value from a table using the first key as a lookup.
function build.switch( values )
return values[values[1]];
end
-- Dump the keys, values, and prototype of a table for debugging.
function dump( t )
function build.dump( t )
print( tostring(t) );
if t ~= nil then
if getmetatable(t) ~= nil then
@ -359,64 +138,151 @@ function dump( t )
end
end
-- Load a project.
function load_project( project )
local root_target = find_target( root() );
assert( root_target , "No root target found at '"..tostring(root()).."'" );
if not root_target.loaded then
root_target.loaded = true;
preorder( visit("load"), root_target );
preorder( visit("static_depend"), root_target );
local cache = find_target( settings.cache );
cache.loaded = true;
cache:add_dependency( SourceFile("build.lua") );
cache:add_dependency( SourceFile("build/lua/build/Cc.lua") );
cache:add_dependency( SourceFile("build/lua/build/CcScanner.lua") );
cache:add_dependency( SourceFile("build/lua/build/settings.lua") );
cache:add_dependency( SourceFile("build/lua/build/Directory.lua") );
cache:add_dependency( SourceFile("build/lua/build/Executable.lua") );
cache:add_dependency( SourceFile("build/lua/build/File.lua") );
cache:add_dependency( SourceFile("build/lua/build/HeaderFile.lua") );
cache:add_dependency( SourceFile("build/lua/build/init.lua") );
cache:add_dependency( SourceFile("build/lua/build/StaticLibrary.lua") );
cache:add_dependency( SourceFile("build/lua/build/DynamicLibrary.lua") );
cache:add_dependency( SourceFile("build/lua/build/Parser.lua") );
cache:add_dependency( SourceFile("build/lua/build/Project.lua") );
cache:add_dependency( SourceFile("build/lua/build/SourceFile.lua") );
cache:add_dependency( SourceFile("build/lua/build/QtMoc.lua") );
cache:add_dependency( SourceFile("build/lua/build/AsciiDoc.lua") );
cache:add_dependency( SourceFile("build/lua/build/msvc.lua") );
cache:add_dependency( SourceFile("build/lua/build/visual_studio.lua") );
local user_settings = home( "user_settings.lua" );
if exists(user_settings) then
cache:add_dependency( SourceFile(user_settings) );
-- Serialize values to to a Lua file (typically the local settings table).
function build.serialize( file, value, level )
local function indent( level )
for i = 0, level - 1 do
file:write( " " );
end
end
if type(value) == "boolean" then
file:write( tostring(value) );
elseif type(value) == "number" then
file:write( value );
elseif type(value) == "string" then
file:write( string.format("%q", value) );
elseif type(value) == "table" then
file:write( "{\n" );
for _, v in ipairs(value) do
build.serialize( file, v, level + 1 );
file:write( ", " );
end
for k, v in pairs(value) do
if type(k) == "string" then
indent( level + 1 );
file:write( "%s = " % k );
build.serialize( file, v, level + 1 );
file:write( ";\n" );
end
end
indent( level );
file:write( "}" );
end
end
-- Load a module.
function load_module( module )
if module.settings then
setmetatable( module.settings, {__index = settings} );
-- Save a settings table to a file.
function build.save_settings( settings, filename )
local file = io.open( filename, "wb" );
assert( file, "Opening %s to write settings failed" % filename );
file:write( "\nreturn " );
build.serialize( file, settings, 0 );
file:write( "\n" );
file:close();
end
-- Merge settings from /source_settings/ into /settings/.
function build.merge_settings( settings, source_settings )
settings = settings or {};
for _, v in ipairs(source_settings) do
table.insert( settings, v );
end
for k, v in pairs(source_settings) do
if type(k) == "string" then
if type(v) == "table" then
settings[k] = build.merge_settings( settings[k], v );
else
settings[k] = v;
end
end
end
return settings;
end
-- Inherit settings from /settings/ to /target/.
function build.inherit_settings( target, settings )
local inherited = false;
if target.settings then
if not getmetatable(target.settings) then
setmetatable( target.settings, {__index = settings} );
inherited = true;
end
else
module.settings = settings;
target.settings = settings;
inherited = true;
end
local settings = module.settings;
for _, unit in ipairs(module) do
if unit.settings then
setmetatable( unit.settings, {__index = settings} );
else
unit.settings = settings;
return inherited;
end
-- Load a target.
function build.load_target( target )
local inherited = build.inherit_settings( target, build.settings );
for _, value in ipairs(target) do
if type(value) == "table" then
build.inherit_settings( value, target.settings );
end
module:add_dependency( unit );
unit.module = module;
end
return inherited;
end
-- Load the dependency graph from the file specified by /settings.cache/.
function build.load()
assert( initialize and type(initialize) == "function", "The 'initialize' function is not defined" );
assert( buildfiles and type(buildfiles) == "function", "The 'buildfiles' function is not defined" );
initialize();
local cache_target = load_binary( settings.cache, initial(goal) );
if cache_target == nil or cache_target:is_outdated() or build.local_settings.updated then
clear();
buildfiles();
local root_target = find_target( root() );
assert( root_target , "No root target found at '"..tostring(root()).."'" );
preorder( build.visit("load"), root_target );
preorder( build.visit("static_depend"), root_target );
bind( root_target );
cache_target = find_target( settings.cache );
assert( cache_target, "No cache target found at '%s' after loading buildfiles" % settings.cache );
cache_target:add_dependency( SourceFile(root("build.lua")) );
cache_target:add_dependency( SourceFile(root("local_settings.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/init.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/File.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/SourceFile.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/HeaderFile.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/PrecompiledHeader.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Directory.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Compile.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Archive.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Link.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Lipo.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Source.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/StaticLibrary.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/DynamicLibrary.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/Executable.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/CcScanner.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/ObjCScanner.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/default_settings.lua")) );
cache_target:add_dependency( SourceFile(root("build/lua/build/commands.lua")) );
end
local project = Project( absolute(string.format("%s.project", module.project_name or module:id())) );
project.module = module;
local working_directory = module:get_working_directory();
working_directory:add_dependency( project );
local all = find_target( initial(goal) );
assert( all, "No target found at '"..tostring(initial(goal)).."'" );
bind( all );
preorder( build.visit("depend"), all );
bind( all );
end
-- Save the dependency graph to the file specified by /settings.cache/.
function build.save()
if build.local_settings.updated then
build.local_settings.updated = nil;
build.save_settings( build.local_settings, build.settings.local_settings_filename );
end
mkdir( branch(settings.cache) );
save_binary( settings.cache );
end
-- Set default settings (all other settings inherit from this table).
build.default_settings = dofile( root("build/lua/build/default_settings.lua") );

View file

@ -0,0 +1,296 @@
llvmgcc = {};
function llvmgcc.configure( settings )
local local_settings = build.local_settings;
if not local_settings.llvmgcc then
local_settings.updated = true;
local_settings.llvmgcc = {
xcrun = "/usr/bin/xcrun";
};
end
end;
function llvmgcc.initialize( settings )
llvmgcc.configure( settings );
if platform == "llvmgcc" then
cc = llvmgcc.cc;
objc = llvmgcc.objc;
build_library = llvmgcc.build_library;
clean_library = llvmgcc.clean_library;
build_executable = llvmgcc.build_executable;
clean_executable = llvmgcc.clean_executable;
lipo_executable = llvmgcc.lipo_executable;
obj_directory = llvmgcc.obj_directory;
cc_name = llvmgcc.cc_name;
cxx_name = llvmgcc.cxx_name;
obj_name = llvmgcc.obj_name;
lib_name = llvmgcc.lib_name;
dll_name = llvmgcc.dll_name;
exe_name = llvmgcc.exe_name;
end
end;
function llvmgcc.cc( target, definition )
local cppdefines = "";
cppdefines = cppdefines.." -DBUILD_OS_MACOSX";
cppdefines = cppdefines.." -DBUILD_PLATFORM_"..upper(platform);
cppdefines = cppdefines.." -DBUILD_VARIANT_"..upper(variant);
cppdefines = cppdefines.." -DBUILD_LIBRARY_SUFFIX=\"\\\"_"..platform.."_"..variant..".lib\\\"\"";
cppdefines = cppdefines.." -DBUILD_MODULE_"..upper(string.gsub(target.module:id(), "-", "_"))
cppdefines = cppdefines.." -DBUILD_LIBRARY_TYPE_"..upper(definition.settings.library_type);
if definition.settings.defines then
for _, define in ipairs(definition.settings.defines) do
cppdefines = cppdefines.." -D"..define;
end
end
if definition.defines then
for _, define in ipairs(definition.defines) do
cppdefines = cppdefines.." -D"..define;
end
end
local cppdirs = "";
if definition.include_directories then
for _, directory in ipairs(definition.include_directories) do
cppdirs = cppdirs.." -I\""..relative(directory).."\"";
end
end
if definition.settings.include_directories then
for _, directory in ipairs(definition.settings.include_directories) do
cppdirs = cppdirs.." -I\""..directory.."\"";
end
end
local ccflags = "";
ccflags = [["%s -c]] % ccflags;
ccflags = [["%s -arch %s]] % { ccflags, target.architecture };
if definition.settings.compile_as_c then
ccflags = ccflags.." -x c";
else
ccflags = ccflags.." -fpermissive -Wno-deprecated -x c++";
end
if definition.settings.runtime_library == "static" or definition.settings.runtime_library == "static_debug" then
ccflags = ccflags.." -static-libstdc++";
end
if definition.settings.debug then
ccflags = ccflags.." -g";
end
if definition.settings.optimization then
ccflags = ccflags.." -O2";
end
if definition.settings.preprocess then
ccflags = ccflags.." -E";
end
if definition.settings.exceptions and not definition.settings.compile_as_c then
ccflags = ccflags.." -fexceptions";
end
if definition.settings.run_time_type_info and not definition.settings.compile_as_c then
ccflags = ccflags.." -frtti";
end
if definition.settings.runtime_checks then
ccflags = [[%s -fstack-protector]] % ccflags;
else
ccflags = [[%s -fno-stack-protector]] % ccflags;
end
if target.precompiled_header ~= nil then
if target.precompiled_header:is_outdated() then
print( leaf(target.precompiled_header.source) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, "xcrun g++ %s %s %s -o %s %s" % {cppdirs, cppdefines, ccflags, target.precompiled_header:get_filename(), target.precompiled_header.source} );
end
end
cppdefines = cppdefines.." -DBUILD_VERSION=\"\\\""..version.."\\\"\"";
for dependency in target:get_dependencies() do
if dependency:is_outdated() and dependency ~= target.precompiled_header then
if dependency:prototype() == FilePrototype then
print( leaf(dependency.source) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, "xcrun g++ %s %s %s -o %s %s" % {cppdirs, cppdefines, ccflags, dependency:get_filename(), absolute(dependency.source)} );
elseif dependency.results then
for _, result in ipairs(dependency.results) do
if result:is_outdated() then
print( leaf(result.source) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, "xcrun g++ %s %s %s -o %s %s" % {cppdirs, cppdefines, ccflags, result:get_filename(), absolute(result.source)} );
end
end
end
end
end
end;
function llvmgcc.build_library( target, definition )
local arflags = "";
arflags = [[%s -static]] % arflags;
local objects = "";
for compile in target:get_dependencies() do
if compile:prototype() == CompilePrototype then
if compile.precompiled_header then
objects = [[%s %s]] % { objects, leaf(compile.precompiled_header:get_filename()) };
end
for object in compile:get_dependencies() do
if object:prototype() == FilePrototype and object ~= compile.precompiled_header then
objects = [[%s %s]] % { objects, leaf(object:get_filename()) };
end
end
end
end
if objects ~= "" then
print( leaf(target:get_filename()) );
pushd( obj_directory(target.module) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, [[xcrun libtool %s -o %s %s]] % {arflags, native(target:get_filename()), objects} );
popd();
end
end;
function llvmgcc.clean_library( target, definition )
rm( target:get_filename() );
rmdir( obj_directory(target.module) );
end;
function llvmgcc.build_executable( target, definition )
local ldlibs = " ";
local lddirs = " -L \""..definition.settings.lib.."\"";
if definition.settings.library_directories then
for _, directory in ipairs(definition.settings.library_directories) do
lddirs = lddirs.." -L \""..directory.."\"";
end
end
local architecture = target.architecture;
local ldflags = "";
ldflags = [[%s -arch %s]] % { ldflags, architecture };
ldflags = [[%s -o %s]] % { ldflags, native(target:get_filename()) };
if target:prototype() == ArchivePrototype then
ldflags = ldflags.." -shared -Wl,--out-implib,"..native( definition.settings.lib.."/"..lib_name(target:id()) );
end
if definition.settings.verbose_linking then
ldflags = ldflags.." -Wl,--verbose=31";
end
if definition.settings.runtime_library == "static" or definition.settings.runtime_library == "static_debug" then
ldflags = ldflags.." -static-libstdc++";
end
if definition.settings.debug then
ldflags = ldflags.." -debug";
end
if definition.settings.strip then
ldflags = ldflags.." -Wl,-dead_strip";
end
local libraries = "";
if target.libraries then
for _, library in ipairs(target.libraries) do
libraries = "%s -l%s" % { libraries, string.gsub(basename(library:id()), "lib", "", 1) };
end
end
if definition.third_party_libraries then
for _, library in ipairs(definition.third_party_libraries) do
libraries = "%s -l%s" % { libraries, library };
end
end
if definition.system_libraries then
for _, library in ipairs(definition.system_libraries) do
libraries = "%s -l%s" % { libraries, library };
end
end
if definition.frameworks then
for _, framework in ipairs(definition.frameworks) do
libraries = "%s -framework %s" % { libraries, framework };
end
end
local objects = "";
for dependency in target:get_dependencies() do
if dependency:prototype() == CompilePrototype then
if dependency.precompiled_header then
objects = [[%s %s]] % { objects, leaf(dependency.precompiled_header:get_filename()) };
end
for object in dependency:get_dependencies() do
if object:prototype() == FilePrototype and object ~= dependency.precompiled_header then
objects = [[%s %s]] % { objects, leaf(object:get_filename()) };
end
end
end
end
if objects ~= "" then
print( leaf(target:get_filename()) );
pushd( obj_directory(target.module) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, "xcrun g++"..ldflags..lddirs..objects..libraries..ldlibs );
popd();
end
end;
function llvmgcc.clean_executable( target, definition )
rm( target:get_filename() );
rmdir( obj_directory(target.module) );
end;
function llvmgcc.lipo_executable( target, definition )
local executables = "";
for executable in target:get_dependencies() do
if executable:prototype() == LinkPrototype then
executables = [[%s %s]] % { executables, executable:get_filename() };
end
end
print( leaf(target:get_filename()) );
local xcrun = definition.settings.llvmgcc.xcrun;
build.system( xcrun, [[xcrun lipo -create %s -output %s]] % {executables, target:get_filename()} );
end
function llvmgcc.obj_directory( target )
return "%s/%s_%s/%s" % { target.settings.obj, platform, variant, relative(target:directory(), root()) };
end;
function llvmgcc.cc_name( name )
return "%s.c" % basename( name );
end;
function llvmgcc.cxx_name( name )
return "%s.cpp" % basename( name );
end;
function llvmgcc.obj_name( name, architecture )
return "%s_%s.o" % { basename(name), architecture };
end;
function llvmgcc.lib_name( name )
return "lib%s_%s.a" % { name, variant };
end;
function llvmgcc.dll_name( name )
return "%s_%s.dylib" % { name, variant };
end;
function llvmgcc.exe_name( name )
return "%s_%s" % { name, variant };
end;

View file

@ -0,0 +1,319 @@
mingw = {};
function mingw.configure( settings )
function autodetect_mingw_directory()
local mingw_directory = "C:/MinGW";
return mingw_directory;
end
local local_settings = build.local_settings;
if not local_settings.mingw then
local_settings.updated = true;
local_settings.mingw = {
mingw_directory = autodetect_mingw_directory() or "C:/MinGW";
};
end
end
function mingw.initialize( settings )
mingw.configure( settings );
if platform == "mingw" then
-- Make sure that the environment variable VS_UNICODE_OUTPUT is not set.
-- Visual Studio sets this to signal its tools to communicate back to
-- Visual Studio using named pipes rather than stdout so that unicode output
-- works better but this then prevents the build tool from intercepting
-- and collating this output.
-- See http://blogs.msdn.com/freik/archive/2006/04/05/569025.aspx.
putenv( "VS_UNICODE_OUTPUT", "" );
local mingw_directory = settings.mingw.mingw_directory;
local path = {
"%s/bin" % mingw_directory,
getenv("PATH")
};
putenv( "PATH", table.concat(path, ";") );
local include = {
"%s/include" % mingw_directory,
getenv("INCLUDE")
};
putenv( "INCLUDE", table.concat(include, ";") );
local lib = {
"%s/lib" % mingw_directory,
getenv("LIB")
};
putenv( "LIB", table.concat(lib, ";") );
cc = mingw.cc;
build_library = mingw.build_library;
clean_library = mingw.clean_library;
build_executable = mingw.build_executable;
clean_executable = mingw.clean_executable;
obj_directory = mingw.obj_directory;
cc_name = mingw.cc_name;
cxx_name = mingw.cxx_name;
pch_name = mingw.pch_name;
pdb_name = mingw.pdb_name;
obj_name = mingw.obj_name;
lib_name = mingw.lib_name;
exp_name = mingw.exp_name;
dll_name = mingw.dll_name;
exe_name = mingw.exe_name;
ilk_name = mingw.ilk_name;
end
end
function mingw.cc( target, definition )
local gcc = "%s/bin/gcc.exe" % definition.settings.mingw.mingw_directory;
local cppdefines = "";
cppdefines = cppdefines.." -DBUILD_OS_"..upper(operating_system());
cppdefines = cppdefines.." -DBUILD_PLATFORM_"..upper(platform);
cppdefines = cppdefines.." -DBUILD_VARIANT_"..upper(variant);
cppdefines = cppdefines.." -DBUILD_LIBRARY_SUFFIX=\"\\\"_"..platform.."_"..variant..".lib\\\"\"";
cppdefines = cppdefines.." -DBUILD_MODULE_"..upper(string.gsub(target.module:id(), "-", "_"))
cppdefines = cppdefines.." -DBUILD_LIBRARY_TYPE_"..upper(definition.settings.library_type);
if definition.settings.defines then
for _, define in ipairs(definition.settings.defines) do
cppdefines = cppdefines.." -D"..define;
end
end
if target.defines then
for _, define in ipairs(target.defines) do
cppdefines = cppdefines.." -D"..define;
end
end
local cppdirs = "";
if target.include_directories then
for _, directory in ipairs(target.include_directories) do
cppdirs = cppdirs.." -I\""..relative(directory).."\"";
end
end
if definition.settings.include_directories then
for _, directory in ipairs(definition.settings.include_directories) do
cppdirs = cppdirs.." -I\""..directory.."\"";
end
end
local ccflags = " -c";
if definition.settings.compile_as_c then
ccflags = ccflags.." -x c";
else
ccflags = ccflags.." -fpermissive -Wno-deprecated -x c++";
end
if definition.settings.runtime_library == "static" or definition.settings.runtime_library == "static_debug" then
ccflags = ccflags.." -static-libstdc++";
end
if definition.settings.debug then
ccflags = ccflags.." -g";
end
if definition.settings.optimization then
ccflags = ccflags.." -O2";
end
if definition.settings.preprocess then
ccflags = ccflags.." -E";
end
if definition.settings.exceptions and not definition.settings.compile_as_c then
ccflags = ccflags.." -fexceptions";
end
if definition.settings.run_time_type_info and not definition.settings.compile_as_c then
ccflags = ccflags.." -frtti";
end
if target.precompiled_header ~= nil then
if target.precompiled_header:is_outdated() then
print( leaf(target.precompiled_header.source) );
build.system( gcc, "gcc"..cppdirs..cppdefines..ccflags.." -o"..obj_directory(definition)..obj_name(target.precompiled_header.source).." "..target.precompiled_header.source, GccScanner );
end
end
local GccScanner = Scanner {
[ [[((?:[A-Z]\:)?[^\:]+)\:([0-9]+)\:[0-9]+\: ([^\:]+)\:(.*)]] ] = function( filename, line, class, message )
print( "%s(%s): %s: %s" % {filename, line, class, message} );
end;
};
cppdefines = cppdefines.." -DBUILD_VERSION=\"\\\""..version.."\\\"\"";
for dependency in target:get_dependencies() do
if dependency:is_outdated() and dependency ~= target.precompiled_header then
if dependency:prototype() == FilePrototype then
print( leaf(dependency.source) );
build.system( gcc, "gcc"..cppdirs..cppdefines..ccflags.." -o"..obj_directory(definition)..obj_name(dependency.source).." "..dependency.source, GccScanner );
elseif dependency.results then
for _, result in ipairs(dependency.results) do
if result:is_outdated() then
print( leaf(result.source) );
build.system( gcc, "gcc"..cppdirs..cppdefines..ccflags.." -o"..obj_directory(definition)..obj_name(result.source).." "..result.source, GccScanner );
end
end
end
end
end
end
function mingw.build_library( target, definition )
local ar = "%s/bin/ar.exe" % definition.settings.mingw.mingw_directory;
local arflags = " ";
local objects = "";
for dependency in target:get_dependencies() do
if dependency:prototype() == CompilePrototype then
if dependency.precompiled_header ~= nil then
objects = objects.." "..obj_name( dependency.precompiled_header:id() );
end
for object in dependency:get_dependencies() do
if object:prototype() == FilePrototype and object ~= dependency.precompiled_header then
objects = objects.." "..obj_name( object:id() );
end
end
end
end
if objects ~= "" then
print( leaf(target:get_filename()) );
pushd( obj_directory(target.module) );
build.system( ar, "ar"..arflags.." -rcs "..native(target:get_filename())..objects );
popd();
end
end
function mingw.clean_library( target, definition )
rm( target:get_filename() );
rmdir( obj_directory(target.module) );
end
function mingw.build_executable( target, definition )
local gxx = "%s/bin/g++.exe" % definition.settings.mingw.mingw_directory;
local ldlibs = " ";
local lddirs = " -L \""..definition.settings.lib.."\"";
if definition.settings.library_directories then
for _, directory in ipairs(definition.settings.library_directories) do
lddirs = lddirs.." -L \""..directory.."\"";
end
end
local ldflags = " ";
ldflags = ldflags.." -o "..native( target:get_filename() );
if target.module:prototype() == DynamicLibraryPrototype then
ldflags = ldflags.." -shared -Wl,--out-implib,"..native( "%s/%s.lib" % {definition.settings.lib, basename(target:id())} );
end
if definition.settings.verbose_linking then
ldflags = ldflags.." -Wl,--verbose=31";
end
if definition.settings.runtime_library == "static" or definition.settings.runtime_library == "static_debug" then
ldflags = ldflags.." -static-libstdc++";
end
if definition.settings.debug then
ldflags = ldflags.." -debug";
end
if definition.settings.generate_map_file then
ldflags = ldflags.." -Wl,-Map,"..native(obj_directory(target.module)..target:id()..".map");
end
if definition.settings.stack_size then
ldflags = ldflags.." -Wl,--stack,"..tostring(definition.settings.stack_size);
end
if definition.settings.strip then
ldflags = ldflags.." -Wl,--strip-all";
end
local libraries = "";
if target.libraries then
for _, library in ipairs(target.libraries) do
libraries = "%s -l%s" % { libraries, basename(library:id()) };
end
end
if definition.third_party_libraries then
for _, library in ipairs(definition.third_party_libraries) do
libraries = "%s -l%s" % { libraries, library };
end
end
local objects = "";
for dependency in target:get_dependencies() do
if dependency:prototype() == CompilePrototype then
if dependency.precompiled_header ~= nil then
objects = objects.." "..obj_name( dependency.precompiled_header:id() );
end
for object in dependency:get_dependencies() do
if object:prototype() == FilePrototype and object ~= dependency.precompiled_header then
objects = objects.." "..obj_name( object:id() );
end
end
end
end
if objects ~= "" then
print( leaf(target:get_filename()) );
pushd( obj_directory(target.module) );
build.system( gxx, "g++"..ldflags..lddirs..objects..libraries..ldlibs );
popd();
end
end
function mingw.clean_executable( target, definition )
rm( target:get_filename() );
rmdir( obj_directory(target.module) );
end
function mingw.obj_directory( target )
return "%s/%s_%s/%s/" % { target.settings.obj, platform, variant, relative(target:directory(), root()) };
end
function mingw.cc_name( name )
return "%s.c" % basename( name );
end
function mingw.cxx_name( name )
return "%s.cpp" % basename( name );
end
function mingw.obj_name( name )
return "%s.o" % basename( name );
end
function mingw.lib_name( name )
return "%s_%s_%s.lib" % { name, platform, variant };
end
function mingw.exp_name( name )
return "%s_%s_%s.exp" % { name, platform, variant };
end
function mingw.dll_name( name )
return "%s_%s_%s.dll" % { name, platform, variant };
end
function mingw.exe_name( name )
return "%s_%s_%s.exe" % { name, platform, variant };
end
function mingw.ilk_name( name )
return "%s_%s_%s.ilk" % { name, platform, variant };
end

View file

@ -1,161 +1,213 @@
function autodetect_visual_studio_directory()
local visual_studio_directory = os.getenv( "VS90COMNTOOLS" ) or os.getenv( "VS100COMNTOOLS" );
if visual_studio_directory then
visual_studio_directory = string.gsub( visual_studio_directory, "\\Common7\\Tools\\", "" );
end
return visual_studio_directory;
end
msvc = {};
function autodetect_windows_sdk_directory()
local windows_sdk_directory = os.getenv( "WindowsSdkDir" );
return windows_sdk_directory;
end
function msvc.configure( settings )
local function registry( key )
local values = {};
local RegQueryScanner = Scanner {
[ [[[ ]* ([A-Za-z0-9_]+) [ ]* ([A-Za-z0-9_]+) [ ]* ([A-Za-z0-9_\\\:\. ]+)]] ] = function( key, type, value )
values[key] = value;
end;
[ [[.*]] ] = function()
end;
};
local reg = "C:/Windows/system32/reg.exe";
local arguments = [[reg query "%s"]] % key;
build.system( reg, arguments, RegQueryScanner );
return values;
end
function msvc( settings )
-- Make sure that the environment variable VS_UNICODE_OUTPUT is not set.
-- Visual Studio sets this to signal its tools to communicate back to
-- Visual Studio using named pipes rather than stdout so that unicode output
-- works better but this then prevents the build tool from intercepting
-- and collating this output.
-- See http://blogs.msdn.com/freik/archive/2006/04/05/569025.aspx.
putenv( "VS_UNICODE_OUTPUT", "" );
local function autodetect_visual_studio_directory()
local visual_studio_directory = os.getenv( "VS90COMNTOOLS" ) or os.getenv( "VS100COMNTOOLS" );
if visual_studio_directory then
visual_studio_directory = string.gsub( visual_studio_directory, "\\Common7\\Tools\\", "" );
end
return visual_studio_directory;
end
local visual_studio_directory = settings.msvc.visual_studio_directory;
local windows_sdk_directory = settings.msvc.windows_sdk_directory;
local path = {
visual_studio_directory..[[\Common7\IDE]],
visual_studio_directory..[[\VC\BIN]],
visual_studio_directory..[[\Common7\Tools]],
visual_studio_directory..[[\VC\VCPackages]],
windows_sdk_directory..[[\bin]],
getenv("PATH")
};
putenv( "PATH", table.concat(path, ";") );
local include = {
visual_studio_directory..[[\VC\ATLMFC\INCLUDE]],
visual_studio_directory..[[\VC\INCLUDE]],
windows_sdk_directory..[[\include]],
getenv("INCLUDE")
};
putenv( "INCLUDE", table.concat(include, ";") );
local lib = {
visual_studio_directory..[[\VC\ATLMFC\LIB]],
visual_studio_directory..[[\VC\LIB]],
windows_sdk_directory..[[\lib]],
getenv("LIB")
};
putenv( "LIB", table.concat(lib, ";") );
local function autodetect_windows_sdk_directory()
local windows_sdk = registry( [[HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows]] );
assert( windows_sdk.CurrentInstallFolder, "Windows SDK not found!" );
return windows_sdk.CurrentInstallFolder;
end
local libpath = {
visual_studio_directory..[[\VC\ATLMFC\LIB]],
visual_studio_directory..[[\VC\LIB]],
getenv("LIBPATH")
};
putenv( "LIBPATH", table.concat(libpath, ";") );
end
local local_settings = build.local_settings;
if not local_settings.msvc then
local_settings.updated = true;
local_settings.msvc = {
visual_studio_directory = autodetect_visual_studio_directory() or "C:/Program Files/Microsoft Visual Studio 9.0";
windows_sdk_directory = autodetect_windows_sdk_directory() or "C:/Program Files/Microsoft SDKs/Windows/v6.0A";
};
end
end;
function cc( target )
local mscc = target.settings.msvc.visual_studio_directory.."/VC/bin/cl.exe";
function msvc.initialize( settings )
msvc.configure( settings );
if platform == "msvc" then
-- Make sure that the environment variable VS_UNICODE_OUTPUT is not set.
-- Visual Studio sets this to signal its tools to communicate back to
-- Visual Studio using named pipes rather than stdout so that unicode output
-- works better but this then prevents the build tool from intercepting
-- and collating this output.
-- See http://blogs.msdn.com/freik/archive/2006/04/05/569025.aspx.
putenv( "VS_UNICODE_OUTPUT", "" );
local visual_studio_directory = settings.msvc.visual_studio_directory;
local windows_sdk_directory = settings.msvc.windows_sdk_directory;
local path = {
visual_studio_directory..[[\Common7\IDE]],
visual_studio_directory..[[\VC\BIN]],
visual_studio_directory..[[\Common7\Tools]],
visual_studio_directory..[[\VC\VCPackages]],
windows_sdk_directory..[[\bin]],
getenv("PATH")
};
putenv( "PATH", table.concat(path, ";") );
local include = {
visual_studio_directory..[[\VC\ATLMFC\INCLUDE]],
visual_studio_directory..[[\VC\INCLUDE]],
windows_sdk_directory..[[\include]],
getenv("INCLUDE")
};
putenv( "INCLUDE", table.concat(include, ";") );
local lib = {
visual_studio_directory..[[\VC\ATLMFC\LIB]],
visual_studio_directory..[[\VC\LIB]],
windows_sdk_directory..[[\lib]],
getenv("LIB")
};
putenv( "LIB", table.concat(lib, ";") );
local libpath = {
visual_studio_directory..[[\VC\ATLMFC\LIB]],
visual_studio_directory..[[\VC\LIB]],
getenv("LIBPATH")
};
putenv( "LIBPATH", table.concat(libpath, ";") );
cc = msvc.cc;
build_library = msvc.build_library;
clean_library = msvc.clean_library;
build_executable = msvc.build_executable;
clean_executable = msvc.clean_executable;
lipo_executable = msvc.lipo_executable;
obj_directory = msvc.obj_directory;
cc_name = msvc.cc_name;
cxx_name = msvc.cxx_name;
pch_name = msvc.pch_name;
pdb_name = msvc.pdb_name;
obj_name = msvc.obj_name;
lib_name = msvc.lib_name;
exp_name = msvc.exp_name;
dll_name = msvc.dll_name;
exe_name = msvc.exe_name;
ilk_name = msvc.ilk_name;
end
end;
function msvc.cc( target, definition )
local mscc = definition.settings.msvc.visual_studio_directory.."/VC/bin/cl.exe";
local cppdefines = "";
cppdefines = cppdefines.." /DBUILD_OS_"..upper(operating_system());
cppdefines = cppdefines.." /DBUILD_PLATFORM_"..upper(platform);
cppdefines = cppdefines.." /DBUILD_VARIANT_"..upper(variant);
cppdefines = cppdefines.." /DBUILD_LIBRARY_SUFFIX=\"\\\"_"..platform.."_"..variant..".lib\\\"\"";
cppdefines = cppdefines.." /DBUILD_MODULE_"..upper(string.gsub(target.module:id(), "-", "_"))
cppdefines = cppdefines.." /DBUILD_LIBRARY_TYPE_"..upper(target.settings.library_type);
cppdefines = cppdefines.." /DBUILD_LIBRARY_TYPE_"..upper(definition.settings.library_type);
if target.settings.defines then
for _, define in ipairs(target.settings.defines) do
if definition.settings.defines then
for _, define in ipairs(definition.settings.defines) do
cppdefines = cppdefines.." /D"..define;
end
end
if target.defines then
for _, define in ipairs(target.defines) do
if definition.defines then
for _, define in ipairs(definition.defines) do
cppdefines = cppdefines.." /D"..define;
end
end
local cppdirs = "";
if target.include_directories then
for _, directory in ipairs(target.include_directories) do
if definition.include_directories then
for _, directory in ipairs(definition.include_directories) do
cppdirs = cppdirs.." /I\""..relative(directory).."\"";
end
end
if target.settings.include_directories then
for _, directory in ipairs(target.settings.include_directories) do
if definition.settings.include_directories then
for _, directory in ipairs(definition.settings.include_directories) do
cppdirs = cppdirs.." /I\""..directory.."\"";
end
end
local ccflags = " /nologo /c";
if target.settings.compile_as_c then
if definition.settings.compile_as_c then
ccflags = ccflags.." /TC";
else
ccflags = ccflags.." /TP";
end
if target.settings.runtime_library == "static" then
if definition.settings.runtime_library == "static" then
ccflags = ccflags.." /MT";
elseif target.settings.runtime_library == "static_debug" then
elseif definition.settings.runtime_library == "static_debug" then
ccflags = ccflags.." /MTd";
elseif target.settings.runtime_library == "dynamic" then
elseif definition.settings.runtime_library == "dynamic" then
ccflags = ccflags.." /MD";
elseif target.settings.runtime_library == "dynamic_debug" then
elseif definition.settings.runtime_library == "dynamic_debug" then
ccflags = ccflags.." /MDd";
end
if target.settings.debug then
local pdb = obj_directory(target)..pdb_name( "msvc.pdb" );
if definition.settings.debug then
local pdb = obj_directory(definition)..pdb_name( "msvc.pdb" );
ccflags = ccflags.." /Zi /Fd"..pdb;
end
if target.settings.exceptions then
if definition.settings.exceptions then
ccflags = ccflags.." /EHsc";
end
if target.settings.link_time_code_generation then
if definition.settings.link_time_code_generation then
ccflags = ccflags.." /GL";
end
if target.settings.minimal_rebuild then
if definition.settings.minimal_rebuild then
ccflags = ccflags.." /Gm";
end
if target.settings.optimization then
if definition.settings.optimization then
ccflags = ccflags.." /GF /O2 /Ot /Oi /GS-";
end
if target.settings.preprocess then
if definition.settings.preprocess then
ccflags = ccflags.." /P /C";
end
if target.settings.run_time_type_info then
if definition.settings.run_time_type_info then
ccflags = ccflags.." /GR";
end
if target.settings.run_time_checks then
if definition.settings.run_time_checks then
ccflags = ccflags.." /RTC1";
end
if target.precompiled_header ~= nil then
if target.precompiled_header:is_outdated() then
system( mscc, "cl"..cppdirs..cppdefines..ccflags.." /Fp"..obj_directory(target)..pch_name( target.precompiled_header:id() ).." /Yc"..target.precompiled_header.header.." /Fo"..obj_directory(target).." ".." "..target.precompiled_header.source );
build.system( mscc, "cl"..cppdirs..cppdefines..ccflags.." /Fp"..obj_directory(definition)..pch_name( target.precompiled_header:id() ).." /Yc"..target.precompiled_header.header.." /Fo"..obj_directory(definition).." ".." "..target.precompiled_header.source );
end
ccflags = ccflags.." /Fp"..obj_directory(target)..pch_name( target.precompiled_header:id() );
ccflags = ccflags.." /Fp"..obj_directory(definition)..pch_name( target.precompiled_header:id() );
ccflags = ccflags.." /Yu"..target.precompiled_header.header;
end
ccsource = "";
for dependency in target:get_dependencies() do
if dependency:is_outdated() and dependency ~= target.precompiled_header then
if dependency:rule() == File then
if dependency:is_outdated() and dependency ~= target.precompiled_header then
if dependency:prototype() == FilePrototype then
ccsource = ccsource.." "..dependency.source;
elseif dependency.results then
for _, result in ipairs(dependency.results) do
@ -169,28 +221,28 @@ function cc( target )
if ccsource ~= "" then
cppdefines = cppdefines.." /DBUILD_VERSION=\"\\\""..version.."\\\"\"";
system( mscc, "cl"..cppdirs..cppdefines..ccflags.." /Fo"..obj_directory(target).." "..ccsource );
build.system( mscc, "cl"..cppdirs..cppdefines..ccflags.." /Fo"..obj_directory(definition).." "..ccsource );
end
end
end;
function build_library( target )
local msar = target.settings.msvc.visual_studio_directory.."/VC/bin/lib.exe";
function msvc.build_library( target, definition )
local msar = definition.settings.msvc.visual_studio_directory.."/VC/bin/lib.exe";
local arflags = " /nologo";
if target.settings.link_time_code_generation then
if definition.settings.link_time_code_generation then
arflags = arflags.." /ltcg";
end
local objects = "";
for dependency in target:get_dependencies() do
if dependency:rule() == Cc then
if dependency:prototype() == CompilePrototype then
if dependency.precompiled_header ~= nil then
objects = objects.." "..obj_name( dependency.precompiled_header:id() );
end
for object in dependency:get_dependencies() do
if object:rule() == File and object ~= dependency.precompiled_header then
if object:prototype() == FilePrototype and object ~= dependency.precompiled_header then
objects = objects.." "..obj_name( object:id() );
end
end
@ -198,92 +250,92 @@ function build_library( target )
end
if objects ~= "" then
print( lib_name(target:id()) );
pushd( obj_directory(target) );
system( msar, "lib"..arflags.." /out:"..native(target:get_filename())..objects );
print( leaf(target:get_filename()) );
pushd( obj_directory(target.module) );
build.system( msar, "lib"..arflags.." /out:"..native(target:get_filename())..objects );
popd();
end
end
end;
function clean_library( target )
rm( target.settings.lib.."/"..lib_name(target:id()) );
rmdir( obj_directory(target) );
end
function msvc.clean_library( target, definition )
rm( target:get_filename() );
rmdir( obj_directory(target.module) );
end;
function build_executable( target )
local msld = target.settings.msvc.visual_studio_directory.."/VC/bin/link.exe";
local msmt = target.settings.msvc.windows_sdk_directory.."/bin/mt.exe";
local msrc = target.settings.msvc.windows_sdk_directory.."/bin/rc.exe";
function msvc.build_executable( target, definition )
local msld = definition.settings.msvc.visual_studio_directory.."/VC/bin/link.exe";
local msmt = definition.settings.msvc.windows_sdk_directory.."/bin/mt.exe";
local msrc = definition.settings.msvc.windows_sdk_directory.."/bin/rc.exe";
local ldlibs = " advapi32.lib gdi32.lib kernel32.lib user32.lib msimg32.lib ws2_32.lib version.lib odbc32.lib odbccp32.lib";
local lddirs = " /libpath:\""..target.settings.lib.."\"";
local lddirs = " /libpath:\""..definition.settings.lib.."\"";
if target.settings.library_directories then
for _, directory in ipairs(target.settings.library_directories) do
if definition.settings.library_directories then
for _, directory in ipairs(definition.settings.library_directories) do
lddirs = lddirs.." /libpath:\""..directory.."\"";
end
end
local ldflags = " /nologo";
local intermediate_manifest = obj_directory(target)..target:id().."_intermediate.manifest";
local intermediate_manifest = obj_directory(target.module)..target:id().."_intermediate.manifest";
ldflags = ldflags.." /manifest /manifestfile:"..intermediate_manifest;
if target.settings.subsystem then
ldflags = ldflags.." /subsystem:"..target.settings.subsystem;
if definition.settings.subsystem then
ldflags = ldflags.." /subsystem:"..definition.settings.subsystem;
end
local out = "";
if target:rule() == Executable then
out = native( target:get_filename() );
ldflags = ldflags.." /out:"..out;
elseif target:rule() == Library then
out = native( target.settings.bin.."/"..dll_name(target:id()) );
ldflags = ldflags.." /out:"..out;
ldflags = ldflags.." /dll /implib:"..native( target.settings.lib.."/"..lib_name(target:id()) );
ldflags = ldflags.." /out:"..native( target:get_filename() );
if target.module:prototype() == DynamicLibraryPrototype then
ldflags = ldflags.." /dll /implib:"..native( "%s/%s.lib" % {definition.settings.lib, basename(target:id())} );
end
if target.settings.verbose_linking then
if definition.settings.verbose_linking then
ldflags = ldflags.." /verbose";
end
if target.settings.debug then
ldflags = ldflags.." /debug /pdb:"..obj_directory(target)..pdb_name( target:id() );
if definition.settings.debug then
ldflags = ldflags.." /debug /pdb:"..obj_directory(target.module)..pdb_name( target:id() );
end
if target.settings.link_time_code_generation then
if definition.settings.link_time_code_generation then
ldflags = ldflags.." /ltcg";
end
if target.settings.generate_map_file then
ldflags = ldflags.." /map:"..native(obj_directory(target)..target:id()..".map");
if definition.settings.generate_map_file then
ldflags = ldflags.." /map:"..native(obj_directory(target.module)..target:id()..".map");
end
if target.settings.optimization then
if definition.settings.optimization then
ldflags = ldflags.." /opt:ref /opt:icf";
end
if target.settings.stack_size then
ldflags = ldflags.." /stack:"..tostring(target.settings.stack_size);
if definition.settings.stack_size then
ldflags = ldflags.." /stack:"..tostring(definition.settings.stack_size);
end
local libraries = "";
if target.libraries then
for _, library in ipairs(target.libraries) do
libraries = libraries.." "..lib_name( library:id() );
libraries = "%s %s.lib" % { libraries, basename(library:id()) };
end
end
if definition.third_party_libraries then
for _, library in ipairs(definition.third_party_libraries) do
libraries = "%s %s" % { libraries, library };
end
end
local objects = "";
for dependency in target:get_dependencies() do
if dependency:rule() == Cc then
if dependency:prototype() == CompilePrototype then
if dependency.precompiled_header ~= nil then
objects = objects.." "..obj_name( dependency.precompiled_header:id() );
end
for object in dependency:get_dependencies() do
if object:rule() == File and object ~= dependency.precompiled_header then
if object:prototype() == FilePrototype and object ~= dependency.precompiled_header then
objects = objects.." "..obj_name( object:id() );
end
end
@ -291,14 +343,10 @@ function build_executable( target )
end
if objects ~= "" then
if target:rule() == Executable then
print( exe_name(target:id()) );
else
print( dll_name(target:id()) );
end
print( leaf(target:get_filename()) );
pushd( obj_directory(target) );
if target.settings.incremental_linking then
pushd( obj_directory(target.module) );
if definition.settings.incremental_linking then
local embedded_manifest = target:id().."_embedded.manifest";
local embedded_manifest_rc = target:id().."_embedded_manifest.rc";
local embedded_manifest_res = target:id().."_embedded_manifest.res";
@ -306,7 +354,7 @@ function build_executable( target )
if exists(embedded_manifest_rc) ~= true then
local rc = io.open( absolute(embedded_manifest_rc), "wb" );
assert( rc, string.format("Opening '%s' to write manifest failed", absolute(embedded_manifest_rc)) );
if target:rule() == Executable then
if target:prototype() == ExecutablePrototype then
rc:write( "1 /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 24 /* RT_MANIFEST */ \""..target:id().."_embedded.manifest\"" );
else
rc:write( "2 /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 24 /* RT_MANIFEST */ \""..target:id().."_embedded.manifest\"" );
@ -314,83 +362,91 @@ function build_executable( target )
rc:close();
end
IgnoreOutputScanner = Scanner {
[ [[.*]] ] = function()
end;
};
if exists(embedded_manifest) ~= true then
system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
system( msmt, "mt /nologo /out:\""..embedded_manifest.."\" /manifest "..intermediate_manifest );
system( msrc, "rc /Fo\""..embedded_manifest_res.."\" "..embedded_manifest_rc );
build.system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
build.system( msmt, "mt /nologo /out:\""..embedded_manifest.."\" /manifest "..intermediate_manifest );
build.system( msrc, "rc /Fo\""..embedded_manifest_res.."\" "..embedded_manifest_rc, IgnoreOutputScanner );
end
objects = objects.." "..embedded_manifest_res;
ldflags = ldflags.." /incremental";
system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
system( msmt, "mt /nologo /out:\""..embedded_manifest.."\" /manifest "..intermediate_manifest );
system( msrc, "rc /Fo\""..embedded_manifest_res.."\" "..embedded_manifest_rc );
system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
build.system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
build.system( msmt, "mt /nologo /out:\""..embedded_manifest.."\" /manifest "..intermediate_manifest );
build.system( msrc, "rc /Fo\""..embedded_manifest_res.."\" "..embedded_manifest_rc, IgnoreOutputScanner );
build.system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
else
ldflags = ldflags.." /incremental:no";
system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
build.system( msld, "link"..ldflags..lddirs..objects..libraries..ldlibs );
sleep( 100 );
system( msmt, "mt /nologo -outputresource:"..out..";#1 -manifest "..intermediate_manifest );
build.system( msmt, "mt /nologo -outputresource:"..native(target:get_filename())..";#1 -manifest "..intermediate_manifest );
end
popd();
end
end
end;
function clean_executable( target )
if target:rule() == Executable then
rm( target.settings.bin.."/"..exe_name(target:id()) );
rm( target.settings.bin.."/"..ilk_name(target:id()) );
rmdir( obj_directory(target) );
function msvc.clean_executable( target, definition )
if target.module:prototype() == ExecutablePrototype then
rm( definition.settings.bin.."/"..exe_name(target:id()) );
rm( definition.settings.bin.."/"..ilk_name(target:id()) );
rmdir( obj_directory(target.module) );
else
rm( target.settings.bin.."/"..dll_name(target:id()) );
rm( target.settings.bin.."/"..ilk_name(target:id()) );
rm( target.settings.lib.."/"..lib_name(target:id()) );
rm( target.settings.lib.."/"..exp_name(target:id()) );
rmdir( obj_directory(target) );
rm( definition.settings.bin.."/"..dll_name(target:id()) );
rm( definition.settings.bin.."/"..ilk_name(target:id()) );
rm( definition.settings.lib.."/"..lib_name(target:id()) );
rm( definition.settings.lib.."/"..exp_name(target:id()) );
rmdir( obj_directory(target.module) );
end
end;
function msvc.lipo_executable( target )
end
function obj_directory( target )
return target.settings.obj.."/"..platform.."_"..variant.."/"..relative( target:directory(), root() ).."/";
function msvc.obj_directory( target )
return "%s/%s_%s/%s/" % { target.settings.obj, platform, variant, relative(target:directory(), root()) };
end
function cc_name( name )
return basename( name )..".c";
function msvc.cc_name( name )
return "%s.c" % basename( name );
end
function cxx_name( name )
return basename( name )..".cpp";
function msvc.cxx_name( name )
return "%s.cpp" % basename( name );
end
function pch_name( name )
return basename( name )..".pch";
function msvc.pch_name( name )
return "%s.pch" % basename( name );
end
function pdb_name( name )
return basename( name )..".pdb";
function msvc.pdb_name( name )
return "%s.pdb" % basename( name );
end
function obj_name( name )
return basename( name )..".obj";
function msvc.obj_name( name )
return "%s.obj" % basename( name );
end
function lib_name( name )
return name.."_"..platform.."_"..variant..".lib";
function msvc.lib_name( name )
return "%s_%s_%s.lib" % { name, platform, variant };
end
function exp_name( name )
return name.."_"..platform.."_"..variant..".exp";
function msvc.exp_name( name )
return "%s_%s_%s.exp" % { name, platform, variant };
end
function dll_name( name )
return name.."_"..platform.."_"..variant..".dll";
function msvc.dll_name( name )
return "%s_%s_%s.dll" % { name, platform, variant };
end
function exe_name( name )
return name.."_"..platform.."_"..variant..".exe";
function msvc.exe_name( name )
return "%s_%s_%s.exe" % { name, platform, variant };
end
function ilk_name( name )
return name.."_"..platform.."_"..variant..".ilk";
function msvc.ilk_name( name )
return "%s_%s_%s.ilk" % { name, platform, variant };
end

View file

@ -1,3 +1,3 @@
[footer-text]
Copyright (C) 2006 - 2011 Charles Baker. All rights reserved.
Copyright (C) 2006 - 2012 Charles Baker. All rights reserved.

View file

@ -1,7 +1,22 @@
--
visual_studio = {};
-- Generate a UUID by calling the uuidgen tool.
local function uuid()
local uuids = {};
local UuidScanner = Scanner {
[ [[([A-Za-z0-9\-]+)]] ] = function( uuid )
table.insert( uuids, uuid );
end;
};
local uuidgen = "%s/Common7/Tools/uuidgen.exe" % settings.msvc.visual_studio_directory;
local arguments = "uuidgen";
build.system( uuidgen, arguments, UuidScanner );
assert( uuids[1], "UUID generation failed!" );
return upper( uuids[1] );
end
-- Generate the header of the vcproj.
--
local function header( vcproj, target )
local name = target.project_name or target:id();
vcproj:write( [[
@ -19,9 +34,7 @@ local function header( vcproj, target )
);
end
--
-- Generate the footer of the vcproj.
--
local function footer( vcproj )
vcproj:write( [[
</VisualStudioProject>
@ -29,62 +42,67 @@ local function footer( vcproj )
);
end
--
-- Generate the configurations.
--
local function configurations( vcproj, target, include_directories )
vcproj:write( [[
<Configurations>
]]
);
pushd( target:directory() );
local module = target:id();
for variant, variant_settings in pairs(target.settings.variants) do
local output = "";
if target:rule() == Executable then
output = relative( target.settings.bin.."/"..module.."_"..platform.."_"..variant..".exe" );
end
local defines = "";
defines = defines.."BUILD_PLATFORM_"..upper(platform)..";";
defines = defines.."BUILD_VARIANT_"..upper(variant)..";";
defines = defines.."BUILD_MODULE_"..upper(string.gsub(module, "-", "_"))..";"
defines = defines.."BUILD_LIBRARY_TYPE_"..upper(variant_settings.library_type)..";";
if target.settings.defines then
for _, define in ipairs(target.settings.defines) do
defines = defines..define..";";
for _, platform in ipairs(target.settings.platforms) do
for _, variant in pairs(target.settings.variants) do
local variant_settings = target.settings.settings_by_variant[variant];
local output = "";
if target:prototype() == ExecutablePrototype then
output = relative( target.settings.bin.."/"..module.."_"..platform.."_"..variant..".exe" );
end
end
if target.defines then
for _, define in ipairs(target.defines) do
defines = defines..define..";";
local defines = "";
defines = defines.."BUILD_PLATFORM_"..upper(platform)..";";
defines = defines.."BUILD_VARIANT_"..upper(variant)..";";
defines = defines.."BUILD_MODULE_"..upper(string.gsub(module, "-", "_"))..";"
defines = defines.."BUILD_LIBRARY_TYPE_"..upper(variant_settings.library_type)..";";
if target.settings.defines then
for _, define in ipairs(target.settings.defines) do
defines = defines..define..";";
end
end
if target.defines then
for _, define in ipairs(target.defines) do
defines = defines..define..";";
end
end
end
vcproj:write( [[
<Configuration
Name="]]..variant..[[|Win32"
OutputDirectory="../../../../obj/]]..platform..[[_]]..variant..[[/]]..relative(target:directory(), root())..[["
IntermediateDirectory="../../../../obj/]]..platform..[[_]]..variant..[[/]]..relative(target:directory(), root())..[["
ConfigurationType="0"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="build command=build variant=]]..variant..[[ platform=]]..platform..[[ target=]]..target:id()..[["
ReBuildCommandLine="build command=clean variant=]]..variant..[[ platform=]]..platform..[[ target=]]..target:id()..[[ &#x0D;&#x0A; build command=build variant=]]..variant..[[ platform=]]..platform..[[ target=]]..target:id()..[["
CleanCommandLine="build command=clean variant=]]..variant..[[ platform=]]..platform..[[ target=]]..target:id()..[["
Output="]]..output..[["
PreprocessorDefinitions="]]..defines..[["
IncludeSearchPath="]]..include_directories..[["
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
]]
);
end
local build_tool = native( relative(root("build/build.exe")) );
vcproj:write( [[
<Configuration
Name="]]..platform..[[_]]..variant..[[|Win32"
OutputDirectory="../../../../obj/]]..platform..[[_]]..variant..[[/]]..relative(target:directory(), root())..[["
IntermediateDirectory="../../../../obj/]]..platform..[[_]]..variant..[[/]]..relative(target:directory(), root())..[["
ConfigurationType="0"
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="]]..build_tool..[[ variant=]]..variant..[[ platform=]]..platform..[[ goal=]]..target:id()..[["
ReBuildCommandLine="]]..build_tool..[[ clean default variant=]]..variant..[[ platform=]]..platform..[[ goal=]]..target:id()..[["
CleanCommandLine="]]..build_tool..[[ clean variant=]]..variant..[[ platform=]]..platform..[[ goal=]]..target:id()..[["
Output="]]..output..[["
PreprocessorDefinitions="]]..defines..[["
IncludeSearchPath="]]..include_directories..[["
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
</Configuration>
]]
);
end
end
popd();
vcproj:write( [[
</Configurations>
@ -92,9 +110,7 @@ local function configurations( vcproj, target, include_directories )
);
end
--
-- Write the beginning of the Files element.
--
local function begin_files( vcproj )
vcproj:write( [[
<Files>
@ -102,9 +118,7 @@ local function begin_files( vcproj )
);
end
--
-- Write the end of the Files element.
--
local function end_files( vcproj, module )
vcproj:write( [[
<File RelativePath=".\]]..leaf(module:directory())..[[.build" />
@ -113,58 +127,49 @@ local function end_files( vcproj, module )
);
end
--
-- Generate files in the project that match \e include_patterns and not
-- \e exclude_patterns.
--
local function files( vcproj, directory, include_patterns, exclude_patterns, level )
function match_( filename, patterns )
for _, pattern in ipairs(patterns) do
if string.match(filename, pattern) then
return true;
end
end
return false;
-- Generate files in the project.
local function generate_files( vcproj, directory, files, level )
pushd( directory );
for _, file in ipairs(files) do
vcproj:write( string.rep(" ", level) );
vcproj:write( "<File RelativePath=\""..native(relative(file:get_filename())).."\" />\n" );
end
vcproj:write( string.rep(" ", level) );
vcproj:write( "<Filter Name=\""..basename(directory).."\" Filter=\"\">\n" );
for entry in ls(directory) do
if is_file(entry) and match_(entry, include_patterns) and not match_(entry, exclude_patterns) then
vcproj:write( string.rep(" ", level + 1) );
vcproj:write( "<File RelativePath=\""..native(relative(entry)).."\" />\n" );
end
end
vcproj:write( string.rep(" ", level) );
vcproj:write( "</Filter>\n" );
popd();
end
--
-- Write out a Microsoft Visual Studio project for an Executable or Library.
--
function generate_visual_studio_project( filename, module )
-- Generate a Visual Studio project for /module/ to /filename/.
local function generate_project( filename, module )
print( filename );
local function populate_files( files, directory )
return function( target )
if target:directory() == directory and (target:prototype() == SourceFilePrototype or target:prototype() == HeaderFilePrototype) then
table.insert( files, target );
end
end
end
local include_directories = "";
for _, directory in ipairs(module.settings.include_directories) do
include_directories = include_directories..native(directory)..";";
end
local files = {};
preorder( populate_files(files, module:directory()), module );
local vcproj = io.open( absolute(filename), "wb" );
header( vcproj, module );
configurations( vcproj, module, include_directories );
begin_files( vcproj );
local include_patterns = { ".*%.c$", ".*%.cpp$", ".*%.h$", ".*%.hpp$", ".*%.ipp$", ".*%.lua$", ".*%.g$" };
local exclude_patterns = { "/moc_.*" };
files( vcproj, absolute("."), include_patterns, exclude_patterns, 2 );
generate_files( vcproj, module:directory(), files, 2 );
end_files( vcproj, module );
footer( vcproj );
vcproj:close();
end
function generate_visual_studio_solution( filename, solution )
-- Generate a Visual Studio solution for /solution/, containing /modules/
-- and /directories/ to /filename/.
local function generate_solution( filename, solution, modules, directories )
print( filename );
local sln = io.open( absolute(filename), "wb" );
@ -174,25 +179,204 @@ Microsoft Visual Studio Solution File, Format Version 10.00
]]
);
for target in solution:get_dependencies() do
if target:rule() == Project then
sln:write( string.format([[
Project("{}") = "%s", "%s.vcproj", "{}"
pushd( branch(absolute(filename)) );
local project_uuid = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
for path, module in pairs(modules) do
local name = module.target.project_name or module.target:id();
local filename = "%s%s.vcproj" % { module.target:directory(), name };
sln:write( string.format([[
Project("{%s}") = "%s", "%s", "{%s}"
EndProject
]], basename(target:get_id()), native(relative(target:path())))
);
end
]], project_uuid, name, native(relative(filename)), module.uuid)
);
end;
sln:write( [[
Project("{}") = "Solution Items", "Solution Items", "{}"
ProjectSection(SolutionItems) = preProject
build.hpp = build.hpp
build.lua = build.lua
EndProjectSection
local folder_uuid = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
local function generate_directories( directories )
for _, directory in ipairs(directories) do
if directory.children then
sln:write([[
Project("{%s}") = "%s", "%s", "{%s}"
EndProject
]]
% {folder_uuid, directory.target:id(), directory.target:id(), directory.uuid}
);
generate_directories( directory.children );
end
end
end
generate_directories( directories );
local build_hpp = native( relative(root("build.hpp")) );
local build_lua = native( relative(root("build.lua")) );
local local_settings_lua = native( relative(root("local_settings.lua")) );
sln:write( [[
Project("{%s}") = "Solution Items", "Solution Items", "{%s}"
ProjectSection(SolutionItems) = preProject
%s = %s
%s = %s
%s = %s
EndProjectSection
EndProject
]] % {folder_uuid, uuid(), build_hpp, build_hpp, build_lua, build_lua, local_settings_lua, local_settings_lua }
);
popd();
sln:write([[
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
]]
);
for _, platform in ipairs(build.settings.platforms) do
for _, variant in ipairs(build.settings.variants) do
sln:write([[
%s_%s|Win32 = %s_%s|Win32
]]
% {platform, variant, platform, variant}
);
end
end
sln:write([[
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
]]
);
for _, module in pairs(modules) do
for _, platform in ipairs(module.target.settings.platforms) do
for _, variant in ipairs(module.target.settings.variants) do
sln:write([[
{%s}.%s_%s|Win32.ActiveCfg = %s_%s|Win32
{%s}.%s_%s|Win32.Build.0 = %s_%s|Win32
]]
% {module.uuid, platform, variant, platform, variant, module.uuid, platform, variant, platform, variant}
);
end
end
end
sln:write([[
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
]]
);
local function generate_nested_projects( directory )
if directory and directory.children then
for _, child in ipairs(directory.children) do
sln:write([[
{%s} = {%s}
]]
% {child.uuid, directory.uuid}
);
end
for _, directory in ipairs(directory.children) do
generate_nested_projects( directory );
end
end
end
for _, directory in ipairs(directories) do
generate_nested_projects( directory );
end
sln:write([[
EndGlobalSection
EndGlobal
]]
);
sln:close();
end
-- Configure the Visual Studio module.
function visual_studio.configure()
end
-- Initiailize Visual Studio module.
function visual_studio.initialize()
end
-- Generate a Visual Studio solution and projects for the project and modules
-- that are dependencies of /root_target/ to /filename/.
function visual_studio.generate_solution_and_projects( filename, root_target )
local function populate( modules, directories )
local function add_directory( target )
local directory = directories[target:path()];
if directory == nil then
directory = { target = target; children = {} };
directories[target:path()] = directory;
if target:parent() then
local parent = add_directory( target:parent() );
table.insert( parent.children, directory );
end
end
return directory;
end
local function add_module( target )
local module = modules[target:path()];
if module == nil then
module = { target = target };
modules[target:path()] = module;
if target:parent() then
local parent = add_directory( target:parent() );
table.insert( parent.children, module );
end
end
return module;
end
return function( target )
if target:prototype() == ExecutablePrototype or target:prototype() == StaticLibraryPrototype or target:prototype() == DynamicLibraryPrototype then
add_module( target );
end
end
end
local function prune( directory )
if directory and directory.children then
if #directory.children == 1 then
local pruned_child = directory.children[1];
directory.uuid = pruned_child.uuid;
directory.target = pruned_child.target;
directory.children = pruned_child.children;
else
for _, child in ipairs(directory.children) do
prune( child );
end
end
end
end
local function generate_uuids( objects )
for _, object in pairs(objects) do
object.uuid = uuid();
end
end
local modules = {};
local directories = {};
preorder( populate(modules, directories), root_target );
generate_uuids( modules );
generate_uuids( directories );
prune( directories[root_target:path()] );
for path, module in pairs(modules) do
local name = module.target.project_name or module.target:id();
generate_project( "%s%s.vcproj" % {module.target:directory(), name}, module.target );
end
generate_solution( filename, root_target, modules, directories[root_target:path()].children );
end
-- The "sln" command entry point (global).
function sln()
build.load();
local all = all or find_target( root() );
assert( all, "No target found at '"..tostring(root()).."'" );
assert( settings.sln, "The solution filename is not specified by settings.sln" );
visual_studio.generate_solution_and_projects( settings.sln, all );
end

View file

@ -0,0 +1,375 @@
local id = 256;
local function uuid()
id = id + 1;
return "%08x%08x%08x" % { id, id, id };
end
local files = {};
local groups = {};
local targets = {};
local project_root = "";
local project_uuid = "";
local function add_group( target )
assert( target );
local path = target:path();
local group = groups[path];
if not group then
group = {
uuid = uuid();
target = target;
children = {};
};
groups[path] = group;
if target:parent() and target:path() ~= root() then
local parent = add_group( target:parent() );
table.insert( parent.children, group );
end
end
return group;
end
local function add_file( target )
assert( target );
if target:parent() then
local path = target:path();
local file = files[path];
if not file then
file = {
uuid = uuid();
target = target
};
files[path] = file;
local group = add_group( target:parent() );
table.insert( group.children, file );
end
end
return file;
end
local function add_target( module )
assert( module );
local path = module:path();
local target = targets[path];
if not target then
target = {
uuid = uuid();
target = module;
configurations = {};
configuration_list_uuid = uuid();
};
targets[path] = target;
local buildfile = absolute("%s.build" % module:id(), module:get_working_directory():path());
if exists(buildfile) then
add_file( File(buildfile) );
end
for _, variant in pairs(module.settings.variants) do
local configuration = {
uuid = uuid();
target = module;
variant = variant;
};
table.insert( target.configurations, configuration );
end
end
return target;
end
local function header( xcodeproj, project )
xcodeproj:write([[
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
]]
);
end;
local function generate_files( xcodeproj, files )
for path, file in pairs(files) do
xcodeproj:write([[
%s /* %s */ = { isa = PBXFileReference; lastKnownFileType = text; path = %s; sourceTree = "<group>"; };
]]
% { file.uuid, file.target:id(), file.target:id() }
);
end
end
local function generate_groups( xcodeproj, groups )
local sorted_groups = {};
for path, group in pairs(groups) do
table.insert( sorted_groups, group );
end
table.sort( sorted_groups, function(lhs, rhs) return lhs.target:id() < rhs.target:id() end );
for _, group in pairs(sorted_groups) do
xcodeproj:write([[
%s /* %s */ = {
isa = PBXGroup;
children = (
]]
% { group.uuid, group.target:path() }
);
table.sort( group.children, function(lhs, rhs)
local lhs_file = 0;
if is_file(lhs.target:path()) then
lhs_file = 1;
end
local rhs_file = 0;
if is_file(rhs.target:path()) then
rhs_file = 1;
end
return
lhs_file < rhs_file or
(lhs_file == rhs_file and lhs.target:id() < rhs.target:id())
;
end);
for _, child in ipairs(group.children) do
xcodeproj:write([[
%s /* %s */,
]]
% { child.uuid, child.target:id() }
);
end;
local base;
if group.target:parent() then
base = group.target:parent():path();
else
base = project_root;
end
xcodeproj:write([[
);
name = %s;
path = %s;
sourceTree = "<group>";
};
]] % { group.target:id(), relative(group.target:path(), base) }
);
end
end
local function generate_targets( xcodeproj, targets )
local sorted_targets = {};
for path, target in pairs(targets) do
table.insert( sorted_targets, target );
end
table.sort( sorted_targets, function(lhs, rhs) return lhs.target:id() < rhs.target:id() end );
for _, target in ipairs(sorted_targets) do
local name = target.target:id();
xcodeproj:write([[
%s /* %s */ = {
isa = PBXLegacyTarget;
buildArgumentsString = "variant=$(CONFIGURATION) action=$(ACTION) xcode_build";
buildConfigurationList = %s /* Build configuration list for PBXLegacyTarget "%s" */;
buildPhases = (
);
buildToolPath = %s;
buildWorkingDirectory = %s;
dependencies = (
);
name = %s;
passBuildSettingsInEnvironment = 1;
productName = %s;
};
]]
% { target.uuid, name, target.configuration_list_uuid, name, home("bin/build"), target.target:get_working_directory():path(), name, name }
);
end
end
local function generate_project( xcodeproj, groups )
local main_group = groups[root()];
assert( main_group, "The main group for the Xcode project wasn't found" );
project_uuid = uuid();
xcodeproj:write([[
%s /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
};
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = %s;
projectDirPath = "";
projectRoot = "";
targets = (
]]
% { project_uuid, main_group.uuid }
);
local sorted_targets = {};
for path, target in pairs(targets) do
table.insert( sorted_targets, target );
end
table.sort( sorted_targets, function(lhs, rhs) return lhs.target:id() < rhs.target:id() end );
for _, target in ipairs(sorted_targets) do
xcodeproj:write([[
%s /* %s */,
]]
% { target.uuid, target.target:id() }
);
end
xcodeproj:write([[
);
};
]]
);
end
local function generate_configurations( xcodeproj, targets )
local sorted_targets = {};
for path, target in pairs(targets) do
table.insert( sorted_targets, target );
end
table.sort( sorted_targets, function(lhs, rhs) return lhs.target:id() < rhs.target:id() end );
for _, target in pairs(sorted_targets) do
table.sort( target.configurations, function(lhs, rhs) return lhs.variant < rhs.variant end );
for _, configuration in ipairs(target.configurations) do
local archs = table.concat( target.target.settings.architectures or {}, " " );
xcodeproj:write([[
%s /* %s */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "%s";
VALID_ARCHS = "%s";
};
name = %s;
};
]]
% { configuration.uuid, target.target:id(), archs, archs, configuration.variant }
);
end
end
end
local function generate_configuration_lists( xcodeproj, targets )
local sorted_targets = {};
for path, target in pairs(targets) do
table.insert( sorted_targets, target );
end
table.sort( sorted_targets, function(lhs, rhs) return lhs.target:id() < rhs.target:id() end );
for _, target in pairs(sorted_targets) do
xcodeproj:write([[
%s /* Build configuration list for PBXLegacyTarget "%s" */ = {
isa = XCConfigurationList;
buildConfigurations = (
]]
% { target.configuration_list_uuid, target.target:id() }
);
for _, configuration in ipairs(target.configurations) do
xcodeproj:write([[
%s /* %s */,
]]
% { configuration.uuid, configuration.variant }
);
end
xcodeproj:write([[
);
defaultConfigurationIsVisible = 0;
};
]]
);
end
end
local function footer( xcodeproj, project )
xcodeproj:write([[
};
rootObject = %s /* Project object */;
}
]]
% project_uuid
);
end;
local function populate( target )
if target:prototype() == SourceFilePrototype or target:prototype() == HeaderFilePrototype then
add_file( target );
elseif target:prototype() == Directory then
add_group( target );
elseif target:prototype() == ExecutablePrototype then
add_target( target );
end
end
xcode = {};
function xcode.configure( settings )
end
function xcode.initialize( settings )
xcode.configure( settings );
end
function xcode.generate_project( name, project )
project_root = branch( name );
preorder( populate, project );
if exists(root("build.lua")) then
add_file( find_target(root("build.lua")) );
end
local xcodeproj_directory = "%s" % name;
if not exists(xcodeproj_directory) then
mkdir( xcodeproj_directory );
end
assert( is_directory(xcodeproj_directory), "The file '%s' already exists but is not a directory as expected" % xcodeproj_directory );
local xcodeproj = io.open( absolute("project.pbxproj", xcodeproj_directory), "wb" );
assert( xcodeproj, "Opening '%s' to write Xcode project file failed" % filename );
header( xcodeproj, project );
generate_files( xcodeproj, files );
generate_groups( xcodeproj, groups );
generate_targets( xcodeproj, targets );
generate_project( xcodeproj, groups );
generate_configurations( xcodeproj, targets );
generate_configuration_lists( xcodeproj, targets );
footer( xcodeproj, project );
xcodeproj:close();
end
-- The "xcodeproj" command entry point (global).
function xcodeproj()
build.load();
local all = all or find_target( root() );
assert( all, "No target found at '%s'" % root() );
assert( settings.xcodeproj, "The project filename is not specified by settings.xcodeproj" );
xcode.generate_project( settings.xcodeproj, all );
end
-- The "xcode_build" command entry point (global) this is used by generated
-- Xcode projects to trigger a build or clean.
function xcode_build()
action = action or "build";
if action == "" or action == "build" then
default();
elseif action == "clean" then
clean();
else
error( "Unable to map the Xcode action '%s' to a build command" % tostring(action) );
end
end

View file

@ -1,6 +1,6 @@
//
// AddOption.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "AddOption.hpp"

View file

@ -1,6 +1,6 @@
//
// AddOption.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_ADDOPTION_HPP_INCLUDED

View file

@ -1,6 +1,6 @@
//
// Error.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "Error.hpp"

View file

@ -1,6 +1,6 @@
//
// Error.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_ERROR_HPP_INCLUDED
@ -23,8 +23,8 @@ namespace cmdline
*/
enum ErrorCodes
{
CMDLINE_ERROR_NONE, ///< No error has occured.
CMDLINE_ERROR_INVALID_OPTION, ///< An option on the command line is not recognized or expects an argument and is grouped with other options.
CMDLINE_ERROR_NONE, ///< No error has occured.
CMDLINE_ERROR_INVALID_OPTION, ///< An option on the command line is not recognized or expects an argument and is grouped with other options.
CMDLINE_ERROR_INVALID_ARGUMENT ///< An option on the command line that requires an argument doesn't have one.
};

View file

@ -1,6 +1,6 @@
//
// Option.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "Option.hpp"

View file

@ -1,6 +1,6 @@
//
// Option.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_OPTION_HPP_INCLUDED

View file

@ -1,9 +1,13 @@
//
// Parser.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "Parser.hpp"
#include "Error.hpp"
#include <sweet/assert/assert.hpp>
#include <stdio.h>
#include <stdlib.h>
using std::vector;
using namespace sweet::cmdline;
@ -17,6 +21,10 @@ Parser::Parser()
{
}
void Parser::parse( int argc, char** argv ) const
{
parse( argc, const_cast<const char**>(argv) );
}
/**
// Parse a command line using the Options that have been added to this
@ -31,8 +39,7 @@ Parser::Parser()
// @return
// True if parsing the command line succeeded otherwise false.
*/
void
Parser::parse( int argc, char** argv ) const
void Parser::parse( int argc, const char** argv ) const
{
int argi = 1;
while ( argi < argc )
@ -96,7 +103,6 @@ Parser::parse( int argc, char** argv ) const
}
}
/**
// Print the Options that this Parser recognises to a stream.
//
@ -109,8 +115,7 @@ Parser::parse( int argc, char** argv ) const
// @return
// Nothing.
*/
void
Parser::print( FILE* stream, int width ) const
void Parser::print( FILE* stream, int width ) const
{
SWEET_ASSERT( stream );
@ -138,7 +143,6 @@ Parser::print( FILE* stream, int width ) const
}
}
/**
// Add Options to this Parser.
//
@ -146,13 +150,11 @@ Parser::print( FILE* stream, int width ) const
// An AddOption helper object that provides a convenient syntax for adding
// Options to this Parser.
*/
AddOption
Parser::add_options()
AddOption Parser::add_options()
{
return AddOption( &options_, &operands_ );
}
/**
// Is a command line argument a short option?
//
@ -162,14 +164,12 @@ Parser::add_options()
// @return
// True if \e argument is a short option otherwise false.
*/
bool
Parser::is_short_option( const char* argument ) const
bool Parser::is_short_option( const char* argument ) const
{
SWEET_ASSERT( argument != 0 );
return argument[0] == '-' && argument[1] != '-';
}
/**
// Is a command line argument a long option?
//
@ -179,14 +179,12 @@ Parser::is_short_option( const char* argument ) const
// @return
// True if \e argument is a long option otherwise false.
*/
bool
Parser::is_long_option( const char* argument ) const
bool Parser::is_long_option( const char* argument ) const
{
SWEET_ASSERT( argument != 0 );
return argument[0] == '-' && argument[1] == '-';
}
/**
// Find an Option by name.
//
@ -196,8 +194,7 @@ Parser::is_long_option( const char* argument ) const
// @return
// The Option or null if no matching Option was found.
*/
const Option*
Parser::find_option_by_name( const std::string& name ) const
const Option* Parser::find_option_by_name( const std::string& name ) const
{
vector<Option>::const_iterator option = options_.begin();
while ( option != options_.end() && option->get_name() != name )
@ -208,7 +205,6 @@ Parser::find_option_by_name( const std::string& name ) const
return option != options_.end() ? &(*option) : 0;
}
/**
// Find an Option by its short name.
//
@ -218,8 +214,7 @@ Parser::find_option_by_name( const std::string& name ) const
// @return
// The Option or null if no matching Option was found.
*/
const Option*
Parser::find_option_by_short_name( const std::string& short_name ) const
const Option* Parser::find_option_by_short_name( const std::string& short_name ) const
{
vector<Option>::const_iterator option = options_.begin();
while ( option != options_.end() && option->get_short_name() != short_name )
@ -230,7 +225,6 @@ Parser::find_option_by_short_name( const std::string& short_name ) const
return option != options_.end() ? &(*option) : 0;
}
/**
// Find the end of a name in a command line argument.
//
@ -243,10 +237,9 @@ Parser::find_option_by_short_name( const std::string& short_name ) const
// @return
// The end of the name in \e name.
*/
const char*
Parser::find_end_of_name( const char* name ) const
const char* Parser::find_end_of_name( const char* name ) const
{
SWEET_ASSERT( name != 0 );
SWEET_ASSERT( name );
while ( *name != 0 && *name != '=' )
{
@ -256,7 +249,6 @@ Parser::find_end_of_name( const char* name ) const
return name;
}
/**
// Find the beginning of the argument (if there is one) in a command line
// argument.
@ -270,10 +262,9 @@ Parser::find_end_of_name( const char* name ) const
// @return
// The beginning of the argument after \e name_end.
*/
const char*
Parser::find_argument( const char* name_end ) const
const char* Parser::find_argument( const char* name_end ) const
{
SWEET_ASSERT( name_end != 0 );
SWEET_ASSERT( name_end );
if ( *name_end != '=' )
{
@ -283,7 +274,6 @@ Parser::find_argument( const char* name_end ) const
return name_end;
}
/**
// Parse an Option.
//
@ -306,12 +296,11 @@ Parser::find_argument( const char* name_end ) const
// argument that was contained within the argument following the argument
// that the Option was in).
*/
int
Parser::parse_option( const Option* option, const char* argument, const char* next_argument ) const
int Parser::parse_option( const Option* option, const char* argument, const char* next_argument ) const
{
SWEET_ASSERT( option != 0 );
SWEET_ASSERT( option->get_address() != 0 );
SWEET_ASSERT( argument != 0 );
SWEET_ASSERT( option );
SWEET_ASSERT( option->get_address() );
SWEET_ASSERT( argument );
//
// If the Option is not a boolean option then it must have an argument that

View file

@ -1,15 +1,17 @@
//
// Parser.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_PARSER_HPP_INCLUDED
#define SWEET_CMDLINE_PARSER_HPP_INCLUDED
#include "cmdline.hpp"
#include "declspec.hpp"
#include "Option.hpp"
#include "AddOption.hpp"
#include <string>
#include <vector>
#include <stdio.h>
namespace sweet
{
@ -22,27 +24,23 @@ namespace cmdline
*/
class SWEET_CMDLINE_DECLSPEC Parser
{
std::vector<Option> options_; ///< The Options that this Parser will parse from the command line.
std::vector<std::string>* operands_; ///< The vector of strings that this Parser will parse operands from the command line into.
std::vector<Option> options_; ///< The Options that this Parser will parse from the command line.
std::vector<std::string>* operands_; ///< The vector of strings that this Parser will parse operands from the command line into.
public:
Parser();
AddOption add_options();
void parse( int argc, char** argv ) const;
void parse( int argc, const char** argv ) const;
void print( FILE* stream, int width = 12 ) const;
private:
bool is_short_option( const char* argument ) const;
bool is_long_option( const char* argument ) const;
const Option* find_option_by_name( const std::string& name ) const;
const Option* find_option_by_short_name( const std::string& short_name ) const;
const char* find_end_of_name( const char* name ) const;
const char* find_argument( const char* name_end ) const;
int parse_option( const Option* option, const char* argument, const char* next_argument ) const;
};

125
sweet/cmdline/Splitter.cpp Normal file
View file

@ -0,0 +1,125 @@
#include "Splitter.hpp"
#include <sweet/assert/assert.hpp>
#include <string.h>
using std::string;
using std::vector;
using namespace sweet::cmdline;
/**
// Constructor.
//
// @param command_line
// The string to split into arguments at whitespace characters while
// combining arguments surrounded by single or double quotes (assumed not
// null).
*/
Splitter::Splitter( const char* command_line )
: command_line_( command_line ),
arguments_()
{
SWEET_ASSERT( command_line );
const char DOUBLE_QUOTE = '"';
const char SINGLE_QUOTE = '\'';
const char BACKSLASH = '\\';
bool ended = true;
char quote = 0;
unsigned int length = strlen( command_line );
command_line_.insert( command_line_.end(), 0, length );
char* destination = &command_line_[0];
const char* i = command_line;
const char* end = i + length;
while ( i != end )
{
if ( !quote )
{
while ( i != end && isspace(*i) )
{
++i;
}
}
if ( i != end )
{
if ( *i == SINGLE_QUOTE || *i == DOUBLE_QUOTE )
{
quote = *i;
++i;
}
}
if ( i != end && ended )
{
ended = false;
arguments_.push_back( destination );
}
if ( i != end && quote )
{
while ( i != end && *i != quote )
{
if ( *i == BACKSLASH )
{
++i;
}
if ( i != end )
{
*destination = *i;
++i;
++destination;
}
}
quote = 0;
if ( i != end )
{
++i;
}
}
while ( i != end && !quote && !isspace(*i) )
{
if ( *i == DOUBLE_QUOTE || *i == SINGLE_QUOTE )
{
quote = *i;
++i;
}
else
{
if ( i != end && *i == BACKSLASH )
{
++i;
}
if ( i != end )
{
*destination = *i;
++i;
++destination;
}
}
}
if ( !quote )
{
ended = true;
*destination = 0;
++destination;
}
}
arguments_.push_back( NULL );
}
/**
// Get the arguments that the command line was split into.
//
// @return
// The arguments (including a NULL terminator as the last element as required
// by posix_spawn() etc).
*/
const std::vector<char*>& Splitter::arguments()
{
return arguments_;
}

View file

@ -0,0 +1,32 @@
#ifndef SWEET_CMDLINE_SPLITTER_HPP_INCLUDED
#define SWEET_CMDLINE_SPLITTER_HPP_INCLUDED
#include "declspec.hpp"
#include <string>
#include <vector>
namespace sweet
{
namespace cmdline
{
/**
// Split a string into an array of const char* suitable for passing to
// exec(), posix_spawn(), etc.
*/
class SWEET_CMDLINE_DECLSPEC Splitter
{
std::string command_line_;
std::vector<char*> arguments_;
public:
Splitter( const char* command_line );
const std::vector<char*>& arguments();
};
}
}
#endif

View file

@ -9,10 +9,11 @@ Library {
"error/error"
};
Cc {
Source {
"AddOption.cpp",
"Error.cpp",
"Option.cpp",
"Parser.cpp"
"Parser.cpp",
"Splitter.cpp"
};
}

View file

@ -1,16 +1,11 @@
//
// cmdline.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_HPP_INCLUDED
#define SWEET_CMDLINE_HPP_INCLUDED
#include <sweet/build.hpp>
#include <vector>
#include <sweet/assert/assert.hpp>
#include <sweet/error/Error.hpp>
#ifndef BUILD_MODULE_CMDLINE
#pragma comment( lib, "cmdline" BUILD_LIBRARY_SUFFIX )
#endif

View file

@ -1,10 +1,6 @@
//
// TestParser.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
//
#include <sweet/unit/UnitTest.h>
#include <sweet/cmdline/cmdline.hpp>
#include <sweet/cmdline/Parser.hpp>
using namespace sweet::cmdline;
@ -14,8 +10,8 @@ SUITE( TestParser )
{
bool boolean = false;
int argc = 2;
char* argv[] = { "", "-b" };
int argc = 2;
const char* argv[] = { "", "-b" };
Parser command_line_parser;
command_line_parser.add_options()
@ -30,8 +26,8 @@ SUITE( TestParser )
{
bool boolean = false;
int argc = 2;
char* argv[] = { "", "--boolean" };
int argc = 2;
const char* argv[] = { "", "--boolean" };
Parser command_line_parser;
command_line_parser.add_options()
@ -46,8 +42,8 @@ SUITE( TestParser )
{
int integer = 0;
int argc = 2;
char* argv[] = { "", "-i1" };
int argc = 2;
const char* argv[] = { "", "-i1" };
Parser command_line_parser;
command_line_parser.add_options()
@ -62,8 +58,8 @@ SUITE( TestParser )
{
int integer = 0;
int argc = 2;
char* argv[] = { "", "--integer=1" };
int argc = 2;
const char* argv[] = { "", "--integer=1" };
Parser command_line_parser;
command_line_parser.add_options()
@ -78,8 +74,8 @@ SUITE( TestParser )
{
float real = 0.0f;
int argc = 2;
char* argv[] = { "", "-r1.0" };
int argc = 2;
const char* argv[] = { "", "-r1.0" };
Parser command_line_parser;
command_line_parser.add_options()
@ -94,8 +90,8 @@ SUITE( TestParser )
{
float real = 0.0f;
int argc = 2;
char* argv[] = { "", "--real=1.0" };
int argc = 2;
const char* argv[] = { "", "--real=1.0" };
Parser command_line_parser;
command_line_parser.add_options()
@ -110,8 +106,8 @@ SUITE( TestParser )
{
std::string string;
int argc = 2;
char* argv[] = { "", "-sfoo" };
int argc = 2;
const char* argv[] = { "", "-sfoo" };
Parser command_line_parser;
command_line_parser.add_options()
@ -126,8 +122,8 @@ SUITE( TestParser )
{
std::string string;
int argc = 2;
char* argv[] = { "", "--string=foo" };
int argc = 2;
const char* argv[] = { "", "--string=foo" };
Parser command_line_parser;
command_line_parser.add_options()

View file

@ -0,0 +1,188 @@
#include <sweet/unit/UnitTest.h>
#include <sweet/cmdline/Splitter.hpp>
#include <sweet/assert/assert.hpp>
#include <string.h>
using namespace sweet::cmdline;
SUITE( TestSplitter )
{
static void test(const char* command_line, const char **arguments)
{
SWEET_ASSERT( command_line );
Splitter splitter( command_line );
int i = 0;
while ( i < int(splitter.arguments().size()) && splitter.arguments()[i] && arguments[i] )
{
CHECK( strcmp(splitter.arguments()[i], arguments[i]) == 0 );
++i;
}
CHECK( i == int(splitter.arguments().size()) - 1 );
CHECK( !splitter.arguments()[i] );
CHECK( !arguments[i] );
}
TEST( SpacedDoubleQuotes )
{
const char* COMMAND_LINE =
"-a \"foo bar baz\" blah"
;
const char* ARGUMENTS[] =
{
"-a",
"foo bar baz",
"blah",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( NonSpacedDoubleQuotes )
{
const char* COMMAND_LINE =
"-a\"foo bar baz\" blah"
;
const char* ARGUMENTS[] =
{
"-afoo bar baz",
"blah",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( SpacedSingleQuotes )
{
const char* COMMAND_LINE =
"-a 'foo bar baz' blah"
;
const char* ARGUMENTS[] =
{
"-a",
"foo bar baz",
"blah",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( NonSpacedSingleQuotes )
{
const char* COMMAND_LINE =
"-a'foo bar baz' blah"
;
const char* ARGUMENTS[] =
{
"-afoo bar baz",
"blah",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( GxxCommandLineWithNonSpacedDoubleQuotesAndEscapedDoubleQuotes )
{
const char* COMMAND_LINE =
"g++ -I\"/Users/charles/sweet/sweet_build_tool\" -I\"C:/boost/include/boost-1_43\" -DBUILD_PLATFORM_GCC -DBUILD_VARIANT_DEBUG "
"-DBUILD_LIBRARY_SUFFIX=\"\\\"_gcc_debug.lib\\\"\" -DBUILD_MODULE_ASSERT -DBUILD_LIBRARY_TYPE_STATIC -c -fpermissive "
"-Wno-deprecated -x c++ -static-libstdc++ -g -fexceptions -frtti "
"-o/Users/charles/sweet/sweet_build_tool/obj/gcc_debug/assert/stdafx.o stdafx.cpp"
;
const char* ARGUMENTS[] =
{
"g++",
"-I/Users/charles/sweet/sweet_build_tool",
"-IC:/boost/include/boost-1_43",
"-DBUILD_PLATFORM_GCC",
"-DBUILD_VARIANT_DEBUG",
"-DBUILD_LIBRARY_SUFFIX=\"_gcc_debug.lib\"",
"-DBUILD_MODULE_ASSERT",
"-DBUILD_LIBRARY_TYPE_STATIC",
"-c",
"-fpermissive",
"-Wno-deprecated",
"-x",
"c++",
"-static-libstdc++",
"-g",
"-fexceptions",
"-frtti",
"-o/Users/charles/sweet/sweet_build_tool/obj/gcc_debug/assert/stdafx.o",
"stdafx.cpp",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( GxxCommandLineWithSpacedDoubleQuotes )
{
const char *COMMAND_LINE =
"g++ -lbuild_tool_gcc_debug -lcmdline_gcc_debug -llua_gcc_debug -lliblua_gcc_debug "
"-lprocess_gcc_debug -lrtti_gcc_debug -lthread_gcc_debug -lpersist_gcc_debug "
"-lpath_gcc_debug -lpointer_gcc_debug -lerror_gcc_debug -lassert_gcc_debug "
"-llibboost_filesystem.a -llibboost_regex.a -llibboost_system.a -llibboost_thread.a "
"stdafx.o Application.o main.o "
"-o /Users/charles/sweet/sweet_build_tool/bin/build_gcc_debug "
"-static-libstdc++ -debug "
"-L \"/Users/charles/sweet/sweet_build_tool/lib\" "
"-L \"/Users/charles/boost/boost_1_43_0/stage/lib\""
;
const char* ARGUMENTS[] =
{
"g++",
"-lbuild_tool_gcc_debug",
"-lcmdline_gcc_debug",
"-llua_gcc_debug",
"-lliblua_gcc_debug",
"-lprocess_gcc_debug",
"-lrtti_gcc_debug",
"-lthread_gcc_debug",
"-lpersist_gcc_debug",
"-lpath_gcc_debug",
"-lpointer_gcc_debug",
"-lerror_gcc_debug",
"-lassert_gcc_debug",
"-llibboost_filesystem.a",
"-llibboost_regex.a",
"-llibboost_system.a",
"-llibboost_thread.a",
"stdafx.o",
"Application.o",
"main.o",
"-o",
"/Users/charles/sweet/sweet_build_tool/bin/build_gcc_debug",
"-static-libstdc++",
"-debug",
"-L",
"/Users/charles/sweet/sweet_build_tool/lib",
"-L",
"/Users/charles/boost/boost_1_43_0/stage/lib",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( UnterminatedSingleQuotedString )
{
const char* COMMAND_LINE = "'This is an unterminated string";
const char* ARGUMENTS[] =
{
"This is an unterminated string",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
TEST( UnterminatedDoubleQuotedString )
{
const char* COMMAND_LINE = "\"This is an unterminated string";
const char* ARGUMENTS[] =
{
"This is an unterminated string",
NULL
};
test( COMMAND_LINE, ARGUMENTS );
}
}

View file

@ -3,13 +3,15 @@ Executable {
id = "cmdline_test";
libraries = {
"assert/assert",
"cmdline/cmdline",
"error/error",
"assert/assert",
"unit/libUnitTest"
};
Cc {
Source {
"main.cpp",
"TestParser.cpp"
"TestParser.cpp",
"TestSplitter.cpp"
};
}

View file

@ -1,6 +1,6 @@
//
// declspec.hpp
// Copyright (c) 2011 Charles Baker. All rights reserved.
// Copyright (c) 2011 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_CMDLINE_DECLSPEC_HPP_INCLUDED

View file

@ -1,13 +1,17 @@
//
// Error.cpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"
#include <sweet/error/Error.hpp>
#include <sweet/assert/assert.hpp>
#include <memory.h>
#include <stdio.h>
#if defined(BUILD_OS_WINDOWS)
#include <windows.h>
#endif
using namespace sweet::error;
@ -46,7 +50,7 @@ Error::Error( int error, const char* format, ... )
/**
// Destructor.
*/
Error::~Error()
Error::~Error() throw ()
{
}
@ -67,7 +71,7 @@ int Error::error() const
// @return
// The text.
*/
const char* Error::what() const
const char* Error::what() const throw ()
{
return text_;
}
@ -82,7 +86,7 @@ const char* Error::what() const
// A variable length argument list that matches that arguments in @e
// format.
*/
void Error::append( const char* format, va_list& args )
void Error::append( const char* format, va_list args )
{
if ( format )
{
@ -93,7 +97,7 @@ void Error::append( const char* format, va_list& args )
++pos;
}
_vsnprintf( pos, end - pos, format, args );
vsnprintf( pos, end - pos, format, args );
text_[sizeof(text_) - 1] = '\0';
}
}
@ -115,7 +119,7 @@ void Error::append( const char* text )
++pos;
}
_snprintf( pos, end - pos, text );
strncpy( pos, text, end - pos );
text_[sizeof(text_) - 1] = '\0';
}
}
@ -135,15 +139,18 @@ void Error::append( const char* text )
// @return
// The buffer.
*/
const char* Error::format( int oserror, char* buffer, size_t length )
const char* Error::format( int oserror, char* buffer, unsigned int length )
{
SWEET_ASSERT( buffer );
SWEET_ASSERT( length > 0 );
#if defined(BUILD_OS_WINDOWS)
int actual_length = ::FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, 0, oserror, 0, buffer, static_cast<int>(length), 0 );
while ( actual_length > 0 && (buffer[actual_length] == '\n' || buffer[actual_length] == '\r' || buffer[actual_length] == '.' || buffer[actual_length] == 0) )
{
buffer[actual_length] = 0;
--actual_length;
}
#elif defined(BUILD_OS_MACOSX)
strerror_r( oserror, buffer, length );
#endif
return buffer;
}

View file

@ -1,6 +1,6 @@
//
// Error.hpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ERROR_ERROR_HPP_INCLUDED
@ -9,8 +9,7 @@
#include "declspec.hpp"
#include "macros.hpp"
#include <exception>
typedef char* va_list;
#include <stdarg.h>
namespace sweet
{
@ -29,13 +28,13 @@ class SWEET_ERROR_DECLSPEC Error : virtual public std::exception
public:
explicit Error( int error );
Error( int error, const char* format, ... );
virtual ~Error();
virtual ~Error() throw ();
int error() const;
const char* what() const;
static const char* format( int oserror, char* buffer, size_t length );
const char* what() const throw ();
static const char* format( int oserror, char* buffer, unsigned int length );
protected:
void append( const char* format, va_list& args );
void append( const char* format, va_list args );
void append( const char* text );
};

View file

@ -1,6 +1,6 @@
//
// ErrorPolicy.cpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"

View file

@ -1,6 +1,6 @@
//
// ErrorPolicy.hpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ERROR_ERRORPOLICY_HPP_INCLUDED

View file

@ -1,6 +1,6 @@
//
// ErrorTemplate.hpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ERROR_ERRORTEMPLATE_HPP_INCLUDED

View file

@ -1,6 +1,6 @@
//
// ErrorTemplate.ipp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ERROR_ERRORTEMPLATE_IPP_INCLUDED
@ -30,7 +30,7 @@ ErrorTemplate<ERRNO, Base>::ErrorTemplate( const char* format, ... )
{
va_list args;
va_start( args, format );
append( format, args );
Error::append( format, args );
va_end( args );
}
@ -47,7 +47,7 @@ template <int ERRNO, class Base>
ErrorTemplate<ERRNO, Base>::ErrorTemplate( const char* format, va_list args )
: Base( ERRNO )
{
append( format, args );
Error::append( format, args );
}
}

View file

@ -1,6 +1,6 @@
//
// boost-integration.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// boost_integration.cpp
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"

View file

@ -1,17 +1,17 @@
//
// declspec.hpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_ERROR_DECLSPEC_HPP_INCLUDED
#define SWEET_ERROR_DECLSPEC_HPP_INCLUDED
#if defined(BUILD_MODULE_ERROR) && defined(BUILD_LIBRARY_TYPE_DYNAMIC)
#if defined(BUILD_OS_WINDOWS) && defined(BUILD_MODULE_ERROR) && defined(BUILD_LIBRARY_TYPE_DYNAMIC)
#define SWEET_ERROR_DECLSPEC __declspec(dllexport)
#elif defined(BUILD_LIBRARY_TYPE_DYNAMIC)
#elif defined(BUILD_OS_WINDOWS) && defined(BUILD_LIBRARY_TYPE_DYNAMIC)
#define SWEET_ERROR_DECLSPEC __declspec(dllimport)
#else
#define SWEET_ERROR_DECLSPEC
#endif
#endif
#endif

View file

@ -1,6 +1,6 @@
//
// dinkumware_integration.cpp
// Copyright (c) 2008 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"

View file

@ -8,7 +8,7 @@ Library {
"assert/assert"
};
Cc {
Source {
pch = "stdafx.hpp";
"boost_integration.cpp",
"dinkumware_integration.cpp",

View file

@ -8,7 +8,7 @@ Executable {
"unit/libUnitTest"
};
Cc {
Source {
pch = "stdafx.hpp";
"main.cpp"
};

View file

@ -1,6 +1,6 @@
//
// error_functions.cpp
// Copyright (c) 2001 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2001 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"
@ -68,9 +68,9 @@ void error( const Error& error )
}
else
{
::fputs( error.what(), stderr );
::fputs( ".\n", stderr );
::exit( EXIT_FAILURE );
fputs( error.what(), stderr );
fputs( ".\n", stderr );
exit( EXIT_FAILURE );
}
}
@ -93,9 +93,9 @@ void error( const std::exception& exception )
}
else
{
::fputs( exception.what(), stderr );
::fputs( ".\n", stderr );
::exit( EXIT_FAILURE );
fputs( exception.what(), stderr );
fputs( ".\n", stderr );
exit( EXIT_FAILURE );
}
}

View file

@ -6,4 +6,6 @@
#define _SCL_SECURE_NO_DEPRECATE
#define NOMINMAX
#include <windows.h>
#if defined(BUILD_OS_WINDOWS)
#include <windows.h>
#endif

View file

@ -6,7 +6,11 @@
#ifndef SWEET_LEXER_LEXER_HPP_INCLUDED
#define SWEET_LEXER_LEXER_HPP_INCLUDED
#if defined(BUILD_PLATFORM_MSVC)
#include <functional>
#else
#include <tr1/functional>
#endif
namespace sweet
{
@ -22,7 +26,7 @@ class LexerErrorPolicy;
/**
// A lexical analyzer.
*/
template <class Iterator, class Char = std::iterator_traits<Iterator>::value_type, class Traits = std::char_traits<Char>, class Allocator = std::allocator<Char>>
template <class Iterator, class Char = typename std::iterator_traits<Iterator>::value_type, class Traits = typename std::char_traits<Char>, class Allocator = typename std::allocator<Char> >
class Lexer
{
typedef std::tr1::function<void (Iterator* begin, Iterator end, std::basic_string<Char, Traits, Allocator>* lexeme, const void** symbol)> LexerActionFunction;

View file

@ -67,7 +67,7 @@ Lexer<Iterator, Char, Traits, Allocator>::Lexer( const LexerStateMachine* state_
if ( state_machine_ )
{
action_handlers_.reserve( state_machine_->actions().size() );
for ( std::vector<ptr<LexerAction>>::const_iterator i = state_machine_->actions().begin(); i != state_machine_->actions().end(); ++i )
for ( std::vector<ptr<LexerAction> >::const_iterator i = state_machine_->actions().begin(); i != state_machine_->actions().end(); ++i )
{
LexerAction* action = i->get();
SWEET_ASSERT( action );
@ -90,7 +90,7 @@ void Lexer<Iterator, Char, Traits, Allocator>::set_action_handler( const char* i
{
SWEET_ASSERT( identifier );
std::vector<LexerActionHandler>::iterator action_handler = action_handlers_.begin();
typename std::vector<LexerActionHandler>::iterator action_handler = action_handlers_.begin();
while ( action_handler != action_handlers_.end() && action_handler->action_->get_identifier() != identifier )
{
++action_handler;

View file

@ -13,6 +13,7 @@
#include "LexerErrorPolicy.hpp"
#include "RegexNode.hpp"
#include "RegexParser.hpp"
#include <limits.h>
using std::pair;
using std::vector;
@ -63,7 +64,7 @@ LexerGenerator::LexerGenerator( const std::vector<LexerToken>& tokens, const std
// @return
// The actions.
*/
std::vector<ptr<LexerAction>>& LexerGenerator::actions()
std::vector<ptr<LexerAction> >& LexerGenerator::actions()
{
return actions_;
}
@ -74,7 +75,7 @@ std::vector<ptr<LexerAction>>& LexerGenerator::actions()
// @return
// The generated states.
*/
std::set<ptr<LexerState>, ptr_less<LexerState>>& LexerGenerator::states()
std::set<ptr<LexerState>, ptr_less<LexerState> >& LexerGenerator::states()
{
return states_;
}
@ -85,7 +86,7 @@ std::set<ptr<LexerState>, ptr_less<LexerState>>& LexerGenerator::states()
// @return
// The generated whitespace states.
*/
std::set<ptr<LexerState>, ptr_less<LexerState>>& LexerGenerator::whitespace_states()
std::set<ptr<LexerState>, ptr_less<LexerState> >& LexerGenerator::whitespace_states()
{
return whitespace_states_;
}
@ -135,7 +136,7 @@ const lexer::LexerAction* LexerGenerator::add_lexer_action( const std::string& i
if ( !identifier.empty() )
{
std::vector<ptr<lexer::LexerAction>>::const_iterator i = actions_.begin();
std::vector<ptr<lexer::LexerAction> >::const_iterator i = actions_.begin();
while ( i != actions_.end() && (*i)->get_identifier() != identifier )
{
++i;
@ -247,7 +248,7 @@ ptr<LexerState> LexerGenerator::goto_( const LexerState* state, int begin, int e
// A variable to receive the starting state for the lexical analyzer
// (assumed not null).
*/
void LexerGenerator::generate_states( const RegexParser& regex_parser, std::set<ptr<LexerState>, ptr_less<LexerState>>* states, const LexerState** start_state )
void LexerGenerator::generate_states( const RegexParser& regex_parser, std::set<ptr<LexerState>, ptr_less<LexerState> >* states, const LexerState** start_state )
{
SWEET_ASSERT( states );
SWEET_ASSERT( states->empty() );
@ -266,7 +267,7 @@ void LexerGenerator::generate_states( const RegexParser& regex_parser, std::set<
while ( added > 0 )
{
added = 0;
for ( std::set<ptr<LexerState>, ptr_less<LexerState>>::const_iterator i = states->begin(); i != states->end(); ++i )
for ( std::set<ptr<LexerState>, ptr_less<LexerState> >::const_iterator i = states->begin(); i != states->end(); ++i )
{
LexerState* state = i->get();
SWEET_ASSERT( state );
@ -299,7 +300,7 @@ void LexerGenerator::generate_states( const RegexParser& regex_parser, std::set<
// Create a goto state and a transition from the current
// state for each distinct range.
//
vector<pair<int, bool>>::const_iterator j = ranges_.begin();
vector<pair<int, bool> >::const_iterator j = ranges_.begin();
while ( j != ranges_.end() )
{
int begin = (j + 0)->first;
@ -340,7 +341,7 @@ void LexerGenerator::generate_indices_for_states()
{
int index = 0;
for ( std::set<ptr<LexerState>, ptr_less<LexerState>>::iterator i = states_.begin(); i != states_.end(); ++i )
for ( std::set<ptr<LexerState>, ptr_less<LexerState> >::iterator i = states_.begin(); i != states_.end(); ++i )
{
LexerState* state = i->get();
SWEET_ASSERT( state );
@ -348,7 +349,7 @@ void LexerGenerator::generate_indices_for_states()
++index;
}
for ( std::set<ptr<LexerState>, ptr_less<LexerState>>::iterator i = whitespace_states_.begin(); i != whitespace_states_.end(); ++i )
for ( std::set<ptr<LexerState>, ptr_less<LexerState> >::iterator i = whitespace_states_.begin(); i != whitespace_states_.end(); ++i )
{
LexerState* state = i->get();
SWEET_ASSERT( state );
@ -443,7 +444,7 @@ void LexerGenerator::insert( int begin, int end )
{
bool in = false;
vector<pair<int, bool>>::iterator i = ranges_.begin();
vector<pair<int, bool> >::iterator i = ranges_.begin();
while ( i != ranges_.end() && i->first < begin )
{
in = i->second;

View file

@ -38,20 +38,20 @@ class RegexParser;
class LexerGenerator
{
LexerErrorPolicy* event_sink_; ///< The event sink to report errors and debug information to or null to ignore errors and debug information.
std::vector<ptr<LexerAction>> actions_; ///< The lexical analyzer actions.
std::set<ptr<LexerState>, ptr_less<LexerState>> states_; ///< The states generated for the lexical analyzer.
std::set<ptr<LexerState>, ptr_less<LexerState>> whitespace_states_; ///< The states generated for the whitespace lexical analyzer.
std::vector<ptr<LexerAction> > actions_; ///< The lexical analyzer actions.
std::set<ptr<LexerState>, ptr_less<LexerState> > states_; ///< The states generated for the lexical analyzer.
std::set<ptr<LexerState>, ptr_less<LexerState> > whitespace_states_; ///< The states generated for the whitespace lexical analyzer.
const LexerState* start_state_; ///< The starting state for the lexical analyzer.
const LexerState* whitespace_start_state_; ///< The starting state for the whitespace lexical analyzer.
std::vector<std::pair<int, bool>> ranges_; ///< Ranges generated for the current transition while generating.
std::vector<std::pair<int, bool> > ranges_; ///< Ranges generated for the current transition while generating.
public:
LexerGenerator( const LexerToken& token, LexerErrorPolicy* event_sink );
LexerGenerator( const std::vector<LexerToken>& tokens, const std::vector<LexerToken>& whitespace_tokens, LexerErrorPolicy* event_sink );
std::vector<ptr<LexerAction>>& actions();
std::set<ptr<LexerState>, ptr_less<LexerState>>& states();
std::set<ptr<LexerState>, ptr_less<LexerState>>& whitespace_states();
std::vector<ptr<LexerAction> >& actions();
std::set<ptr<LexerState>, ptr_less<LexerState> >& states();
std::set<ptr<LexerState>, ptr_less<LexerState> >& whitespace_states();
const LexerState* start_state() const;
const LexerState* whitespace_start_state() const;
const lexer::LexerAction* add_lexer_action( const std::string& identifier );
@ -61,7 +61,7 @@ class LexerGenerator
private:
ptr<LexerState> goto_( const LexerState* state, int begin, int end );
void generate_states( const RegexParser& regular_expression_parser, std::set<ptr<LexerState>, ptr_less<LexerState>>* states, const LexerState** start_state );
void generate_states( const RegexParser& regular_expression_parser, std::set<ptr<LexerState>, ptr_less<LexerState> >* states, const LexerState** start_state );
void generate_indices_for_states();
void generate_symbol_for_state( LexerState* state ) const;

View file

@ -6,10 +6,16 @@
#include "stdafx.hpp"
#include "LexerItem.hpp"
#include "RegexNode.hpp"
#include <string>
#include <stdio.h>
using namespace sweet;
using namespace sweet::lexer;
#if defined(BUILD_PLATFORM_MSVC)
#define snprintf _snprintf
#endif
/**
// Constructor.
*/
@ -159,7 +165,7 @@ void LexerItem::describe( std::string* description ) const
const RegexNode* node = *i;
SWEET_ASSERT( node );
char buffer [32];
_snprintf( buffer, sizeof(buffer), "%d ", node->get_index() );
snprintf( buffer, sizeof(buffer), "%d ", node->get_index() );
buffer [sizeof(buffer) - 1] = '\0';
description->append( buffer );
}

View file

@ -9,6 +9,7 @@
#include "declspec.hpp"
#include "RegexNodeLess.hpp"
#include <sweet/pointer/ptr.hpp>
#include <string>
#include <set>
namespace sweet

View file

@ -7,10 +7,15 @@
#include "LexerState.hpp"
#include "LexerItem.hpp"
#include "LexerTransition.hpp"
#include <stdio.h>
using namespace sweet;
using namespace sweet::lexer;
#if defined(BUILD_PLATFORM_MSVC)
#define snprintf _snprintf
#endif
/**
// Constructor.
*/
@ -201,7 +206,7 @@ void LexerState::describe( std::string* description ) const
SWEET_ASSERT( description );
char buffer [512];
_snprintf( buffer, sizeof(buffer), "%d (0x%08x):\n", index_, symbol_ );
snprintf( buffer, sizeof(buffer), "%d (%p):\n", index_, symbol_ );
buffer [sizeof(buffer) - 1] = '\0';
description->append( buffer );

View file

@ -101,7 +101,7 @@ const std::string& LexerStateMachine::identifier() const
// @return
// The actions.
*/
const std::vector<ptr<LexerAction>>& LexerStateMachine::actions() const
const std::vector<ptr<LexerAction> >& LexerStateMachine::actions() const
{
return actions_;
}
@ -112,7 +112,7 @@ const std::vector<ptr<LexerAction>>& LexerStateMachine::actions() const
// @return
// The states.
*/
const std::vector<ptr<LexerState>>& LexerStateMachine::states() const
const std::vector<ptr<LexerState> >& LexerStateMachine::states() const
{
return states_;
}
@ -123,7 +123,7 @@ const std::vector<ptr<LexerState>>& LexerStateMachine::states() const
// @return
// The whitespace states.
*/
const std::vector<ptr<LexerState>>& LexerStateMachine::whitespace_states() const
const std::vector<ptr<LexerState> >& LexerStateMachine::whitespace_states() const
{
return whitespace_states_;
}
@ -159,7 +159,7 @@ const LexerState* LexerStateMachine::whitespace_start_state() const
void LexerStateMachine::describe( std::string* description ) const
{
SWEET_ASSERT( description );
std::vector<ptr<LexerState>>::const_iterator i = states_.begin();
std::vector<ptr<LexerState> >::const_iterator i = states_.begin();
while ( i != states_.end() )
{
const LexerState* state = i->get();

View file

@ -29,9 +29,9 @@ class LexerErrorPolicy;
class SWEET_LEXER_DECLSPEC LexerStateMachine
{
std::string identifier_; ///< The identifier of this LexerStateMachine.
std::vector<ptr<lexer::LexerAction>> actions_; ///< The lexer actions for this ParserStateMachine.
std::vector<ptr<LexerState>> states_; ///< The states that make up the state machine for this LexerStateMachine.
std::vector<ptr<LexerState>> whitespace_states_; ///< The states that make up the state machine for whitespace in this LexerStateMachine.
std::vector<ptr<lexer::LexerAction> > actions_; ///< The lexer actions for this ParserStateMachine.
std::vector<ptr<LexerState> > states_; ///< The states that make up the state machine for this LexerStateMachine.
std::vector<ptr<LexerState> > whitespace_states_; ///< The states that make up the state machine for whitespace in this LexerStateMachine.
const LexerState* start_state_; ///< The starting state for the state machine.
const LexerState* whitespace_start_state_; ///< The starting state for the whitespace state machine.
@ -40,9 +40,9 @@ class SWEET_LEXER_DECLSPEC LexerStateMachine
LexerStateMachine( const std::string& identifier, const std::vector<LexerToken>& tokens, const std::vector<LexerToken>& whitespace_tokens = std::vector<LexerToken>(), LexerErrorPolicy* event_sink = NULL );
const std::string& identifier() const;
const std::vector<ptr<LexerAction>>& actions() const;
const std::vector<ptr<LexerState>>& states() const;
const std::vector<ptr<LexerState>>& whitespace_states() const;
const std::vector<ptr<LexerAction> >& actions() const;
const std::vector<ptr<LexerState> >& states() const;
const std::vector<ptr<LexerState> >& whitespace_states() const;
const LexerState* start_state() const;
const LexerState* whitespace_start_state() const;
void describe( std::string* description ) const;

View file

@ -8,9 +8,14 @@
#include "LexerAction.hpp"
#include "LexerState.hpp"
#include <sweet/assert/assert.hpp>
#include <stdio.h>
using namespace sweet::lexer;
#if defined(BUILD_PLATFORM_MSVC)
#define snprintf _snprintf
#endif
/**
// Constructor.
//
@ -109,7 +114,7 @@ void LexerTransition::describe( std::string* description ) const
SWEET_ASSERT( state_ );
char buffer [512];
_snprintf( buffer, sizeof(buffer), "to %d on ['%c' %d, '%c' %d) %s",
snprintf( buffer, sizeof(buffer), "to %d on ['%c' %d, '%c' %d) %s",
state_->get_index(),
begin_ > 32 && begin_ < 128 ? begin_ : '.',
begin_,

View file

@ -7,6 +7,7 @@
#include "RegexNode.hpp"
#include "LexerAction.hpp"
#include <algorithm>
#include <stdio.h>
#include <limits.h>
using std::find;
@ -323,7 +324,7 @@ RegexNode* RegexNode::get_node( int n ) const
// @return
// The child nodes.
*/
const std::vector<ptr<RegexNode>>& RegexNode::get_nodes() const
const std::vector<ptr<RegexNode> >& RegexNode::get_nodes() const
{
return nodes_;
}
@ -393,7 +394,7 @@ const std::set<RegexNode*, RegexNodeLess>& RegexNode::get_next_positions() const
*/
void RegexNode::calculate_nullable()
{
for ( std::vector<ptr<RegexNode>>::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
for ( std::vector<ptr<RegexNode> >::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
{
RegexNode* node = i->get();
SWEET_ASSERT( node );
@ -446,7 +447,7 @@ void RegexNode::calculate_nullable()
*/
void RegexNode::calculate_first_positions()
{
for ( std::vector<ptr<RegexNode>>::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
for ( std::vector<ptr<RegexNode> >::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
{
RegexNode* node = i->get();
SWEET_ASSERT( node );
@ -498,7 +499,7 @@ void RegexNode::calculate_first_positions()
*/
void RegexNode::calculate_last_positions()
{
for ( std::vector<ptr<RegexNode>>::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
for ( std::vector<ptr<RegexNode> >::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
{
RegexNode* node = i->get();
SWEET_ASSERT( node );
@ -550,7 +551,7 @@ void RegexNode::calculate_last_positions()
*/
void RegexNode::calculate_follow_positions()
{
for ( std::vector<ptr<RegexNode>>::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
for ( std::vector<ptr<RegexNode> >::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
{
RegexNode* node = i->get();
SWEET_ASSERT( node );
@ -662,7 +663,7 @@ void RegexNode::print( const std::set<RegexNode*>& dot_nodes ) const
printf( "%s", action_ != NULL ? action_->get_identifier().c_str() : "null" );
}
for ( std::vector<ptr<RegexNode>>::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
for ( std::vector<ptr<RegexNode> >::const_iterator i = nodes_.begin(); i != nodes_.end(); ++i )
{
const ptr<RegexNode>& node = *i;
node->print( dot_nodes );

View file

@ -71,7 +71,7 @@ class RegexNode : public pointer::enable_ptr_from_this<RegexNode>
int end_character_; ///< One past the last character in the interval of characters represented by the node.
const LexerToken* token_; ///< The token recognized at the node or null if the node doesn't recognize a token.
const LexerAction* action_; ///< The action taken at the node or null if no action is taken at the node.
std::vector<ptr<RegexNode>> nodes_; ///< The child nodes.
std::vector<ptr<RegexNode> > nodes_; ///< The child nodes.
bool nullable_; ///< True if the node is nullable otherwise false.
std::set<RegexNode*, RegexNodeLess> first_positions_; ///< The first positions at the node.
std::set<RegexNode*, RegexNodeLess> last_positions_; ///< The last positions at the node.
@ -96,7 +96,7 @@ class RegexNode : public pointer::enable_ptr_from_this<RegexNode>
void add_node( const ptr<RegexNode>& node );
RegexNode* get_node( int index ) const;
const std::vector<ptr<RegexNode>>& get_nodes() const;
const std::vector<ptr<RegexNode> >& get_nodes() const;
bool is_nullable() const;
const std::set<RegexNode*, RegexNodeLess>& get_first_positions() const;

View file

@ -32,7 +32,7 @@ namespace lexer
// ParserGrammar for regular expressions.
*/
template <class Iterator>
class RegexGrammar : public boost::spirit::grammar<RegexGrammar<Iterator>>
class RegexGrammar : public boost::spirit::grammar<RegexGrammar<Iterator> >
{
public:
typedef Iterator iterator;
@ -1037,9 +1037,9 @@ void RegexParser::print_positions( const std::set<RegexNode*, RegexNodeLess>& po
// @param level
// The recursion level to use when identing lines.
*/
void RegexParser::print_nodes( const vector<ptr<RegexNode>>& nodes, int level ) const
void RegexParser::print_nodes( const vector<ptr<RegexNode> >& nodes, int level ) const
{
for ( vector<ptr<RegexNode>>::const_iterator i = nodes.begin(); i != nodes.end(); ++i )
for ( vector<ptr<RegexNode> >::const_iterator i = nodes.begin(); i != nodes.end(); ++i )
{
static const char* LEXER_NODE_TYPES [LEXER_NODE_COUNT] =
{

View file

@ -35,7 +35,7 @@ class RegexParser
LexerGenerator* lexer_generator_; ///< The LexerGenerator to retrieve actions from and report errors and debug information to.
std::set<RegexCharacter> bracket_expression_characters_; ///< The characters in the current bracket expression.
int index_; ///< The current node index.
std::vector<ptr<RegexNode>> nodes_; ///< The current nodes.
std::vector<ptr<RegexNode> > nodes_; ///< The current nodes.
int errors_; ///< The number of errors that have occured.
public:
@ -96,7 +96,7 @@ class RegexParser
ptr<RegexNode> regex_node( const LexerAction* action );
void print_positions( const std::set<RegexNode*, RegexNodeLess>& positions ) const;
void print_nodes( const std::vector<ptr<RegexNode>>& nodes, int level ) const;
void print_nodes( const std::vector<ptr<RegexNode> >& nodes, int level ) const;
void calculate_symbols_for_characters_start_and_end();
void calculate_combined_parse_tree( const std::vector<LexerToken>& tokens );

View file

@ -10,7 +10,7 @@ Library {
"pointer/pointer"
};
Cc {
Source {
pch = "stdafx.hpp";
"Error.cpp",
"LexerAction.cpp",

View file

@ -8,6 +8,7 @@
#include <sweet/lexer/LexerStateMachine.hpp>
#include <sweet/lexer/Lexer.ipp>
#include <sweet/lexer/PositionIterator.hpp>
#include <string.h>
using namespace sweet::lexer;
@ -1219,7 +1220,7 @@ SUITE( RegularExpressions )
{
void* whitespace;
LexerStateMachine lexer_state_machine( "[ \\t\\r\\n]", &whitespace );
Lexer<PositionIterator<const char*>> lexer( &lexer_state_machine, NULL );
Lexer<PositionIterator<const char*> > lexer( &lexer_state_machine, NULL );
const char* regex = "\n \r\n \r \r\n";
lexer.reset( PositionIterator<const char*>(regex, regex + strlen(regex)), PositionIterator<const char*>() );

View file

@ -10,7 +10,7 @@ Executable {
"unit/libUnitTest"
};
Cc {
Source {
pch = "stdafx.hpp";
"main.cpp",
"TestRegularExpressions.cpp"

View file

@ -1,6 +1,6 @@
//
// AddGlobal.hpp
// Copyright (c) 2007 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_ADDGLOBAL_HPP_INCLUDED

View file

@ -1,6 +1,6 @@
//
// AddGlobal.ipp
// Copyright (c) 2007 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_ADDGLOBAL_IPP_INCLUDED
@ -9,6 +9,11 @@
#include "AddGlobal.hpp"
#include "LuaPosition.hpp"
#include "LuaPolicyWrapper.ipp"
#include "LuaRawWrapper.hpp"
#include "LuaThunker.hpp"
#include "LuaReturner.hpp"
#include "LuaConverter.hpp"
#include "LuaStackGuard.hpp"
#include <sweet/assert/assert.hpp>
/**
@ -66,7 +71,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
void* copied_function = lua_newuserdata( lua_state_, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = function;
LuaConverter<P0>::push( lua_state_, p0 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_setglobal( lua_state_, name );
return *this;
@ -105,7 +110,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
*reinterpret_cast<Function*>(copied_function) = function;
LuaConverter<P0>::push( lua_state_, p0 );
LuaConverter<P1>::push( lua_state_, p1 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_setglobal( lua_state_, name );
return *this;
@ -148,7 +153,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
LuaConverter<P0>::push( lua_state_, p0 );
LuaConverter<P1>::push( lua_state_, p1 );
LuaConverter<P2>::push( lua_state_, p2 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_setglobal( lua_state_, name );
return *this;
@ -195,7 +200,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
LuaConverter<P1>::push( lua_state_, p1 );
LuaConverter<P2>::push( lua_state_, p2 );
LuaConverter<P3>::push( lua_state_, p3 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_setglobal( lua_state_, name );
return *this;
@ -246,7 +251,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
LuaConverter<P2>::push( lua_state_, p2 );
LuaConverter<P3>::push( lua_state_, p3 );
LuaConverter<P4>::push( lua_state_, p4 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_setglobal( lua_state_, name );
return *this;
@ -301,7 +306,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
LuaConverter<P3>::push( lua_state_, p3 );
LuaConverter<P4>::push( lua_state_, p4 );
LuaConverter<P5>::push( lua_state_, p5 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_setglobal( lua_state_, name );
return *this;
@ -360,7 +365,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const Function& function, c
LuaConverter<P4>::push( lua_state_, p4 );
LuaConverter<P5>::push( lua_state_, p5 );
LuaConverter<P6>::push( lua_state_, p6 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_setglobal( lua_state_, name );
return *this;
@ -390,7 +395,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaStackGuard guard( lua_state_ );
void* copied_function = lua_newuserdata( lua_state_, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, 1, 2, 3, 4, 5, 6, 7>::function, 1 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, 1, 2, 3, 4, 5, 6, 7>::function, 1 );
lua_setglobal( lua_state_, name );
return *this;
@ -424,7 +429,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
void* copied_function = lua_newuserdata( lua_state_, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
LuaConverter<P0>::push( lua_state_, p0 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_setglobal( lua_state_, name );
return *this;
@ -462,7 +467,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
LuaConverter<P0>::push( lua_state_, p0 );
LuaConverter<P1>::push( lua_state_, p1 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_setglobal( lua_state_, name );
return *this;
@ -504,7 +509,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P0>::push( lua_state_, p0 );
LuaConverter<P1>::push( lua_state_, p1 );
LuaConverter<P2>::push( lua_state_, p2 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_setglobal( lua_state_, name );
return *this;
@ -550,7 +555,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P1>::push( lua_state_, p1 );
LuaConverter<P2>::push( lua_state_, p2 );
LuaConverter<P3>::push( lua_state_, p3 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_setglobal( lua_state_, name );
return *this;
@ -600,7 +605,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P2>::push( lua_state_, p2 );
LuaConverter<P3>::push( lua_state_, p3 );
LuaConverter<P4>::push( lua_state_, p4 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_setglobal( lua_state_, name );
return *this;
@ -654,7 +659,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P3>::push( lua_state_, p3 );
LuaConverter<P4>::push( lua_state_, p4 );
LuaConverter<P5>::push( lua_state_, p5 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_setglobal( lua_state_, name );
return *this;
@ -712,7 +717,7 @@ sweet::lua::AddGlobal::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P4>::push( lua_state_, p4 );
LuaConverter<P5>::push( lua_state_, p5 );
LuaConverter<P6>::push( lua_state_, p6 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_pushcclosure( lua_state_, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_setglobal( lua_state_, name );
return *this;

View file

@ -1,13 +1,13 @@
//
// AddMember.cpp
// Copyright (c) 2007 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#include "AddMember.hpp"
#include "AddMemberHelper.hpp"
#include "LuaStackGuard.hpp"
#include "lua_types.hpp"
#include "lua_functions.hpp"
#include "lua_functions.ipp"
#include <sweet/assert/assert.hpp>
using namespace sweet;

View file

@ -132,7 +132,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
void* copied_function = lua_newuserdata( lua_state, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = function;
LuaConverter<P0>::push( lua_state, p0 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_setfield( lua_state, -2, name );
return *this;
@ -172,7 +172,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
*reinterpret_cast<Function*>(copied_function) = function;
LuaConverter<P0>::push( lua_state, p0 );
LuaConverter<P1>::push( lua_state, p1 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_setfield( lua_state, -2, name );
return *this;
@ -216,7 +216,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
LuaConverter<P0>::push( lua_state, p0 );
LuaConverter<P1>::push( lua_state, p1 );
LuaConverter<P2>::push( lua_state, p2 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_setfield( lua_state, -2, name );
return *this;
@ -264,7 +264,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
LuaConverter<P1>::push( lua_state, p1 );
LuaConverter<P2>::push( lua_state, p2 );
LuaConverter<P3>::push( lua_state, p3 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_setfield( lua_state, -2, name );
return *this;
@ -316,7 +316,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
LuaConverter<P2>::push( lua_state, p2 );
LuaConverter<P3>::push( lua_state, p3 );
LuaConverter<P4>::push( lua_state, p4 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_setfield( lua_state, -2, name );
return *this;
@ -372,7 +372,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
LuaConverter<P3>::push( lua_state, p3 );
LuaConverter<P4>::push( lua_state, p4 );
LuaConverter<P5>::push( lua_state, p5 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_setfield( lua_state, -2, name );
return *this;
@ -432,7 +432,7 @@ sweet::lua::AddMember::operator()( const char* name, const Function& function, c
LuaConverter<P4>::push( lua_state, p4 );
LuaConverter<P5>::push( lua_state, p5 );
LuaConverter<P6>::push( lua_state, p6 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_setfield( lua_state, -2, name );
return *this;
@ -464,7 +464,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaStackGuard guard( lua_state );
void* copied_function = lua_newuserdata( lua_state, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, 1, 2, 3, 4, 5, 6, 7>::function, 1 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, 1, 2, 3, 4, 5, 6, 7>::function, 1 );
lua_setfield( lua_state, -2, name );
return *this;
@ -500,7 +500,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
void* copied_function = lua_newuserdata( lua_state, sizeof(Function) );
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
LuaConverter<P0>::push( lua_state, p0 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, 1, 2, 3, 4, 5, 6>::function, 2 );
lua_setfield( lua_state, -2, name );
return *this;
@ -540,7 +540,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
*reinterpret_cast<Function*>(copied_function) = policy_wrapper.get_function();
LuaConverter<P0>::push( lua_state, p0 );
LuaConverter<P1>::push( lua_state, p1 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, 1, 2, 3, 4, 5>::function, 3 );
lua_setfield( lua_state, -2, name );
return *this;
@ -584,7 +584,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P0>::push( lua_state, p0 );
LuaConverter<P1>::push( lua_state, p1 );
LuaConverter<P2>::push( lua_state, p2 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, 1, 2, 3, 4>::function, 4 );
lua_setfield( lua_state, -2, name );
return *this;
@ -632,7 +632,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P1>::push( lua_state, p1 );
LuaConverter<P2>::push( lua_state, p2 );
LuaConverter<P3>::push( lua_state, p3 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, 1, 2, 3>::function, 5 );
lua_setfield( lua_state, -2, name );
return *this;
@ -684,7 +684,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P2>::push( lua_state, p2 );
LuaConverter<P3>::push( lua_state, p3 );
LuaConverter<P4>::push( lua_state, p4 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, 1, 2>::function, 6 );
lua_setfield( lua_state, -2, name );
return *this;
@ -740,7 +740,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P3>::push( lua_state, p3 );
LuaConverter<P4>::push( lua_state, p4 );
LuaConverter<P5>::push( lua_state, p5 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, 1>::function, 7 );
lua_setfield( lua_state, -2, name );
return *this;
@ -800,7 +800,7 @@ sweet::lua::AddMember::operator()( const char* name, const LuaPolicyWrapper<Func
LuaConverter<P4>::push( lua_state, p4 );
LuaConverter<P5>::push( lua_state, p5 );
LuaConverter<P6>::push( lua_state, p6 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_pushcclosure( lua_state, &LuaThunker<Function, LuaReturner<typename traits<Function>::return_type, POLICY>, LuaPosition<P0, 2>::position, LuaPosition<P1, 3>::position, LuaPosition<P2, 4>::position, LuaPosition<P3, 5>::position, LuaPosition<P4, 6>::position, LuaPosition<P5, 7>::position, LuaPosition<P6, 8>::position>::function, 8 );
lua_setfield( lua_state, -2, name );
return *this;

View file

@ -1,6 +1,6 @@
//
// AddMemberHelper.hpp
// Copyright (c) 2009 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2009 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_ADDMEMBERHELPER_HPP_INCLUDED
@ -8,6 +8,8 @@
#include "declspec.hpp"
struct lua_State;
namespace sweet
{

View file

@ -94,7 +94,7 @@ AddParameter& AddParameter::operator()( bool value )
*/
AddParameter& AddParameter::operator()( int value )
{
add_parameter_helper_->push( static_cast<lua_Integer>(value) );
add_parameter_helper_->push( value );
return *this;
}

View file

@ -1,12 +1,13 @@
//
// AddParameter.ipp
// Copyright (c) 2007 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_ADDPARAMETER_IPP_INCLUDED
#define SWEET_LUA_ADDPARAMETER_IPP_INCLUDED
#include "AddParameter.hpp"
#include "AddParameterHelper.hpp"
/**
// Push an arbitrary value onto the Lua stack.
@ -28,8 +29,8 @@ sweet::lua::AddParameter& sweet::lua::AddParameter::operator()( const Type& valu
/**
// Call the function and retrieve an arbitrary return value.
//
// This is done in a separate function (instead of the destructor) because
// calling the function can throw an exception.
// This is done in this function instead of the destructor because calling
// the function can throw an exception.
//
// @param return_value
// A pointer to the variable to place the return value into (assumed not

View file

@ -9,6 +9,12 @@
#include "LuaValue.hpp"
#include "Lua.hpp"
#include <sweet/error/macros.hpp>
#include <memory.h>
#include <stdio.h>
#if defined(BUILD_OS_WINDOWS)
#define snprintf _snprintf
#endif
using namespace sweet::lua;
@ -755,15 +761,14 @@ const char* AddParameterHelper::stack_trace_for_resume( lua_State* lua_state, bo
size_t written = 0;
memset( message, 0, length );
written += _snprintf( message + written, length - written, "%s", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "Unknown error" );
written += snprintf( message + written, length - written, "%s", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "Unknown error" );
if ( stack_trace_enabled )
{
static const int STACK_TRACE_BEGIN = 0;
static const int STACK_TRACE_END = 6;
written += _snprintf( message + written, length - written, ".\nstack trace:" );
written += snprintf( message + written, length - written, ".\nstack trace:" );
lua_Debug debug;
memset( &debug, 0, sizeof(debug) );
@ -776,14 +781,14 @@ const char* AddParameterHelper::stack_trace_for_resume( lua_State* lua_state, bo
//
// Source and line number.
//
written += _snprintf( message + written, length - written, "\n " );
written += snprintf( message + written, length - written, "\n " );
if ( debug.currentline > 0 )
{
written += _snprintf( message + written, length - written, "%s(%d) : ", debug.source, debug.currentline );
written += snprintf( message + written, length - written, "%s(%d) : ", debug.source, debug.currentline );
}
else
{
written += _snprintf( message + written, length - written, "%s(1) : ", debug.source, debug.currentline );
written += snprintf( message + written, length - written, "%s(1) : ", debug.source, debug.currentline );
}
//
@ -791,18 +796,18 @@ const char* AddParameterHelper::stack_trace_for_resume( lua_State* lua_state, bo
//
if ( *debug.namewhat != '\0' )
{
written += _snprintf( message + written, length - written, "in function " LUA_QS, debug.name );
written += snprintf( message + written, length - written, "in function " LUA_QS, debug.name );
}
else
{
switch ( *debug.what )
{
case 'm':
written += _snprintf( message + written, length - written, "main");
written += snprintf( message + written, length - written, "main");
break;
default:
written += _snprintf( message + written, length - written, "in function <%s(%d)>", debug.source, debug.linedefined );
written += snprintf( message + written, length - written, "in function <%s(%d)>", debug.source, debug.linedefined );
break;
}
}

View file

@ -1,6 +1,6 @@
//
// AddParameterHelper.ipp
// Copyright (c) 2007 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_ADDPARAMETERHELPER_IPP_INCLUDED
@ -8,7 +8,9 @@
#include "AddParameterHelper.hpp"
#include "LuaStackGuard.hpp"
#include "LuaConverter.hpp"
#include "Error.hpp"
#include "Lua.hpp"
#include <sweet/traits/traits.hpp>
#include <sweet/assert/assert.hpp>
@ -78,7 +80,7 @@ void AddParameterHelper::end( Type* return_value )
SWEET_ASSERT( return_value );
LuaStackGuard guard( lua_state_, error_handler_ == 0 ? parameters_ + 1 : parameters_ + 2 );
internal_end( 1 );
*return_value = LuaConverter<traits::traits<Type>::value_type>::to( lua_state_, -1 );
*return_value = LuaConverter<typename traits::traits<Type>::value_type>::to( lua_state_, -1 );
lua_pop( lua_state_, 1 );
}

View file

@ -1,13 +1,12 @@
//
// Lua.hpp
// Copyright (c) 2007 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_LUA_HPP_INCLUDED
#define SWEET_LUA_LUA_HPP_INCLUDED
#include "declspec.hpp"
#include "AddParameterHelper.ipp"
#include "AddMemberHelper.hpp"
#include "AddGlobal.ipp"
#include "AddMember.ipp"
@ -87,5 +86,7 @@ class SWEET_LUA_DECLSPEC Lua
}
#include "Lua.ipp"
#include "AddParameterHelper.ipp"
#include "lua_functions.ipp"
#endif

View file

@ -1,6 +1,6 @@
//
// Lua.ipp
// Copyright (c) 2009 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2009 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_LUA_IPP_INCLUDED
@ -27,8 +27,8 @@ namespace lua
template <class Type>
void Lua::create( const Type& object )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::create( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::create( lua_state_, object );
}
/**
@ -43,8 +43,8 @@ void Lua::create( const Type& object )
template <class Type>
void Lua::create_with_existing_table( const Type& object )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::create_with_existing_table( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::create_with_existing_table( lua_state_, object );
}
/**
@ -56,8 +56,8 @@ void Lua::create_with_existing_table( const Type& object )
template <class Type>
void Lua::destroy( const Type& object )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::destroy( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::destroy( lua_state_, object );
}
/**
@ -70,8 +70,8 @@ void Lua::destroy( const Type& object )
template <class Type>
AddMember Lua::members( const Type& object )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
return AddMember( &add_member_helper_ );
}
@ -94,8 +94,8 @@ bool Lua::is_value( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return !lua_isnil( lua_state_, -1 ) ? true : false;
}
@ -118,8 +118,8 @@ bool Lua::is_boolean( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_isboolean( lua_state_, -1 ) ? true : false;
}
@ -143,8 +143,8 @@ bool Lua::is_number( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_isnumber( lua_state_, -1 ) ? true : false;
}
@ -169,8 +169,8 @@ bool Lua::is_string( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_isstring( lua_state_, -1 ) ? true : false;
}
@ -194,8 +194,8 @@ bool Lua::is_function( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_isfunction( lua_state_, -1 ) ? true : false;
}
@ -219,8 +219,8 @@ bool Lua::boolean( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_toboolean( lua_state_, -1 ) ? true : false;
}
@ -244,8 +244,8 @@ int Lua::integer( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_tointeger( lua_state_, -1 );
}
@ -270,8 +270,8 @@ Lua::number( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return static_cast<float>( lua_tonumber(lua_state_, -1) );
}
@ -295,8 +295,8 @@ std::string Lua::string( const Type& object, const char* field ) const
SWEET_ASSERT( field );
LuaStackGuard guard( lua_state_ );
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state_, object );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state_, object );
lua_getfield( lua_state_, -1, field );
return lua_tostring( lua_state_, -1 );
}

View file

@ -4,7 +4,11 @@
//
#include "LuaAllocator.hpp"
#if defined(BUILD_OS_WINDOWS)
#include <malloc.h>
#elif defined(BUILD_OS_MACOSX)
#include <stdlib.h>
#endif
using namespace sweet::lua;
@ -26,11 +30,11 @@ void* LuaAllocator::allocate( void* context, void* ptr, size_t osize, size_t nsi
{
if ( nsize == 0 )
{
::free( ptr );
free( ptr );
return 0;
}
else
{
return ::realloc( ptr, nsize );
return realloc( ptr, nsize );
}
}

View file

@ -1,12 +1,13 @@
//
// LuaAllocator.hpp
// Copyright (c) 2007 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_LUAALLOCATOR_HPP_INCLUDED
#define SWEET_LUA_LUAALLOCATOR_HPP_INCLUDED
#include "declspec.hpp"
#include <sys/types.h>
namespace sweet
{

View file

@ -43,7 +43,7 @@ struct LuaConverter
};
template <class Type>
struct LuaConverter<LuaValueWrapper<Type>>
struct LuaConverter<LuaValueWrapper<Type> >
{
static void push( lua_State* lua_state, const LuaValueWrapper<Type>& value );
};

View file

@ -7,6 +7,7 @@
#define SWEET_LUA_LUACONVERTER_IPP_INCLUDED
#include "LuaConverter.hpp"
#include "LuaObjectConverter.hpp"
#include "LuaThunker.ipp"
namespace sweet
@ -16,36 +17,35 @@ namespace lua
{
template <class Type>
void
sweet::lua::LuaConverter<Type>::create( lua_State* lua_state, typename traits::traits<Type>::parameter_type value )
void sweet::lua::LuaConverter<Type>::create( lua_State* lua_state, typename traits::traits<Type>::parameter_type value )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::create( lua_state, value );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::create( lua_state, value );
}
template <class Type>
void sweet::lua::LuaConverter<Type>::destroy( lua_State* lua_state, typename traits::traits<Type>::parameter_type value )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::destroy( lua_state, value );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::destroy( lua_state, value );
}
template <class Type>
void LuaConverter<Type>::push( lua_State* lua_state, typename traits::traits<Type>::parameter_type value )
{
typedef traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::push( lua_state, value );
typedef typename traits::traits<Type>::base_type base_type;
LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::push( lua_state, value );
}
template <class Type>
Type LuaConverter<Type>::to( lua_State* lua_state, int position )
{
typedef traits::traits<Type>::base_type base_type;
return LuaObjectConverter<Type, LuaTraits<base_type>::storage_type>::to( lua_state, position );
typedef typename traits::traits<Type>::base_type base_type;
return LuaObjectConverter<Type, typename LuaTraits<base_type>::storage_type>::to( lua_state, position );
}
template <class Type>
void LuaConverter<sweet::lua::LuaValueWrapper<Type>>::push( lua_State* lua_state, const LuaValueWrapper<Type>& value )
void LuaConverter<sweet::lua::LuaValueWrapper<Type> >::push( lua_State* lua_state, const LuaValueWrapper<Type>& value )
{
LuaObjectConverter<Type, LuaByValue>::push( lua_state, value.get_value() );
}

View file

@ -1,11 +1,17 @@
//
// LuaGlobalEnvironment.cpp
// Copyright (c) 2008 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "LuaGlobalEnvironment.hpp"
using namespace sweet::lua;
/**
// Represents the %Lua global environment when adding globals or members.
*/
const sweet::lua::LuaGlobalEnvironment sweet::lua::global_environment;
LuaGlobalEnvironment::LuaGlobalEnvironment()
{
}

View file

@ -21,6 +21,8 @@ namespace lua
*/
class SWEET_LUA_DECLSPEC LuaGlobalEnvironment
{
public:
LuaGlobalEnvironment();
};
SWEET_LUA_DECLSPEC extern const LuaGlobalEnvironment global_environment;

View file

@ -1,12 +1,18 @@
//
// LuaNil.cpp
// Copyright (c) 2008 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2008 - 2012 Charles Baker. All rights reserved.
//
#include "stdafx.hpp"
#include "LuaNil.hpp"
using namespace sweet::lua;
/**
// Represents a %Lua nil value when adding globals or members.
*/
const sweet::lua::LuaNil sweet::lua::nil;
const sweet::lua::LuaNil sweet::lua::nil;
LuaNil::LuaNil()
{
}

View file

@ -21,6 +21,8 @@ namespace lua
*/
class SWEET_LUA_DECLSPEC LuaNil
{
public:
LuaNil();
};
SWEET_LUA_DECLSPEC extern const LuaNil nil;

View file

@ -1,6 +1,6 @@
//
// LuaObject.hpp
// Copyright (c) 2007 - 2011 Charles Baker. All rights reserved.
// Copyright (c) 2007 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_LUAOBJECT_HPP_INCLUDED
@ -52,34 +52,4 @@ class SWEET_LUA_DECLSPEC LuaObject
}
/**
// Persist this LuaObject in an Archive.
//
// @param archive
// The Archive to persist this LuaObject in.
*/
template <class Archive>
void sweet::lua::LuaObject::persist( Archive& archive )
{
lua_ = reinterpret_cast<Lua*>( archive.get_context(SWEET_STATIC_TYPEID(Lua)) );
SWEET_ASSERT( lua_ );
lua_State* lua_state = lua_->get_lua_state();
SWEET_ASSERT( lua_state );
LuaStackGuard stack_guard( lua_state );
if ( archive.is_writing() )
{
lua_push_object( lua_state, this );
}
sweet::persist::persist_lua_table( archive, "table", lua_state, false );
if ( archive.is_reading() )
{
lua_create_object_with_existing_table( lua_state, this );
}
}
#endif

View file

@ -1,6 +1,6 @@
//
// LuaObjectConverter.hpp
// Copyright (c) 2009 - 2010 Charles Baker. All rights reserved.
// Copyright (c) 2009 - 2012 Charles Baker. All rights reserved.
//
#ifndef SWEET_LUA_LUAOBJECTCONVERTER_HPP_INCLUDED
@ -8,6 +8,7 @@
#include "LuaTraits.hpp"
#include "lua_functions.hpp"
#include <sweet/assert/assert.hpp>
namespace sweet
{

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