diff --git a/lbs.lua b/lbs.lua index 3226b5e..8aebe54 100644 --- a/lbs.lua +++ b/lbs.lua @@ -73,6 +73,10 @@ local function compile(CXX, src_dirs, include_dirs, defines, additional_argument local base_argv = {} additional_arguments[#additional_arguments+1] = "-c" + if (config.buildmode == "debug") then + additional_arguments[#additional_arguments+1] = "-O0" + additional_arguments[#additional_arguments+1] = "-g" + end for _,v in pairs(additional_arguments) do base_argv[#base_argv+1] = v end for _,v in pairs(include_dirs) do base_argv[#base_argv+1] = "-I\"" .. v .. "\"" end for k,v in pairs(defines) do base_argv[#base_argv+1] = "-D" .. k .. "=" .. v end @@ -100,6 +104,10 @@ end local function link(LNK, obj_dirs, library_dirs, linker_inputs, additional_arguments, file_output) local argv = {} + if (config.buildmode == "debug") then + additional_arguments[#additional_arguments+1] = "-O0" + additional_arguments[#additional_arguments+1] = "-g" + end for _,v in pairs(library_dirs) do argv[#argv+1] = "-L\"" .. v .. "\"" end for _,v in pairs(linker_inputs) do argv[#argv+1] = "-l\"" .. v .. "\"" end for _,v in pairs(additional_arguments) do argv[#argv+1] = v end @@ -137,6 +145,8 @@ function build(...) compile(CXX, source_dirs, include_dirs, defines, additional_arguments) link(CXX, {"obj"}, library_dirs, linker_inputs, {}, program_name) + + print("Program generated! See " .. program_name) end function main(...) build(...) end diff --git a/src/lua_filesystem.cpp b/src/lua_filesystem.cpp index 207c935..e2f89ba 100644 --- a/src/lua_filesystem.cpp +++ b/src/lua_filesystem.cpp @@ -106,11 +106,14 @@ int lua_fs_list_alldirs(lua_State* L) int lua_fs_foreach_dir(lua_State* L) { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path"); - const char* path = lua_tostring(L, 1); + try { + luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path"); + const char* path = lua_tostring(L, 1); - void* ud = lua_newuserdata(L, sizeof(std::filesystem::directory_iterator)); - new (ud) std::filesystem::directory_iterator(path); + void* ud = lua_newuserdata(L, sizeof(std::filesystem::directory_iterator)); + new (ud) std::filesystem::directory_iterator(path); + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured creating fs.foreach iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } luaL_getmetatable(L, "fs.stdlibcpp.filesystem.directory_iterator"); lua_setmetatable(L, -2); @@ -123,8 +126,11 @@ int lua_fs_forall_dir(lua_State* L) luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path"); const char* path = lua_tostring(L, 1); - void* ud = lua_newuserdata(L, sizeof(std::filesystem::recursive_directory_iterator)); - new (ud) std::filesystem::recursive_directory_iterator(path); + try { + void* ud = lua_newuserdata(L, sizeof(std::filesystem::recursive_directory_iterator)); + new (ud) std::filesystem::recursive_directory_iterator(path); + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured creating fs.forall iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } luaL_getmetatable(L, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); lua_setmetatable(L, -2); @@ -134,51 +140,63 @@ int lua_fs_forall_dir(lua_State* L) int lua_fs_foreach_dir_next(lua_State* L) { - int idx = lua_upvalueindex(1); - luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); - void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); - std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; - if (x._At_end()) - return 0; - std::string p = (*x).path().string(); - lua_pushlstring(L, p.c_str(), p.size()); - x++; + try { + int idx = lua_upvalueindex(1); + luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); + void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.directory_iterator"); + luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); + std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; + if (x._At_end()) + return 0; + std::string p = (*x).path().string(); + lua_pushlstring(L, p.c_str(), p.size()); + x++; + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured iterating fs.foreach\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } return 1; } int lua_fs_forall_dir_next(lua_State* L) { - int idx = lua_upvalueindex(1); - luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); - void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); - std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; - if (x == std::filesystem::recursive_directory_iterator{}) - return 0; - std::string p = (*x).path().string(); - lua_pushlstring(L, p.c_str(), p.size()); - x++; + try { + int idx = lua_upvalueindex(1); + luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); + void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); + luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); + std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; + if (x == std::filesystem::recursive_directory_iterator{}) + return 0; + std::string p = (*x).path().string(); + lua_pushlstring(L, p.c_str(), p.size()); + x++; + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured iterating fs.forall\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } return 1; } int lua_fs_foreach_dir_dtor(lua_State* L) { - luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); - void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); - std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; - x.~directory_iterator(); + try { + luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); + void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.directory_iterator"); + luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); + std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; + x.~directory_iterator(); + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured destroying fs.foreach iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } return 0; } int lua_fs_forall_dir_dtor(lua_State* L) { - luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); - void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); - std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; - x.~recursive_directory_iterator(); + try { + luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); + void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); + luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); + std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; + x.~recursive_directory_iterator(); + } catch (const std::exception& e) + { return luaL_error(L, "%s:%d: An exception occured destroying fs.forall iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } return 0; } diff --git a/src/lua_platform.cpp b/src/lua_platform.cpp index 812872c..6580bee 100644 --- a/src/lua_platform.cpp +++ b/src/lua_platform.cpp @@ -65,122 +65,151 @@ int lua_platform_exec(lua_State* L) int lua_platform_exec_parallel(lua_State* L) { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a command"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TNUMBER, 2, "Expected second argument to be an integer representing the maximum number of parallel jobs to start"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TTABLE, 3, "Expected third argument to be a table of table of strings representing the arguments"); - const char* cmd = (lua_tostring(L, 1)); - const size_t max_parallel = lua_tointeger(L, 2); - const size_t num_cmds = lua_objlen(L, 3); + try { + luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a command"); + luaL_argcheck(L, lua_type(L, 2) == LUA_TNUMBER, 2, "Expected second argument to be an integer representing the maximum number of parallel jobs to start"); + luaL_argcheck(L, lua_type(L, 3) == LUA_TTABLE, 3, "Expected third argument to be a table of table of strings representing the arguments"); + const char* cmd = (lua_tostring(L, 1)); + const size_t max_parallel = lua_tointeger(L, 2); + const size_t num_cmds = lua_objlen(L, 3); - size_t* num_args = (size_t*)malloc(num_cmds * sizeof(size_t)); - memset(num_args, 0, sizeof(size_t) * num_cmds); - const char*** args = (const char***)malloc(num_cmds*sizeof(const char**)); - - // Generate the command stack from lua arguments - for (size_t i = 0; i < num_cmds; ++i) - { - lua_rawgeti(L, 3, i + 1); - if (lua_istable(L, -1)) - { - const size_t tbl_num_args = lua_objlen(L, -1); - num_args[i] = tbl_num_args; - args[i] = (const char**)malloc(tbl_num_args*sizeof(const char*)); - for (size_t j = 0; j < tbl_num_args; ++j) + uniproc_process* workers = nullptr; + int* retcodes = nullptr; + size_t* num_args = nullptr; + const char*** args = nullptr; + std::vector std_outs; + std::vector std_errs; + + try { + num_args = (size_t*)malloc(num_cmds * sizeof(size_t)); + memset(num_args, 0, sizeof(size_t) * num_cmds); + args = (const char***)malloc(num_cmds * sizeof(const char**)); + + // Generate the command stack from lua arguments + for (size_t i = 0; i < num_cmds; ++i) { - lua_rawgeti(L, -1, j + 1); - if (!lua_isstring(L, -1)) - return luaL_error(L, "Expected program argument to be a string. args[%d][%d] was a %s, not a string!\n", i, j, lua_typename(L, lua_type(L, -1))); - args[i][j] = lua_tostring(L, -1); + lua_rawgeti(L, 3, i + 1); + if (lua_istable(L, -1)) + { + const size_t tbl_num_args = lua_objlen(L, -1); + num_args[i] = tbl_num_args; + args[i] = (const char**)malloc(tbl_num_args * sizeof(const char*)); + for (size_t j = 0; j < tbl_num_args; ++j) + { + lua_rawgeti(L, -1, j + 1); + if (!lua_isstring(L, -1)) + return luaL_error(L, "Expected program argument to be a string. args[%d][%d] was a %s, not a string!\n", i, j, lua_typename(L, lua_type(L, -1))); + args[i][j] = lua_tostring(L, -1); + lua_pop(L, 1); + } + } + else if (lua_type(L, -1) == LUA_TSTRING) + { + num_args[i] = 1; + args[i] = (const char**)malloc(1 * sizeof(const char*)); + args[i][0] = lua_tostring(L, -1); + } + else + return luaL_error(L, "Expected a table of program arguments. args[%d] was a %s, not a table!\n", i, lua_typename(L, lua_type(L, -1))); lua_pop(L, 1); } + + workers = (uniproc_process*)malloc(max_parallel * sizeof(uniproc_process)); + uniproc_nullify_processes(workers, max_parallel); + retcodes = (int*)malloc(num_cmds * sizeof(int)); + memset(retcodes, 0, num_cmds); + + std_outs.resize(num_cmds, ""); + std_errs.resize(num_cmds, ""); + } - else if (lua_type(L, -1) == LUA_TSTRING) - { - num_args[i] = 1; - args[i] = (const char**)malloc(1*sizeof(const char*)); - args[i][0] = lua_tostring(L, -1); + catch (const std::exception& e) { + fprintf(stderr, "%s:%d: Exception occured in preparation for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); + return luaL_error(L, "%s:%d: Exception occured in preparation for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - else - return luaL_error(L, "Expected a table of program arguments. args[%d] was a %s, not a table!\n", i, lua_typename(L, lua_type(L, -1))); - lua_pop(L, 1); - } - uniproc_process* workers = (uniproc_process*)malloc(max_parallel*sizeof(uniproc_process)); - uniproc_nullify_processes(workers, max_parallel); - int* retcodes = (int*)malloc(num_cmds*sizeof(int)); - memset(retcodes, 0, num_cmds); - - std::vector std_outs; - std::vector std_errs; - std_outs.resize(num_cmds, ""); - std_errs.resize(num_cmds, ""); - - - size_t cmd_idx = 0; - while (cmd_idx < num_cmds || !uniproc_are_processes_finished(workers, max_parallel)) - { - for (uniproc_process* p = workers; p != (workers + max_parallel); ++p) + size_t cmd_idx = 0; + while (cmd_idx < num_cmds || !uniproc_are_processes_finished(workers, max_parallel)) { - // Check and handle a worker if it has completed - if (uniproc_are_processes_finished(p, 1)) - { - char buf[64]; - // Read the std. streams into the output vectors - while (fgets(buf, sizeof(buf), p->out) != NULL) - std_outs[p->userdata].append(buf); - while (fgets(buf, sizeof(buf), p->err) != NULL) - std_errs[p->userdata].append(buf); - // Add the process return code to retcode array - uniproc_await_processes(p, retcodes + p->userdata, 1); - // Close the process and zero it - uniproc_close_process(p); - } - // If a worker is null and there is more jobs to complete - // Create a new process - // Is a while loop to handle the possibility that process creation fails - while (uniproc_is_process_null(p) && cmd_idx < num_cmds) - { - // Create process - *p = uniproc_create_process(cmd, num_args[cmd_idx], args[cmd_idx]); - p->userdata = cmd_idx; - cmd_idx++; - - // If we failed to create the process, set the output for it to an error value - if (uniproc_is_process_null(p)) + try { + for (uniproc_process* p = workers; p != (workers + max_parallel); ++p) { - std_outs[p->userdata] = "uniproc: failed to create process"; - std_errs[p->userdata] = "uniproc: failed to create process"; - retcodes[p->userdata] = -1; + // Check and handle a worker if it has completed + if (!uniproc_is_process_null(p) && uniproc_are_processes_finished(p, 1)) + { + char buf[64]; + // Read the std. streams into the output vectors + // TODO: Errors out here + fprintf(stderr, "p->out = %p\n", p->out); + while (fgets(buf, sizeof(buf), p->out) != NULL) + std_outs[p->userdata].append(buf); + fprintf(stderr, "C: %llu\n", cmd_idx); + fprintf(stderr, "p->err = %p\n", p->err); + while (fgets(buf, sizeof(buf), p->err) != NULL) + std_errs[p->userdata].append(buf); + fprintf(stderr, "D: %llu\n", cmd_idx); + // Add the process return code to retcode array + uniproc_await_processes(p, retcodes + p->userdata, 1); + // Close the process and zero it + uniproc_close_process(p); + } + // If a worker is null and there is more jobs to complete + // Create a new process + // Is a while loop to handle the possibility that process creation fails + while (uniproc_is_process_null(p) && cmd_idx < num_cmds) + { + // Create process + *p = uniproc_create_process(cmd, num_args[cmd_idx], args[cmd_idx]); + p->userdata = cmd_idx; + cmd_idx++; + + // If we failed to create the process, set the output for it to an error value + if (uniproc_is_process_null(p)) + { + std_outs[p->userdata] = "uniproc: failed to create process"; + std_errs[p->userdata] = "uniproc: failed to create process"; + retcodes[p->userdata] = -1; + } + } } + // Await a process completing before trying to iterate again + // Prevents spinning the CPU + uniproc_await_any_processes(workers, max_parallel); + } + catch (const std::exception& e) { + fprintf(stderr, "%s:%d: Exception occured in parallel execution for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); + return luaL_error(L, "%s:%d: Exception occured in parallel execution for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } } - // Await a process completing before trying to iterate again - // Prevents spinning the CPU - uniproc_await_any_processes(workers, max_parallel); + + for (size_t i = 0; i < num_cmds; ++i) + free(args[i]); + free(num_args); + free(args); + // Don't need to close processes as that is handled in the command loop + free(workers); + + + + // Join thread results together and push them to lua stack + lua_newtable(L); // rc + lua_newtable(L); // stdout + lua_newtable(L); // stderr + for (size_t i = 0; i < num_cmds; ++i) + { + lua_pushinteger(L, retcodes[i]); + lua_rawseti(L, -4, i + 1); + lua_pushlstring(L, std_outs[i].c_str(), std_outs[i].size()); + lua_rawseti(L, -3, i + 1); + lua_pushlstring(L, std_errs[i].c_str(), std_errs[i].size()); + lua_rawseti(L, -2, i + 1); + } + + return 3; } - - for (size_t i = 0; i < num_cmds; ++i) - free(args[i]); - free(num_args); - free(args); - // Don't need to close processes as that is handled in the command loop - free(workers); - - - - // Join thread results together and push them to lua stack - lua_newtable(L); // rc - lua_newtable(L); // stdout - lua_newtable(L); // stderr - for (size_t i = 0; i < num_cmds; ++i) + catch (const std::exception& e) { - lua_pushinteger(L, retcodes[i]); - lua_rawseti(L, -4, i+1); - lua_pushlstring(L, std_outs[i].c_str(), std_outs[i].size()); - lua_rawseti(L, -3, i+1); - lua_pushlstring(L, std_errs[i].c_str(), std_errs[i].size()); - lua_rawseti(L, -2, i+1); + fprintf(stderr, "%s:%d: Exception occured in cleanup and result handling for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); + return luaL_error(L, "%s:%d: Exception occured in cleanup and result handling for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - - return 3; } diff --git a/thirdparty/luajit b/thirdparty/luajit index a4f56a4..84cb21f 160000 --- a/thirdparty/luajit +++ b/thirdparty/luajit @@ -1 +1 @@ -Subproject commit a4f56a459a588ae768801074b46ba0adcfb49eb1 +Subproject commit 84cb21ffaf648b472ff3884556e2c413e8abe179