Added CMake builder.

This commit is contained in:
g012 2017-09-27 01:33:21 +02:00
parent e808ee4e43
commit 55381d271b
9 changed files with 377 additions and 19 deletions

109
CMakeLists.txt Normal file
View File

@ -0,0 +1,109 @@
cmake_minimum_required(VERSION 3.1)
project(l65)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(L65_SOURCE_DIR ${PROJECT_SOURCE_DIR})
set(L65_BINARY_DIR ${PROJECT_BINARY_DIR})
set(L65_VERSION_MAJOR "1")
set(L65_VERSION_MINOR "0")
set(L65_VERSION_REVISION "0")
set(L65_VERSION "${L65_VERSION_MAJOR}.${L65_VERSION_MINOR}.${L65_VERSION_REVISION}")
configure_file("${L65_SOURCE_DIR}/l65cfg.lua.in" "${L65_BINARY_DIR}/l65cfg.lua")
set(LINKLIBS)
if (MSVC)
set(USE_MSVC_RUNTIME_LIBRARY_DLL OFF CACHE BOOL "" FORCE)
add_definitions(-D_HAS_EXCEPTIONS=0 -DWIN32_LEAN_AND_MEAN -DUNICODE -D_UNICODE)
add_definitions(-DNOMINMAX -D_USE_MATH_DEFINES)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
foreach (flag CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (${flag} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
endif()
if (${flag} MATCHES "/MDd")
string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
endif()
if(${flag} MATCHES "/EHsc")
string(REGEX REPLACE "/EHsc" "/EHs-c-" ${flag} "${${flag}}")
endif()
if(${flag} MATCHES "/GR")
string(REGEX REPLACE "/GR" "/GR-" ${flag} "${${flag}}")
endif()
if(${flag} MATCHES "/Gm")
string(REGEX REPLACE "/Gm" "/Gm-" ${flag} "${${flag}}")
endif()
endforeach()
add_compile_options(/WX /MP /fp:fast /volatile:iso)
add_compile_options(/wd4103 /wd4244 /wd4456 /wd4554 /wd4557 /wd4702 /wd6255 /wd6262 /wd28278)
else ()
if (APPLE)
add_definitions(-DLUA_USE_MACOSX)
else ()
add_definitions(-DLUA_USE_LINUX)
endif ()
add_definitions(-D_FILE_OFFSET_BITS=64)
add_compile_options(-fno-strict-aliasing -fomit-frame-pointer -ffast-math -fvisibility=hidden -fno-threadsafe-statics -fvisibility-inlines-hidden)
add_compile_options(-fno-rtti -fno-exceptions)
add_compile_options(-Werror -Wsign-compare -Wno-dangling-else -Wno-missing-braces -Wno-unused-function -Wno-shift-op-parentheses -Wno-unused-variable -Wno-switch -Wno-parentheses)
endif()
set(L65_SOURCES
${L65_SOURCE_DIR}/lfs.c
${L65_SOURCE_DIR}/lpeg.c
${L65_SOURCE_DIR}/main.c
)
set(L65_HEADERS
${L65_SOURCE_DIR}/lua.h
${L65_BINARY_DIR}/scripts.h
)
set(L65_RESOURCES
${L65_SOURCE_DIR}/6502.lua
${L65_SOURCE_DIR}/l65.lua
${L65_BINARY_DIR}/l65cfg.lua
${L65_SOURCE_DIR}/vcs.l65
)
add_executable(embed ${L65_SOURCE_DIR}/embed.c)
file(GLOB L65_FILES ${L65_SOURCE_DIR}/*.l65)
add_custom_command(
OUTPUT ${L65_BINARY_DIR}/scripts.h
COMMAND embed -o ${L65_BINARY_DIR}/scripts.h ${L65_SOURCE_DIR}/6502.lua ${L65_SOURCE_DIR}/l65.lua ${L65_BINARY_DIR}/l65cfg.lua ${L65_FILES}
)
add_executable(${PROJECT_NAME} ${L65_SOURCES} ${L65_HEADERS} ${L65_RESOURCES})
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99)
target_include_directories(${PROJECT_NAME} PRIVATE "${L65_SOURCE_DIR}" "${L65_BINARY_DIR}")
if (MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/INCREMENTAL:NO /MANIFEST:NO /SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup")
elseif (UNIX)
list(APPEND LINKLIBS m dl)
endif()
target_link_libraries(${PROJECT_NAME} ${LINKLIBS})

152
embed.c Normal file
View File

@ -0,0 +1,152 @@
#define LUA_IMPLEMENTATION
#include "lua.h"
#define PROGNAME "embed" /* default program name */
#define OUTPUT "scripts.h" /* default output file */
static int dumping = 1; /* dump bytecodes? */
static int stripping = 0; /* strip debug information? */
static char Output[] = { OUTPUT }; /* default output file name */
static const char* output = Output; /* actual output file name */
static const char* progname = PROGNAME; /* actual program name */
static void fatal(const char* message)
{
fprintf(stderr, "%s: %s\n", progname, message);
exit(EXIT_FAILURE);
}
static void cannot(const char* what)
{
fprintf(stderr, "%s: cannot %s %s: %s\n", progname, what, output, strerror(errno));
exit(EXIT_FAILURE);
}
static void usage(const char* message)
{
if (*message == '-')
fprintf(stderr, "%s: unrecognized option '%s'\n", progname, message);
else
fprintf(stderr, "%s: %s\n", progname, message);
fprintf(stderr,
"usage: %s [options] [filenames]\n"
"Available options are:\n"
" -o name output to file 'name' (default is \"%s\")\n"
, progname, Output);
exit(EXIT_FAILURE);
}
#define IS(s) (strcmp(argv[i],s)==0)
static int doargs(int argc, char* argv[])
{
int i;
if (argv[0] != NULL && *argv[0] != 0) progname = argv[0];
for (i = 1; i < argc; i++)
{
if (*argv[i] != '-') /* end of options; keep it */
break;
else if (IS("--")) /* end of options; skip it */
{
++i;
break;
}
else if (IS("-")) /* end of options; use stdin */
break;
else if (IS("-o")) /* output file */
{
output = argv[++i];
if (output == NULL || *output == 0 || (*output == '-' && output[1] != 0))
usage("'-o' needs argument");
if (IS("-")) output = NULL;
}
else /* unknown option */
usage(argv[i]);
}
return i;
}
#define FUNCTION "(function()end)();"
static int w_o;
static int writer(lua_State* L, const void* p, size_t size, void* f)
{
for (size_t i = 0; i < size; ++i)
{
if ((i+w_o) % 32 == 0) fprintf(f, "\n");
fprintf(f, "0x%02X, ", (int)(((unsigned char*)p)[i]));
}
w_o += size;
return size == 0;
}
static int pmain(lua_State* L)
{
int argc = (int)lua_tointeger(L, 1);
char** argv = (char**)lua_touserdata(L, 2);
int i;
if (!lua_checkstack(L, argc)) fatal("too many input files");
FILE* f = (output == NULL) ? stdout : fopen(output, "wb");
if (f == NULL) cannot("open");
for (i = 0; i < argc; i++)
{
int compile = 0;
const char* filename = IS("-") ? NULL : argv[i];
if (!filename) fatal("invalid input file");
char *ufname = strdup(filename);
int fnix = 0; for (int i = 0; ufname[i]; ++i) { if (ufname[i] == '/' || ufname[i] == '\\') fnix = i + 1; if (ufname[i] == '.') ufname[i] = '_'; }
char *name = malloc(1024);
sprintf(name, "script_%s", ufname + fnix);
free(ufname);
int fnl = strlen(filename);
compile = fnl > 4 && !strcmp(".lua", filename + fnl - 4);
if (compile)
{
if (luaL_loadfile(L, filename) != LUA_OK) fatal(lua_tostring(L, -1));
fprintf(f, "static const unsigned char %s[] = {", name);
w_o = 0;
lua_dump(L, writer, f, 0);
lua_pop(L, 1);
fprintf(f, "\n};\n");
}
else
{
FILE* l = fopen(filename, "rb"); if (!l) cannot("open");
fseek(l, 0, SEEK_END);
int size = (int)ftell(l);
rewind(l);
unsigned char *buffer = malloc(size);
if (size != fread(buffer, 1, size, l)) fatal("failed reading input file");
fclose(l);
fprintf(f, "static const char %s[] = {", name);
for (int i = 0; i < size; ++i)
{
if (i % 32 == 0) fprintf(f, "\n");
fprintf(f, "0x%02X, ", (int)buffer[i]);
}
fprintf(f, "\n};\n");
free(buffer);
}
free(name);
}
if (ferror(f)) cannot("write");
if (fclose(f)) cannot("close");
return 0;
}
int main(int argc, char* argv[])
{
lua_State* L;
int i = doargs(argc, argv);
argc -= i; argv += i;
if (argc <= 0) usage("no input files given");
L = luaL_newstate();
if (L == NULL) fatal("cannot create state: not enough memory");
lua_pushcfunction(L, &pmain);
lua_pushinteger(L, argc);
lua_pushlightuserdata(L, argv);
if (lua_pcall(L, 2, 0, 0) != LUA_OK) fatal(lua_tostring(L, -1));
lua_close(L);
return EXIT_SUCCESS;
}

28
l65.lua
View File

@ -2478,15 +2478,31 @@ l65 = {
loadfile_org = loadfile,
dofile_org = dofile,
}
do
local getembedded = type(arg[-1]) == 'function' and arg[-1]
l65.load_embedded = function(name)
if not getembedded then return end
local src,isl65 = getembedded(name)
if not src then return end
if isl65 then
local filename = name .. '.l65'
local st, ast = assert(l65.parse(src))
local bc = assert(l65.load_org(l65.format(ast), filename))
return bc, filename
else
local filename = name .. '.lua'
local bc = assert(l65.load_org(src, filename))
return bc, filename
end
end
end
l65.searcher = function(name)
local filename,err = package.searchpath(name, l65.search_path, '.', '.')
if not filename then return err end
local file = io.open(filename, 'rb')
if not file then return "failed to open " .. filename .. " for reading" end
local file = assert(io.open(filename, 'rb'))
local src = file:read('*a')
file:close()
local st, ast = l65.parse(src)
if not st then print(ast) return end
local st, ast = assert(l65.parse(src))
local bc = assert(l65.load_org(l65.format(ast), filename))
return bc, filename
end
@ -2543,6 +2559,7 @@ l65.uninstallhooks = function()
dofile = l65.dofile_org
end
end
table.insert(package.searchers, l65.searcher_index, l65.load_embedded)
l65.installhooks()
function getopt(optstring, ...)
@ -2578,8 +2595,9 @@ function getopt(optstring, ...)
end)
end
local cfg=require"l65cfg" l65.cfg=cfg
local version = function()
print("1.0.0")
print(string.format("l65 %s", cfg.version))
end
local usage = function()
print(string.format([[

8
l65cfg.lua Normal file
View File

@ -0,0 +1,8 @@
local M = {}
M.major = 1
M.minor = 0
M.revision = 0
M.version = "1.0.0"
return M

8
l65cfg.lua.in Normal file
View File

@ -0,0 +1,8 @@
local M = {}
M.major = ${L65_VERSION_MAJOR}
M.minor = ${L65_VERSION_MINOR}
M.revision = ${L65_VERSION_REVISION}
M.version = "${L65_VERSION}"
return M

16
lfs.c
View File

@ -2,6 +2,8 @@
* lfs.c and lfs.h mixed together
*/
#include "lua.h"
/*
** LuaFileSystem
** Copyright Kepler Project 2003 - 2016 (http://keplerproject.github.io/luafilesystem)
@ -16,9 +18,9 @@
#endif
#ifdef _WIN32
#define chdir(p) (_chdir(p))
#define getcwd(d, s) (_getcwd(d, s))
#define rmdir(p) (_rmdir(p))
//#define chdir(p) (_chdir(p))
//#define getcwd(d, s) (_getcwd(d, s))
//#define rmdir(p) (_rmdir(p))
#define LFS_EXPORT __declspec (dllexport)
#ifndef fileno
#define fileno(f) (_fileno(f))
@ -102,12 +104,6 @@ LFS_EXPORT int luaopen_lfs (lua_State *L);
#define LFS_MAXPATHLEN MAXPATHLEN
#endif
//#include <lua.h>
//#include <lauxlib.h>
//#include <lualib.h>
//#include "lfs.h"
#define LFS_VERSION "1.6.3"
#define LFS_LIBNAME "lfs"
@ -325,7 +321,7 @@ static int lfs_lock_dir(lua_State *L) {
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
}
strcpy(ln, path); strcat(ln, lockfile);
if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
if((fd = CreateFileA(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
int en = GetLastError();
free(ln); lua_pushnil(L);

3
lpeg.c
View File

@ -7,6 +7,7 @@
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "lua.h"
// only exported function
int luaopen_lpeg (lua_State *L);
@ -25,8 +26,10 @@ int luaopen_lpeg (lua_State *L);
#if !defined(LPEG_DEBUG)
#ifndef NDEBUG
#define NDEBUG
#endif
#endif
#define VERSION "1.0.1"

2
lua.h
View File

@ -13930,7 +13930,7 @@ static int luai_searcherpreload (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */
lua_pushfstring(L, "\n\tno luai_field package.preload['%s']", name);
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
return 1;
}

70
main.c
View File

@ -1,15 +1,79 @@
#define LUA_IMPLEMENTATION
#include "lua.h"
#include "scripts.h"
extern int luaopen_lpeg(lua_State *L);
extern int luaopen_lfs(lua_State *L);
static struct script { const char *name; int t; const char *data; size_t sz; } embedded[] = {
{ "l65cfg", 0, script_l65cfg_lua, sizeof(script_l65cfg_lua) },
{ "vcs", 1, script_vcs_l65, sizeof(script_vcs_l65) },
};
static int getembedded(lua_State *L)
{
const char *name = lua_tostring(L, 1);
for (struct script *s = embedded, *e = s + sizeof(embedded) / sizeof(embedded[0]); s != e; ++s)
{
if (!strcmp(s->name, name))
{
lua_pushlstring(L, s->data, s->sz);
lua_pushboolean(L, s->t);
return 2;
}
}
return 0;
}
static int msghandler(lua_State *L)
{
const char *msg = lua_tostring(L, 1);
if (msg == NULL)
{
if (luaL_callmeta(L, 1, "__tostring") && lua_type(L, -1) == LUA_TSTRING)
return 1;
msg = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
}
luaL_traceback(L, L, msg, 1);
return 1;
}
int main(int argc, char *argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_require(L, "lpeg", luaopen_lpeg, 1); lua_pop(L, 1);
luaL_require(L, "lfs", luaopen_lfs, 1); lua_pop(L, 1);
return 0;
luaL_requiref(L, "lpeg", luaopen_lpeg, 1); lua_pop(L, 1);
luaL_requiref(L, "lfs", luaopen_lfs, 1); lua_pop(L, 1);
// preload embedded lua scripts
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
luaL_loadbufferx(L, script_6502_lua, sizeof(script_6502_lua), "6502.lua", "b");
lua_setfield(L, -2, "6502");
lua_pop(L, 1);
// error handler
lua_pushcfunction(L, msghandler);
// l65.lua script
luaL_loadbufferx(L, script_l65_lua, sizeof(script_l65_lua), "l65.lua", "b");
// arg[] table
lua_createtable(L, argc-1, 2);
lua_pushcfunction(L, getembedded); // pass embedded script lookup function as arg[-1]
lua_rawseti(L, -2, -1);
for (int i = 0; i < argc; i++) lua_pushstring(L, argv[i]), lua_rawseti(L, -2, i);
lua_pushvalue(L, -1);
lua_setglobal(L, "arg");
// ... arguments
{ int i; for (i = 1; i < argc; ++i) lua_rawgeti(L, -i, i); lua_remove(L, -i); }
// call l65
int status = lua_pcall(L, argc-1, 0, -argc-1);
if (status != LUA_OK)
{
const char *msg = lua_tostring(L, -1);
fprintf(stderr, "%s\n", msg);
lua_pop(L, 1);
}
lua_pop(L, 1); // remove msghandler
lua_close(L);
return status;
}