| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /*
- * Copyright (c) 2012-2023 Daniele Bartolini et al.
- * SPDX-License-Identifier: MIT
- */
- #include "config.h"
- #include "core/containers/array.inl"
- #include "core/containers/hash_set.inl"
- #include "core/filesystem/file.h"
- #include "core/memory/temp_allocator.inl"
- #include "core/process.h"
- #include "core/strings/dynamic_string.inl"
- #include "core/strings/string_stream.inl"
- #include "core/strings/string_view.inl"
- #include "resource/compile_options.inl"
- #include "resource/lua_resource.h"
- #if CROWN_DEBUG
- #define LUAJIT_FLAGS "-bg" // Keep debug info
- #else
- #define LUAJIT_FLAGS "-b"
- #endif
- namespace crown
- {
- namespace lua_resource
- {
- const char *program(const LuaResource *lr)
- {
- return (char *)&lr[1];
- }
- } // namespace lua_resource
- #if CROWN_CAN_COMPILE
- namespace lua_resource_internal
- {
- static const char *skip_blanks(const char *lua)
- {
- lua = skip_spaces(lua);
- if (*lua == '-') {
- ++lua;
- if (*lua++ == '-' && *lua++ == '[' && *lua++ == '[') {
- // Multi-line comment.
- const char *mlc_end = strstr(lua, "--]]");
- if (mlc_end != NULL)
- lua = mlc_end + 4;
- else
- lua += strlen(lua);
- } else {
- // Single-line comment.
- while (*lua && *lua != '\n')
- ++lua;
- }
- }
- return skip_spaces(lua);
- }
- void find_requirements(HashSet<StringView> &requirements, const char *lua)
- {
- while (*lua) {
- lua = skip_blanks(lua);
- if (*lua == 'r') { // Find require()s.
- const char *require = strstr(lua, "require");
- if (!require) {
- ++lua;
- continue;
- }
- lua = skip_blanks(require + 7);
- if (*lua == '(')
- ++lua;
- lua = skip_blanks(lua);
- if (*lua == '\'' || *lua == '"') {
- const char *param_begin = lua + 1;
- const char *param_end = strchr(param_begin, *lua);
- if (param_end != NULL) {
- hash_set::insert(requirements
- , StringView(param_begin, param_end - param_begin)
- );
- lua = param_end + 1;
- }
- }
- } else if (*lua == '-' || isspace(*lua)) {
- lua = skip_blanks(lua);
- } else if (*lua) {
- ++lua;
- }
- }
- }
- s32 compile(CompileOptions &opts)
- {
- TempAllocator1024 ta;
- DynamicString lua_src(ta);
- DynamicString lua_out(ta);
- opts.absolute_path(lua_src, opts.source_path());
- opts.temporary_path(lua_out, "lua");
- const char *argv[] =
- {
- EXE_PATH("luajit"),
- LUAJIT_FLAGS,
- lua_src.c_str(),
- lua_out.c_str(),
- NULL
- };
- Process pr;
- s32 sc = pr.spawn(argv, CROWN_PROCESS_STDOUT_PIPE | CROWN_PROCESS_STDERR_MERGE);
- DATA_COMPILER_ASSERT(sc == 0
- , opts
- , "Failed to spawn `%s`"
- , argv[0]
- );
- // Scan the .lua code for requirements.
- Buffer lua_code = opts.read();
- HashSet<StringView> requirements(default_allocator());
- lua_resource_internal::find_requirements(requirements, array::begin(lua_code));
- auto cur = hash_set::begin(requirements);
- auto end = hash_set::end(requirements);
- for (; cur != end; ++cur) {
- HASH_SET_SKIP_HOLE(requirements, cur);
- TempAllocator256 ta;
- DynamicString name(ta);
- name = *cur;
- opts.add_requirement("lua", name.c_str());
- }
- StringStream output(ta);
- opts.read_output(output, pr);
- s32 ec = pr.wait();
- DATA_COMPILER_ASSERT(ec == 0
- , opts
- , "Failed to compile lua:\n%s"
- , string_stream::c_str(output)
- );
- Buffer blob = opts.read_temporary(lua_out.c_str());
- opts.delete_file(lua_out.c_str());
- LuaResource lr;
- lr.version = RESOURCE_HEADER(RESOURCE_VERSION_SCRIPT);
- lr.size = array::size(blob);
- opts.write(lr.version);
- opts.write(lr.size);
- opts.write(blob);
- return 0;
- }
- } // namespace lua_resource_internal
- #endif // if CROWN_CAN_COMPILE
- } // namespace crown
|