diff --git a/modules/xcode b/modules/xcode index 6e2494b4..e6a66297 160000 --- a/modules/xcode +++ b/modules/xcode @@ -1 +1 @@ -Subproject commit 6e2494b4d07a883508bc6626686a47f927a596cb +Subproject commit e6a662976b8542d1cdb59a758ec741b5e215285e diff --git a/src/base/premake.lua b/src/base/premake.lua index 0d7dabd9..3c35d0aa 100644 --- a/src/base/premake.lua +++ b/src/base/premake.lua @@ -43,7 +43,7 @@ function premake.capture(fn) -- start a new capture without forgetting the old one local old = _captured - _captured = {} + _captured = buffered.new() -- capture fn() @@ -51,6 +51,9 @@ -- build the result local captured = premake.captured() + -- free the capture buffer. + buffered.close(_captured) + -- restore the old capture and done _captured = old return captured @@ -64,7 +67,7 @@ function premake.captured() if _captured then - return table.concat(_captured, _eol) + return buffered.tostring(_captured) else return "" end @@ -147,19 +150,28 @@ -- function premake.generate(obj, ext, callback) - local fn = premake.filename(obj, ext) - printf("Generating %s...", path.getrelative(os.getcwd(), fn)) + local output = premake.capture(function () + _indentLevel = 0 + callback(obj) + _indentLevel = 0 + end) - local f, err = io.open(fn, "wb") - if (not f) then + local fn = premake.filename(obj, ext) + + -- make sure output folder exists. + local dir = path.getdirectory(fn) + ok, err = os.mkdir(dir) + if not ok then error(err, 0) end - io.output(f) - _indentLevel = 0 - callback(obj) - f:close() - _indentLevel = 0 + local f, err = os.writefile_ifnotequal(output, fn); + + if (f < 0) then + error(err, 0) + elseif (f > 0) then + printf("Generated %s...", path.getrelative(os.getcwd(), fn)) + end end @@ -217,7 +229,7 @@ end if not _captured then io.write(s) else - table.insert(_captured, s) + buffered.write(_captured, s) end end @@ -230,12 +242,15 @@ end function premake.outln(s) premake.out(s) - if not _captured then - io.write(_eol or "\n") - end + premake.out(_eol or "\n") end - +-- +-- Output a UTF-8 signature. +-- + function p.utf8() + premake.out('\239\187\191') + end --- -- Write a formatted string to the exported file, after decreasing the diff --git a/src/host/buffered_io.c b/src/host/buffered_io.c new file mode 100644 index 00000000..e60c359e --- /dev/null +++ b/src/host/buffered_io.c @@ -0,0 +1,105 @@ +/** + * \file buffered_io.c + * \brief provide buffered io. + * \author Copyright (c) 2014 + */ + +#include +#include +#include "premake.h" + +typedef struct struct_Buffer +{ + size_t capacity; + size_t length; + char* data; +} Buffer; + + +int buffered_new(lua_State* L) +{ + Buffer* b = (Buffer*)malloc(sizeof(Buffer)); + b->capacity = 0; + b->length = 0; + b->data = NULL; + lua_pushlightuserdata(L, b); + return 1; +} + + +static void do_write(Buffer* b, const char *s, size_t l) +{ + char* data; + + if (b->length + l > b->capacity) + { + size_t cap = (b->capacity * 3) / 2; + if (cap <= 65536) + cap = 65536; + + data = (char*)calloc(cap, 1); + if (b->length > 0) + { + memcpy(data, b->data, b->length); + free(b->data); + } + b->data = data; + b->capacity = cap; + } + + memcpy(b->data + b->length, s, l); + b->length += l; +} + + +int buffered_write(lua_State* L) +{ + size_t l; + const char *s = luaL_checklstring(L, 2, &l); + Buffer* b = (Buffer*)lua_touserdata(L, 1); + + do_write(b, s, l); + return 0; +} + + +int buffered_writeln(lua_State* L) +{ + size_t l; + const char *s = luaL_checklstring(L, 2, &l); + Buffer* b = (Buffer*)lua_touserdata(L, 1); + + do_write(b, s, l); + do_write(b, "\r\n", 2); + return 0; +} + + +int buffered_close(lua_State* L) +{ + Buffer* b = (Buffer*)lua_touserdata(L, 1); + free(b->data); + free(b); + return 0; +} + + +int buffered_tostring(lua_State* L) +{ + Buffer* b = (Buffer*)lua_touserdata(L, 1); + size_t len = b->length; + + // trim string for _eol of line at the end. + if (len > 0 && b->data[len-1] == '\n') + --len; + if (len > 0 && b->data[len-1] == '\r') + --len; + + if (len > 0) + // push data into a string. + lua_pushlstring(L, b->data, len); + else + lua_pushstring(L, ""); + + return 1; +} diff --git a/src/host/premake.c b/src/host/premake.c index 0e54e715..96a9c7a5 100644 --- a/src/host/premake.c +++ b/src/host/premake.c @@ -86,6 +86,15 @@ static const luaL_Reg string_functions[] = { { NULL, NULL } }; +static const luaL_Reg buffered_functions[] = { + { "new", buffered_new }, + { "write", buffered_write }, + { "writeln", buffered_writeln }, + { "tostring", buffered_tostring }, + { "close", buffered_close }, + { NULL, NULL } +}; + #ifdef PREMAKE_CURL static const luaL_Reg http_functions[] = { { "get", http_get }, @@ -113,6 +122,7 @@ int premake_init(lua_State* L) luaL_register(L, "path", path_functions); luaL_register(L, "os", os_functions); luaL_register(L, "string", string_functions); + luaL_register(L, "buffered", buffered_functions); #ifdef PREMAKE_CURL luaL_register(L, "http", http_functions); diff --git a/src/host/premake.h b/src/host/premake.h index 5dafb2b2..edbd9600 100644 --- a/src/host/premake.h +++ b/src/host/premake.h @@ -121,6 +121,11 @@ int string_endswith(lua_State* L); int string_hash(lua_State* L); int string_sha1(lua_State* L); int string_startswith(lua_State* L); +int buffered_new(lua_State* L); +int buffered_write(lua_State* L); +int buffered_writeln(lua_State* L); +int buffered_close(lua_State* L); +int buffered_tostring(lua_State* L); #ifdef PREMAKE_CURL int http_get(lua_State* L); diff --git a/tests/testfx.lua b/tests/testfx.lua index 5d3ca26e..6abbaef7 100644 --- a/tests/testfx.lua +++ b/tests/testfx.lua @@ -310,6 +310,12 @@ local function stub_print(s) end + local function stub_os_writefile_ifnotequal(content, fname) + test.value_openedfilename = fname; + test.value_closedfile = true + return 0; + end + -- -- Define a collection for the test suites @@ -431,6 +437,7 @@ print = stub_print io.open = stub_io_open io.output = stub_io_output + os.writefile_ifnotequal = stub_os_writefile_ifnotequal local numpassed = 0 local numfailed = 0