Merge pull request #722 from TerryE/luac-cross.2
Moving luac cross from master to dev
This commit is contained in:
commit
5d28de8595
|
@ -8,8 +8,10 @@
|
||||||
// #define LUA_USE_BUILTIN_IO // for io.xxx(), partially work
|
// #define LUA_USE_BUILTIN_IO // for io.xxx(), partially work
|
||||||
|
|
||||||
// #define LUA_USE_BUILTIN_OS // for os.xxx(), not work
|
// #define LUA_USE_BUILTIN_OS // for os.xxx(), not work
|
||||||
// #define LUA_USE_BUILTIN_DEBUG // for debug.xxx(), not work
|
// #define LUA_USE_BUILTIN_DEBUG
|
||||||
|
#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback()
|
||||||
|
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
#define LUA_USE_MODULES
|
#define LUA_USE_MODULES
|
||||||
|
|
||||||
#ifdef LUA_USE_MODULES
|
#ifdef LUA_USE_MODULES
|
||||||
|
@ -46,5 +48,6 @@
|
||||||
//#define LUA_USE_MODULES_HX711
|
//#define LUA_USE_MODULES_HX711
|
||||||
|
|
||||||
#endif /* LUA_USE_MODULES */
|
#endif /* LUA_USE_MODULES */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __USER_MODULES_H__ */
|
#endif /* __USER_MODULES_H__ */
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
|
//#include "user_interface.h"
|
||||||
|
#include "user_config.h"
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define ICACHE_RODATA_ATTR
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#include "c_stdlib.h"
|
#include "c_stdlib.h"
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#include "c_string.h"
|
#include "c_string.h"
|
||||||
#include "user_interface.h"
|
|
||||||
#include "user_config.h"
|
|
||||||
|
|
||||||
// const char *lua_init_value = "print(\"Hello world\")";
|
// const char *lua_init_value = "print(\"Hello world\")";
|
||||||
const char *lua_init_value = "@init.lua";
|
const char *lua_init_value = "@init.lua";
|
||||||
|
@ -21,7 +32,6 @@ const char *c_getenv(const char *__string)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
|
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
|
||||||
// void *c_malloc(size_t __size){
|
// void *c_malloc(size_t __size){
|
||||||
// if(__size>system_get_free_heap_size()){
|
// if(__size>system_get_free_heap_size()){
|
||||||
|
@ -43,7 +53,8 @@ const char *c_getenv(const char *__string)
|
||||||
// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
|
// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
|
||||||
// os_free(p);
|
// os_free(p);
|
||||||
// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
|
// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
|
||||||
// }
|
// }c_stdlib.s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// int c_rand(void){
|
// int c_rand(void){
|
||||||
|
@ -55,9 +66,8 @@ const char *c_getenv(const char *__string)
|
||||||
// }
|
// }
|
||||||
#include <_ansi.h>
|
#include <_ansi.h>
|
||||||
//#include <reent.h>
|
//#include <reent.h>
|
||||||
#include <string.h>
|
|
||||||
//#include "mprec.h"
|
//#include "mprec.h"
|
||||||
|
#endif
|
||||||
double powersOf10[] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = /* Table giving binary powers of 10. Entry */
|
double powersOf10[] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = /* Table giving binary powers of 10. Entry */
|
||||||
{
|
{
|
||||||
10., /* is 10^2^i. Used to convert decimal */
|
10., /* is 10^2^i. Used to convert decimal */
|
||||||
|
|
|
@ -4,17 +4,15 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//#include "c_assert.h"
|
|
||||||
#include "c_math.h"
|
|
||||||
#include "c_stdarg.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lapi_c
|
#define lapi_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
//#include C_HEADER_ASSERT
|
||||||
|
#include C_HEADER_MATH
|
||||||
|
#include C_HEADER_STRING
|
||||||
#include "lapi.h"
|
#include "lapi.h"
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "c_ctype.h"
|
#include "lua.h"
|
||||||
// #include "c_errno.h"
|
#include C_HEADER_CTYPE
|
||||||
#include "c_stdarg.h"
|
#include C_HEADER_ERRNO
|
||||||
#include "c_stdio.h"
|
#include C_HEADER_STDIO
|
||||||
#include "c_stdlib.h"
|
#include C_HEADER_STDLIB
|
||||||
#include "c_string.h"
|
#include C_HEADER_STRING
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
#include "flash_fs.h"
|
#include "flash_fs.h"
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This file uses only the official API of Lua.
|
/* This file uses only the official API of Lua.
|
||||||
** Any function declared here could be written as an application function.
|
** Any function declared here could be written as an application function.
|
||||||
|
@ -20,8 +24,6 @@
|
||||||
#define lauxlib_c
|
#define lauxlib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
|
||||||
#include "lua.h"
|
|
||||||
|
|
||||||
#include "lrotable.h"
|
#include "lrotable.h"
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
@ -573,7 +575,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
|
||||||
typedef struct LoadF {
|
typedef struct LoadF {
|
||||||
int extraline;
|
int extraline;
|
||||||
|
@ -647,7 +649,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include "c_fcntl.h"
|
#include C_HEADER_FCNTL
|
||||||
|
|
||||||
typedef struct LoadFSF {
|
typedef struct LoadFSF {
|
||||||
int extraline;
|
int extraline;
|
||||||
|
|
|
@ -9,11 +9,14 @@
|
||||||
#define lauxlib_h
|
#define lauxlib_h
|
||||||
|
|
||||||
|
|
||||||
//#include "c_stddef.h"
|
|
||||||
#include "c_stdio.h"
|
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <stdio.h>
|
||||||
|
#else
|
||||||
|
#include "c_stdio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(LUA_COMPAT_GETN)
|
#if defined(LUA_COMPAT_GETN)
|
||||||
LUALIB_API int (luaL_getn) (lua_State *L, int t);
|
LUALIB_API int (luaL_getn) (lua_State *L, int t);
|
||||||
|
@ -79,7 +82,7 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||||
|
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||||
#else
|
#else
|
||||||
LUALIB_API int (luaL_loadfsfile) (lua_State *L, const char *filename);
|
LUALIB_API int (luaL_loadfsfile) (lua_State *L, const char *filename);
|
||||||
|
|
|
@ -6,16 +6,14 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "c_ctype.h"
|
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lbaselib_c
|
#define lbaselib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lrotable.h"
|
#include "lrotable.h"
|
||||||
|
@ -295,7 +293,7 @@ static int luaB_loadstring (lua_State *L) {
|
||||||
|
|
||||||
static int luaB_loadfile (lua_State *L) {
|
static int luaB_loadfile (lua_State *L) {
|
||||||
const char *fname = luaL_optstring(L, 1, NULL);
|
const char *fname = luaL_optstring(L, 1, NULL);
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
return load_aux(L, luaL_loadfile(L, fname));
|
return load_aux(L, luaL_loadfile(L, fname));
|
||||||
#else
|
#else
|
||||||
return load_aux(L, luaL_loadfsfile(L, fname));
|
return load_aux(L, luaL_loadfsfile(L, fname));
|
||||||
|
@ -342,7 +340,7 @@ static int luaB_load (lua_State *L) {
|
||||||
static int luaB_dofile (lua_State *L) {
|
static int luaB_dofile (lua_State *L) {
|
||||||
const char *fname = luaL_optstring(L, 1, NULL);
|
const char *fname = luaL_optstring(L, 1, NULL);
|
||||||
int n = lua_gettop(L);
|
int n = lua_gettop(L);
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
if (luaL_loadfile(L, fname) != 0) lua_error(L);
|
if (luaL_loadfile(L, fname) != 0) lua_error(L);
|
||||||
#else
|
#else
|
||||||
if (luaL_loadfsfile(L, fname) != 0) lua_error(L);
|
if (luaL_loadfsfile(L, fname) != 0) lua_error(L);
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
|
|
||||||
#define lcode_c
|
#define lcode_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
|
||||||
#include "lcode.h"
|
#include "lcode.h"
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
|
|
|
@ -5,18 +5,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define ldblib_c
|
#define ldblib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lrotable.h"
|
#include "lrotable.h"
|
||||||
|
#include "user_modules.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ static int db_getregistry (lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
|
|
||||||
static int db_getmetatable (lua_State *L) {
|
static int db_getmetatable (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
|
@ -73,7 +75,7 @@ static void settabsi (lua_State *L, const char *i, int v) {
|
||||||
lua_setfield(L, -2, i);
|
lua_setfield(L, -2, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
static lua_State *getthread (lua_State *L, int *arg) {
|
static lua_State *getthread (lua_State *L, int *arg) {
|
||||||
if (lua_isthread(L, 1)) {
|
if (lua_isthread(L, 1)) {
|
||||||
*arg = 1;
|
*arg = 1;
|
||||||
|
@ -84,7 +86,7 @@ static lua_State *getthread (lua_State *L, int *arg) {
|
||||||
return L;
|
return L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
|
|
||||||
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
||||||
if (L == L1) {
|
if (L == L1) {
|
||||||
|
@ -324,7 +326,7 @@ static int db_debug (lua_State *L) {
|
||||||
lua_settop(L, 0); /* remove eventual returns */
|
lua_settop(L, 0); /* remove eventual returns */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LEVELS1 12 /* size of the first part of the stack */
|
#define LEVELS1 12 /* size of the first part of the stack */
|
||||||
#define LEVELS2 10 /* size of the second part of the stack */
|
#define LEVELS2 10 /* size of the second part of the stack */
|
||||||
|
@ -384,12 +386,15 @@ static int db_errorfb (lua_State *L) {
|
||||||
#define MIN_OPT_LEVEL 1
|
#define MIN_OPT_LEVEL 1
|
||||||
#include "lrodefs.h"
|
#include "lrodefs.h"
|
||||||
const LUA_REG_TYPE dblib[] = {
|
const LUA_REG_TYPE dblib[] = {
|
||||||
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
{LSTRKEY("debug"), LFUNCVAL(db_debug)},
|
{LSTRKEY("debug"), LFUNCVAL(db_debug)},
|
||||||
{LSTRKEY("getfenv"), LFUNCVAL(db_getfenv)},
|
{LSTRKEY("getfenv"), LFUNCVAL(db_getfenv)},
|
||||||
{LSTRKEY("gethook"), LFUNCVAL(db_gethook)},
|
{LSTRKEY("gethook"), LFUNCVAL(db_gethook)},
|
||||||
{LSTRKEY("getinfo"), LFUNCVAL(db_getinfo)},
|
{LSTRKEY("getinfo"), LFUNCVAL(db_getinfo)},
|
||||||
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
|
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
|
||||||
|
#endif
|
||||||
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
|
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
|
||||||
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
|
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
|
||||||
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
|
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
|
||||||
{LSTRKEY("setfenv"), LFUNCVAL(db_setfenv)},
|
{LSTRKEY("setfenv"), LFUNCVAL(db_setfenv)},
|
||||||
|
@ -397,6 +402,7 @@ const LUA_REG_TYPE dblib[] = {
|
||||||
{LSTRKEY("setlocal"), LFUNCVAL(db_setlocal)},
|
{LSTRKEY("setlocal"), LFUNCVAL(db_setlocal)},
|
||||||
{LSTRKEY("setmetatable"), LFUNCVAL(db_setmetatable)},
|
{LSTRKEY("setmetatable"), LFUNCVAL(db_setmetatable)},
|
||||||
{LSTRKEY("setupvalue"), LFUNCVAL(db_setupvalue)},
|
{LSTRKEY("setupvalue"), LFUNCVAL(db_setupvalue)},
|
||||||
|
#endif
|
||||||
{LSTRKEY("traceback"), LFUNCVAL(db_errorfb)},
|
{LSTRKEY("traceback"), LFUNCVAL(db_errorfb)},
|
||||||
{LNILKEY, LNILVAL}
|
{LNILKEY, LNILVAL}
|
||||||
};
|
};
|
|
@ -5,15 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdarg.h"
|
|
||||||
#include "c_stddef.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define ldebug_c
|
#define ldebug_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lapi.h"
|
#include "lapi.h"
|
||||||
#include "lcode.h"
|
#include "lcode.h"
|
||||||
|
|
|
@ -4,15 +4,14 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define ldo_c
|
#define ldo_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_stddef.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define ldump_c
|
#define ldump_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stddef.h"
|
|
||||||
|
|
||||||
#define lfunc_c
|
#define lfunc_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lgc_c
|
#define lgc_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_ctype.h"
|
|
||||||
#include "c_locale.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define llex_c
|
#define llex_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_CTYPE
|
||||||
|
#include C_HEADER_LOCALE
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
#include "llex.h"
|
#include "llex.h"
|
||||||
|
|
|
@ -9,12 +9,9 @@
|
||||||
|
|
||||||
|
|
||||||
//#include "c_limits.h"
|
//#include "c_limits.h"
|
||||||
//#include "c_stddef.h"
|
|
||||||
|
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
typedef LUAI_UINT32 lu_int32;
|
typedef LUAI_UINT32 lu_int32;
|
||||||
|
|
||||||
typedef LUAI_UMEM lu_mem;
|
typedef LUAI_UMEM lu_mem;
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_math.h"
|
|
||||||
|
|
||||||
#define lmathlib_c
|
#define lmathlib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
#include C_HEADER_MATH
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
@ -35,7 +35,7 @@ static int math_abs (lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef LUA_NUMBER_INTEGRAL
|
#ifndef LUA_NUMBER_INTEGRAL
|
||||||
|
#if 0
|
||||||
static int math_sin (lua_State *L) {
|
static int math_sin (lua_State *L) {
|
||||||
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
|
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -85,6 +85,7 @@ static int math_atan2 (lua_State *L) {
|
||||||
lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int math_ceil (lua_State *L) {
|
static int math_ceil (lua_State *L) {
|
||||||
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
|
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
|
||||||
|
@ -95,7 +96,7 @@ static int math_floor (lua_State *L) {
|
||||||
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
|
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
static int math_fmod (lua_State *L) {
|
static int math_fmod (lua_State *L) {
|
||||||
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -108,6 +109,7 @@ static int math_modf (lua_State *L) {
|
||||||
lua_pushnumber(L, fp);
|
lua_pushnumber(L, fp);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else // #ifndef LUA_NUMBER_INTEGRAL
|
#else // #ifndef LUA_NUMBER_INTEGRAL
|
||||||
|
|
||||||
|
@ -173,7 +175,7 @@ static int math_pow (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
#ifndef LUA_NUMBER_INTEGRAL
|
#ifndef LUA_NUMBER_INTEGRAL
|
||||||
|
#if 0
|
||||||
static int math_log (lua_State *L) {
|
static int math_log (lua_State *L) {
|
||||||
lua_pushnumber(L, log(luaL_checknumber(L, 1)));
|
lua_pushnumber(L, log(luaL_checknumber(L, 1)));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -210,6 +212,7 @@ static int math_ldexp (lua_State *L) {
|
||||||
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
|
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // #ifdef LUA_NUMBER_INTEGRAL
|
#endif // #ifdef LUA_NUMBER_INTEGRAL
|
||||||
|
|
||||||
|
@ -306,6 +309,8 @@ static int math_randomseed (lua_State *L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MIN_OPT_LEVEL 1
|
#define MIN_OPT_LEVEL 1
|
||||||
#include "lrodefs.h"
|
#include "lrodefs.h"
|
||||||
const LUA_REG_TYPE math_map[] = {
|
const LUA_REG_TYPE math_map[] = {
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stddef.h"
|
|
||||||
|
|
||||||
#define lmem_c
|
#define lmem_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,11 @@
|
||||||
#define lmem_h
|
#define lmem_h
|
||||||
|
|
||||||
|
|
||||||
|
//#ifdef LUA_CROSS_COMPILER
|
||||||
|
//#include <stddef.h>
|
||||||
|
//#else
|
||||||
//#include "c_stddef.h"
|
//#include "c_stddef.h"
|
||||||
|
//#endif
|
||||||
|
|
||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
|
@ -9,15 +9,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "c_fcntl.h"
|
|
||||||
#include "flash_fs.h"
|
|
||||||
|
|
||||||
#define loadlib_c
|
#define loadlib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
#include C_HEADER_FCNTL
|
||||||
|
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
|
#include "flash_fs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
@ -328,7 +331,7 @@ static int ll_loadlib (lua_State *L) {
|
||||||
** 'require' function
|
** 'require' function
|
||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
static int readable (const char *filename) {
|
static int readable (const char *filename) {
|
||||||
FILE *f = c_fopen(filename, "r"); /* try to open file */
|
FILE *f = c_fopen(filename, "r"); /* try to open file */
|
||||||
if (f == NULL) return 0; /* open failed */
|
if (f == NULL) return 0; /* open failed */
|
||||||
|
@ -389,7 +392,7 @@ static int loader_Lua (lua_State *L) {
|
||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
filename = findfile(L, name, "path");
|
filename = findfile(L, name, "path");
|
||||||
if (filename == NULL) return 1; /* library not found in this path */
|
if (filename == NULL) return 1; /* library not found in this path */
|
||||||
#if 0
|
#ifdef LUA_CROSS_COMPILER
|
||||||
if (luaL_loadfile(L, filename) != 0)
|
if (luaL_loadfile(L, filename) != 0)
|
||||||
#else
|
#else
|
||||||
if (luaL_loadfsfile(L, filename) != 0)
|
if (luaL_loadfsfile(L, filename) != 0)
|
||||||
|
|
|
@ -4,16 +4,15 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_ctype.h"
|
|
||||||
#include "c_stdarg.h"
|
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lobject_c
|
#define lobject_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
|
@ -21,9 +20,11 @@
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
#include "lvm.h"
|
#include "lvm.h"
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
#include "flash_api.h"
|
#include "flash_api.h"
|
||||||
|
#else
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
const TValue luaO_nilobject_ = {LUA_TVALUE_NIL};
|
const TValue luaO_nilobject_ = {LUA_TVALUE_NIL};
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,9 +65,11 @@ int luaO_log2 (unsigned int x) {
|
||||||
};
|
};
|
||||||
int l = -1;
|
int l = -1;
|
||||||
while (x >= 256) { l += 8; x >>= 8; }
|
while (x >= 256) { l += 8; x >>= 8; }
|
||||||
// return l + log_2[x];
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
return l + log_2[x];
|
||||||
|
#else
|
||||||
return l + byte_of_aligned_array(log_2,x);
|
return l + byte_of_aligned_array(log_2,x);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +98,21 @@ int luaO_str2d (const char *s, lua_Number *result) {
|
||||||
*result = lua_str2number(s, &endptr);
|
*result = lua_str2number(s, &endptr);
|
||||||
if (endptr == s) return 0; /* conversion failed */
|
if (endptr == s) return 0; /* conversion failed */
|
||||||
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
|
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
|
||||||
|
#if defined(LUA_CROSS_COMPILER)
|
||||||
|
{
|
||||||
|
long lres = strtoul(s, &endptr, 16);
|
||||||
|
#if LONG_MAX != 2147483647L
|
||||||
|
if (lres & ~0xffffffffL)
|
||||||
|
*result = cast_num(-1);
|
||||||
|
else if (lres & 0x80000000L)
|
||||||
|
*result = cast_num(lres | ~0x7fffffffL);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
*result = cast_num(lres);
|
||||||
|
}
|
||||||
|
#else
|
||||||
*result = cast_num(c_strtoul(s, &endptr, 16));
|
*result = cast_num(c_strtoul(s, &endptr, 16));
|
||||||
|
#endif
|
||||||
if (*endptr == '\0') return 1; /* most common case */
|
if (*endptr == '\0') return 1; /* most common case */
|
||||||
while (isspace(cast(unsigned char, *endptr))) endptr++;
|
while (isspace(cast(unsigned char, *endptr))) endptr++;
|
||||||
if (*endptr != '\0') return 0; /* invalid trailing characters? */
|
if (*endptr != '\0') return 0; /* invalid trailing characters? */
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#ifndef lobject_h
|
#ifndef lobject_h
|
||||||
#define lobject_h
|
#define lobject_h
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <stdarg.h>
|
||||||
|
#else
|
||||||
#include "c_stdarg.h"
|
#include "c_stdarg.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
#define lopcodes_c
|
#define lopcodes_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
|
#include "luac_cross.h"
|
||||||
#include "lopcodes.h"
|
#include "lopcodes.h"
|
||||||
|
|
||||||
|
|
||||||
/* ORDER OP */
|
/* ORDER OP */
|
||||||
|
|
||||||
const char *const luaP_opnames[NUM_OPCODES+1] = {
|
const char *const luaP_opnames[NUM_OPCODES+1] = {
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lparser_c
|
#define lparser_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lcode.h"
|
#include "lcode.h"
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/* Read-only tables for Lua */
|
/* Read-only tables for Lua */
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "lrotable.h"
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
#include "lrotable.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stddef.h"
|
|
||||||
|
|
||||||
#define lstate_c
|
#define lstate_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lstring_c
|
#define lstring_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
|
|
|
@ -5,16 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_ctype.h"
|
|
||||||
#include "c_stddef.h"
|
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lstrlib_c
|
#define lstrlib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
** Hence even when the load factor reaches 100%, performance remains good.
|
** Hence even when the load factor reaches 100%, performance remains good.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_math.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define ltable_c
|
#define ltable_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_MATH
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stddef.h"
|
|
||||||
|
|
||||||
#define ltablib_c
|
#define ltablib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define ltm_c
|
#define ltm_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
|
@ -8,10 +8,18 @@
|
||||||
|
|
||||||
#ifndef lua_h
|
#ifndef lua_h
|
||||||
#define lua_h
|
#define lua_h
|
||||||
|
#ifdef LUAC_CROSS_FILE
|
||||||
|
#include "luac_cross.h"
|
||||||
|
#endif
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#else
|
||||||
#include "c_stdarg.h"
|
#include "c_stdarg.h"
|
||||||
#include "c_stddef.h"
|
#include "c_stddef.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "luaconf.h"
|
#include "luaconf.h"
|
||||||
|
|
||||||
|
@ -382,7 +390,9 @@ typedef struct __lua_load{
|
||||||
|
|
||||||
int lua_main( int argc, char **argv );
|
int lua_main( int argc, char **argv );
|
||||||
|
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
void lua_handle_input (bool force);
|
void lua_handle_input (bool force);
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
** Header to allow luac.cross compile within NodeMCU
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
#ifndef luac_cross_h
|
||||||
|
#define luac_cross_h
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
|
||||||
|
#define C_HEADER_ASSERT <assert.h>
|
||||||
|
#define C_HEADER_CTYPE <ctype.h>
|
||||||
|
#define C_HEADER_ERRNO <errno.h>
|
||||||
|
#define C_HEADER_FCNTL <fcntl.h>
|
||||||
|
#define C_HEADER_LOCALE <locale.h>
|
||||||
|
#define C_HEADER_MATH <math.h>
|
||||||
|
#define C_HEADER_STDIO <stdio.h>
|
||||||
|
#define C_HEADER_STDLIB <stdlib.h>
|
||||||
|
#define C_HEADER_STRING <string.h>
|
||||||
|
#define C_HEADER_TIME <time.h>
|
||||||
|
|
||||||
|
#define ICACHE_RODATA_ATTR
|
||||||
|
|
||||||
|
#define c_abs abs
|
||||||
|
#define c_exit exit
|
||||||
|
#define c_fclose fclose
|
||||||
|
#define c_feof feof
|
||||||
|
#define c_ferror ferror
|
||||||
|
#define c_fopen fopen
|
||||||
|
#define c_fread fread
|
||||||
|
#define c_free free
|
||||||
|
#define c_freopen freopen
|
||||||
|
#define c_getc getc
|
||||||
|
#define c_getenv getenv
|
||||||
|
#define c_memcmp memcmp
|
||||||
|
#define c_memcpy memcpy
|
||||||
|
#define c_printf printf
|
||||||
|
#define c_puts puts
|
||||||
|
#define c_reader reader
|
||||||
|
#define c_realloc realloc
|
||||||
|
#define c_sprintf sprintf
|
||||||
|
#define c_stderr stderr
|
||||||
|
#define c_stdin stdin
|
||||||
|
#define c_stdout stdout
|
||||||
|
#define c_strcat strcat
|
||||||
|
#define c_strchr strchr
|
||||||
|
#define c_strcmp strcmp
|
||||||
|
#define c_strcoll strcoll
|
||||||
|
#define c_strcpy strcpy
|
||||||
|
#define c_strcspn strcspn
|
||||||
|
#define c_strerror strerror
|
||||||
|
#define c_strlen strlen
|
||||||
|
#define c_strncat strncat
|
||||||
|
#define c_strncmp strncmp
|
||||||
|
#define c_strncpy strncpy
|
||||||
|
#define c_strpbrk strpbrk
|
||||||
|
#define c_strrchr strrchr
|
||||||
|
#define c_strstr strstr
|
||||||
|
double c_strtod(const char *__n, char **__end_PTR);
|
||||||
|
#define c_strtoul strtoul
|
||||||
|
#define c_ungetc ungetc
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define C_HEADER_ASSERT "c_assert.h"
|
||||||
|
#define C_HEADER_CTYPE "c_ctype.h"
|
||||||
|
#define C_HEADER_ERRNO "c_errno.h"
|
||||||
|
#define C_HEADER_FCNTL "c_fcntl.h"
|
||||||
|
#define C_HEADER_LOCALE "c_locale.h"
|
||||||
|
#define C_HEADER_MATH "c_math.h"
|
||||||
|
#define C_HEADER_STDIO "c_stdio.h"
|
||||||
|
#define C_HEADER_STDLIB "c_stdlib.h"
|
||||||
|
#define C_HEADER_STRING "c_string.h"
|
||||||
|
#define C_HEADER_TIME "c_time.h"
|
||||||
|
|
||||||
|
#endif /* LUA_CROSS_COMPILER */
|
||||||
|
#endif /* luac_cross_h */
|
|
@ -4,12 +4,14 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include <errno.h>
|
#include "luac_cross.h"
|
||||||
#include <locale.h>
|
#include C_HEADER_ERRNO
|
||||||
#include <stdlib.h>
|
#include C_HEADER_LOCALE
|
||||||
#include <string.h>
|
#include C_HEADER_STDLIB
|
||||||
#include <time.h>
|
#include C_HEADER_STRING
|
||||||
|
#include C_HEADER_TIME
|
||||||
|
|
||||||
#define loslib_c
|
#define loslib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
|
@ -4,10 +4,13 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_errno.h"
|
#define LUAC_CROSS_FILE
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
#include "luac_cross.h"
|
||||||
#include "c_string.h"
|
#include C_HEADER_ERRNO
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STDLIB
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#define luac_c
|
#define luac_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
|
@ -4,8 +4,11 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_ctype.h"
|
#define LUAC_CROSS_FILE
|
||||||
#include "c_stdio.h"
|
|
||||||
|
#include "luac_cross.h"
|
||||||
|
#include C_HEADER_CTYPE
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
|
||||||
#define luac_c
|
#define luac_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
|
@ -8,8 +8,13 @@
|
||||||
#ifndef lconfig_h
|
#ifndef lconfig_h
|
||||||
#define lconfig_h
|
#define lconfig_h
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#else
|
||||||
#include "c_limits.h"
|
#include "c_limits.h"
|
||||||
#include "c_stddef.h"
|
#include "c_stddef.h"
|
||||||
|
#endif
|
||||||
#include "user_config.h"
|
#include "user_config.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -252,7 +257,12 @@
|
||||||
#define lua_stdin_is_tty() isatty(0)
|
#define lua_stdin_is_tty() isatty(0)
|
||||||
#elif defined(LUA_WIN)
|
#elif defined(LUA_WIN)
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <stdio.h>
|
||||||
|
else
|
||||||
#include "c_stdio.h"
|
#include "c_stdio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
|
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
|
||||||
#else
|
#else
|
||||||
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
|
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
|
||||||
|
@ -294,8 +304,8 @@
|
||||||
** GNU readline and history facilities).
|
** GNU readline and history facilities).
|
||||||
*/
|
*/
|
||||||
#if defined(LUA_USE_STDIO)
|
#if defined(LUA_USE_STDIO)
|
||||||
#if defined(LUA_USE_READLINE)
|
#if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
|
||||||
#include "c_stdio.h"
|
#include <stdio.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
||||||
|
@ -303,7 +313,7 @@
|
||||||
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
|
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
|
||||||
add_history(lua_tostring(L, idx)); /* add it to history */
|
add_history(lua_tostring(L, idx)); /* add it to history */
|
||||||
#define lua_freeline(L,b) ((void)L, c_free(b))
|
#define lua_freeline(L,b) ((void)L, c_free(b))
|
||||||
#else // #if defined(LUA_USE_READLINE)
|
#else // #if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
|
||||||
#define lua_readline(L,b,p) \
|
#define lua_readline(L,b,p) \
|
||||||
((void)L, c_fputs(p, c_stdout), c_fflush(c_stdout), /* show prompt */ \
|
((void)L, c_fputs(p, c_stdout), c_fflush(c_stdout), /* show prompt */ \
|
||||||
c_fgets(b, LUA_MAXINPUT, c_stdin) != NULL) /* get line */
|
c_fgets(b, LUA_MAXINPUT, c_stdin) != NULL) /* get line */
|
||||||
|
@ -623,7 +633,11 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
|
||||||
@@ The luai_num* macros define the primitive operations over numbers.
|
@@ The luai_num* macros define the primitive operations over numbers.
|
||||||
*/
|
*/
|
||||||
#if defined(LUA_CORE)
|
#if defined(LUA_CORE)
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <math.h>
|
||||||
|
#else
|
||||||
#include "c_math.h"
|
#include "c_math.h"
|
||||||
|
#endif
|
||||||
#define luai_numadd(a,b) ((a)+(b))
|
#define luai_numadd(a,b) ((a)+(b))
|
||||||
#define luai_numsub(a,b) ((a)-(b))
|
#define luai_numsub(a,b) ((a)-(b))
|
||||||
#define luai_nummul(a,b) ((a)*(b))
|
#define luai_nummul(a,b) ((a)*(b))
|
||||||
|
@ -866,7 +880,10 @@ union luai_Cast { double l_d; long l_l; };
|
||||||
|
|
||||||
#define LUA_INTFRMLEN "l"
|
#define LUA_INTFRMLEN "l"
|
||||||
#define LUA_INTFRM_T long
|
#define LUA_INTFRM_T long
|
||||||
|
#ifndef LUA_CROSS_COMPILER
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef long int32_t;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "c_types.h"
|
|
||||||
|
|
||||||
#define lundump_c
|
#define lundump_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
#ifndef lundump_h
|
#ifndef lundump_h
|
||||||
#define lundump_h
|
#define lundump_h
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
#include "c_stdint.h"
|
#include "c_stdint.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lzio.h"
|
#include "lzio.h"
|
||||||
|
|
|
@ -5,15 +5,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_stdio.h"
|
|
||||||
#include "c_stdlib.h"
|
|
||||||
#include "c_string.h"
|
|
||||||
#include "c_math.h"
|
|
||||||
|
|
||||||
#define lvm_c
|
#define lvm_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STDIO
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
#include C_HEADER_MATH
|
||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "c_string.h"
|
|
||||||
|
|
||||||
#define lzio_c
|
#define lzio_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include C_HEADER_STRING
|
||||||
|
|
||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#define linit_c
|
#define linit_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUAC_CROSS_FILE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ static const luaL_Reg lualibs[] = {
|
||||||
{LUA_TABLIBNAME, luaopen_table},
|
{LUA_TABLIBNAME, luaopen_table},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LUA_USE_BUILTIN_DEBUG)
|
#if defined(LUA_USE_BUILTIN_DEBUG) || defined(LUA_USE_BUILTIN_DEBUG_MINIMAL)
|
||||||
{LUA_DBLIBNAME, luaopen_debug},
|
{LUA_DBLIBNAME, luaopen_debug},
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,7 +72,7 @@ extern const luaR_entry syslib[];
|
||||||
extern const luaR_entry tab_funcs[];
|
extern const luaR_entry tab_funcs[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LUA_USE_BUILTIN_DEBUG)
|
#if defined(LUA_USE_BUILTIN_DEBUG) || defined(LUA_USE_BUILTIN_DEBUG_MINIMAL)
|
||||||
extern const luaR_entry dblib[];
|
extern const luaR_entry dblib[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ const luaR_table lua_rotable[] =
|
||||||
{LUA_TABLIBNAME, tab_funcs},
|
{LUA_TABLIBNAME, tab_funcs},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LUA_USE_BUILTIN_DEBUG)
|
#if defined(LUA_USE_BUILTIN_DEBUG) || defined(LUA_USE_BUILTIN_DEBUG_MINIMAL)
|
||||||
{LUA_DBLIBNAME, dblib},
|
{LUA_DBLIBNAME, dblib},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,848 @@
|
||||||
|
-- eLua build system
|
||||||
|
|
||||||
|
module( ..., package.seeall )
|
||||||
|
|
||||||
|
local lfs = require "lfs"
|
||||||
|
local sf = string.format
|
||||||
|
utils = require "tools.utils"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Various helpers
|
||||||
|
|
||||||
|
-- Return the time of the last modification of the file
|
||||||
|
local function get_ftime( path )
|
||||||
|
local t = lfs.attributes( path, 'modification' )
|
||||||
|
return t or -1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if a given target name is phony
|
||||||
|
local function is_phony( target )
|
||||||
|
return target:find( "#phony" ) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a string with $(key) replaced with 'value'
|
||||||
|
local function expand_key( s, key, value )
|
||||||
|
if not value then return s end
|
||||||
|
local fmt = sf( "%%$%%(%s%%)", key )
|
||||||
|
return ( s:gsub( fmt, value ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a target name considering phony targets
|
||||||
|
local function get_target_name( s )
|
||||||
|
if not is_phony( s ) then return s end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 'Liniarize' a file name by replacing its path separators indicators with '_'
|
||||||
|
local function linearize_fname( s )
|
||||||
|
return ( s:gsub( "[\\/]", "__" ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: transform a table into a string if needed
|
||||||
|
local function table_to_string( t )
|
||||||
|
if not t then return nil end
|
||||||
|
if type( t ) == "table" then t = table.concat( t, " " ) end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: return the extended type of an object (takes into account __type)
|
||||||
|
local function exttype( o )
|
||||||
|
local t = type( o )
|
||||||
|
if t == "table" and o.__type then t = o:__type() end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Table utils
|
||||||
|
-- (from http://lua-users.org/wiki/TableUtils)
|
||||||
|
|
||||||
|
function table.val_to_str( v )
|
||||||
|
if "string" == type( v ) then
|
||||||
|
v = string.gsub( v, "\n", "\\n" )
|
||||||
|
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
|
||||||
|
return "'" .. v .. "'"
|
||||||
|
end
|
||||||
|
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
|
||||||
|
else
|
||||||
|
return "table" == type( v ) and table.tostring( v ) or tostring( v )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.key_to_str ( k )
|
||||||
|
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
|
||||||
|
return k
|
||||||
|
else
|
||||||
|
return "[" .. table.val_to_str( k ) .. "]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.tostring( tbl )
|
||||||
|
local result, done = {}, {}
|
||||||
|
for k, v in ipairs( tbl ) do
|
||||||
|
table.insert( result, table.val_to_str( v ) )
|
||||||
|
done[ k ] = true
|
||||||
|
end
|
||||||
|
for k, v in pairs( tbl ) do
|
||||||
|
if not done[ k ] then
|
||||||
|
table.insert( result,
|
||||||
|
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "{" .. table.concat( result, "," ) .. "}"
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Dummy 'builder': simply checks the date of a file
|
||||||
|
|
||||||
|
local _fbuilder = {}
|
||||||
|
|
||||||
|
_fbuilder.new = function( target, dep )
|
||||||
|
local self = {}
|
||||||
|
setmetatable( self, { __index = _fbuilder } )
|
||||||
|
self.target = target
|
||||||
|
self.dep = dep
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
_fbuilder.build = function( self )
|
||||||
|
-- Doesn't build anything but returns 'true' if the dependency is newer than
|
||||||
|
-- the target
|
||||||
|
if is_phony( self.target ) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return get_ftime( self.dep ) > get_ftime( self.target )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_fbuilder.target_name = function( self )
|
||||||
|
return get_target_name( self.dep )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Object type
|
||||||
|
_fbuilder.__type = function()
|
||||||
|
return "_fbuilder"
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Target object
|
||||||
|
|
||||||
|
local _target = {}
|
||||||
|
|
||||||
|
_target.new = function( target, dep, command, builder, ttype )
|
||||||
|
local self = {}
|
||||||
|
setmetatable( self, { __index = _target } )
|
||||||
|
self.target = target
|
||||||
|
self.command = command
|
||||||
|
self.builder = builder
|
||||||
|
builder:register_target( target, self )
|
||||||
|
self:set_dependencies( dep )
|
||||||
|
self.dep = self:_build_dependencies( self.origdep )
|
||||||
|
self.dont_clean = false
|
||||||
|
self.can_substitute_cmdline = false
|
||||||
|
self._force_rebuild = #self.dep == 0
|
||||||
|
builder.runlist[ target ] = false
|
||||||
|
self:set_type( ttype )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set dependencies as a string; actual dependencies are computed by _build_dependencies
|
||||||
|
-- (below) when 'build' is called
|
||||||
|
_target.set_dependencies = function( self, dep )
|
||||||
|
self.origdep = dep
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the target type
|
||||||
|
-- This is only for displaying actions
|
||||||
|
_target.set_type = function( self, ttype )
|
||||||
|
local atable = { comp = { "[COMPILE]", 'blue' } , dep = { "[DEPENDS]", 'magenta' }, link = { "[LINK]", 'yellow' }, asm = { "[ASM]", 'white' } }
|
||||||
|
local tdata = atable[ ttype ]
|
||||||
|
if not tdata then
|
||||||
|
self.dispstr = is_phony( self.target ) and "[PHONY]" or "[TARGET]"
|
||||||
|
self.dispcol = 'green'
|
||||||
|
else
|
||||||
|
self.dispstr = tdata[ 1 ]
|
||||||
|
self.dispcol = tdata[ 2 ]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set dependencies
|
||||||
|
-- This uses a proxy table and returns string deps dynamically according
|
||||||
|
-- to the targets currently registered in the builder
|
||||||
|
_target._build_dependencies = function( self, dep )
|
||||||
|
-- Step 1: start with an array
|
||||||
|
if type( dep ) == "string" then dep = utils.string_to_table( dep ) end
|
||||||
|
-- Step 2: linearize "dep" array keeping targets
|
||||||
|
local filter = function( e )
|
||||||
|
local t = exttype( e )
|
||||||
|
return t ~= "_ftarget" and t ~= "_target"
|
||||||
|
end
|
||||||
|
dep = utils.linearize_array( dep, filter )
|
||||||
|
-- Step 3: strings are turned into _fbuilder objects if not found as targets;
|
||||||
|
-- otherwise the corresponding target object is used
|
||||||
|
for i = 1, #dep do
|
||||||
|
if type( dep[ i ] ) == 'string' then
|
||||||
|
local t = self.builder:get_registered_target( dep[ i ] )
|
||||||
|
dep[ i ] = t or _fbuilder.new( self.target, dep[ i ] )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return dep
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set pre-build function
|
||||||
|
_target.set_pre_build_function = function( self, f )
|
||||||
|
self._pre_build_function = f
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set post-build function
|
||||||
|
_target.set_post_build_function = function( self, f )
|
||||||
|
self._post_build_function = f
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Force rebuild
|
||||||
|
_target.force_rebuild = function( self, flag )
|
||||||
|
self._force_rebuild = flag
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set additional arguments to send to the builder function if it is a callable
|
||||||
|
_target.set_target_args = function( self, args )
|
||||||
|
self._target_args = args
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to execute in clean mode
|
||||||
|
_target._cleaner = function( target, deps, tobj, disp_mode )
|
||||||
|
-- Clean the main target if it is not a phony target
|
||||||
|
local dprint = function( ... )
|
||||||
|
if disp_mode ~= "minimal" then print( ... ) end
|
||||||
|
end
|
||||||
|
if not is_phony( target ) then
|
||||||
|
if tobj.dont_clean then
|
||||||
|
dprint( sf( "[builder] Target '%s' will not be deleted", target ) )
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if disp_mode ~= "minimal" then io.write( sf( "[builder] Removing %s ... ", target ) ) end
|
||||||
|
if os.remove( target ) then dprint "done." else dprint "failed!" end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build the given target
|
||||||
|
_target.build = function( self )
|
||||||
|
if self.builder.runlist[ self.target ] then return end
|
||||||
|
local docmd = self:target_name() and lfs.attributes( self:target_name(), "mode" ) ~= "file"
|
||||||
|
docmd = docmd or self.builder.global_force_rebuild
|
||||||
|
local initdocmd = docmd
|
||||||
|
self.dep = self:_build_dependencies( self.origdep )
|
||||||
|
local depends, dep, previnit = '', self.dep, self.origdep
|
||||||
|
-- Iterate through all dependencies, execute each one in turn
|
||||||
|
local deprunner = function()
|
||||||
|
for i = 1, #dep do
|
||||||
|
local res = dep[ i ]:build()
|
||||||
|
docmd = docmd or res
|
||||||
|
local t = dep[ i ]:target_name()
|
||||||
|
if exttype( dep[ i ] ) == "_target" and t and not is_phony( self.target ) then
|
||||||
|
docmd = docmd or get_ftime( t ) > get_ftime( self.target )
|
||||||
|
end
|
||||||
|
if t then depends = depends .. t .. " " end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
deprunner()
|
||||||
|
-- Execute the preb-build function if needed
|
||||||
|
if self._pre_build_function then self._pre_build_function( self, docmd ) end
|
||||||
|
-- If the dependencies changed as a result of running the pre-build function
|
||||||
|
-- run through them again
|
||||||
|
if previnit ~= self.origdep then
|
||||||
|
self.dep = self:_build_dependencies( self.origdep )
|
||||||
|
depends, dep, docmd = '', self.dep, initdocmd
|
||||||
|
deprunner()
|
||||||
|
end
|
||||||
|
-- If at least one dependency is new rebuild the target
|
||||||
|
docmd = docmd or self._force_rebuild or self.builder.clean_mode
|
||||||
|
local keep_flag = true
|
||||||
|
if docmd and self.command then
|
||||||
|
if self.builder.disp_mode ~= 'all' and self.builder.disp_mode ~= "minimal" and not self.builder.clean_mode then
|
||||||
|
io.write( utils.col_funcs[ self.dispcol ]( self.dispstr ) .. " " )
|
||||||
|
end
|
||||||
|
local cmd, code = self.command
|
||||||
|
if self.builder.clean_mode then cmd = _target._cleaner end
|
||||||
|
if type( cmd ) == 'string' then
|
||||||
|
cmd = expand_key( cmd, "TARGET", self.target )
|
||||||
|
cmd = expand_key( cmd, "DEPENDS", depends )
|
||||||
|
cmd = expand_key( cmd, "FIRST", dep[ 1 ]:target_name() )
|
||||||
|
if self.builder.disp_mode == 'all' then
|
||||||
|
print( cmd )
|
||||||
|
elseif self.builder.disp_mode ~= "minimal" then
|
||||||
|
print( self.target )
|
||||||
|
end
|
||||||
|
code = self:execute( cmd )
|
||||||
|
else
|
||||||
|
if not self.builder.clean_mode and self.builder.disp_mode ~= "all" and self.builder.disp_mode ~= "minimal" then
|
||||||
|
print( self.target )
|
||||||
|
end
|
||||||
|
code = cmd( self.target, self.dep, self.builder.clean_mode and self or self._target_args, self.builder.disp_mode )
|
||||||
|
if code == 1 then -- this means "mark target as 'not executed'"
|
||||||
|
keep_flag = false
|
||||||
|
code = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if code ~= 0 then
|
||||||
|
print( utils.col_red( "[builder] Error building target" ) )
|
||||||
|
if self.builder.disp_mode ~= 'all' and type( cmd ) == "string" then
|
||||||
|
print( utils.col_red( "[builder] Last executed command was: " ) )
|
||||||
|
print( cmd )
|
||||||
|
end
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Execute the post-build function if needed
|
||||||
|
if self._post_build_function then self._post_build_function( self, docmd ) end
|
||||||
|
-- Marked target as "already ran" so it won't run again
|
||||||
|
self.builder.runlist[ self.target ] = true
|
||||||
|
return docmd and keep_flag
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the actual target name (taking into account phony targets)
|
||||||
|
_target.target_name = function( self )
|
||||||
|
return get_target_name( self.target )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Restrict cleaning this target
|
||||||
|
_target.prevent_clean = function( self, flag )
|
||||||
|
self.dont_clean = flag
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Object type
|
||||||
|
_target.__type = function()
|
||||||
|
return "_target"
|
||||||
|
end
|
||||||
|
|
||||||
|
_target.execute = function( self, cmd )
|
||||||
|
local code
|
||||||
|
if utils.is_windows() and #cmd > 8190 and self.can_substitute_cmdline then
|
||||||
|
-- Avoid cmd's maximum command line length limitation
|
||||||
|
local t = cmd:find( " " )
|
||||||
|
f = io.open( "tmpcmdline", "w" )
|
||||||
|
local rest = cmd:sub( t + 1 )
|
||||||
|
f:write( ( rest:gsub( "\\", "/" ) ) )
|
||||||
|
f:close()
|
||||||
|
cmd = cmd:sub( 1, t - 1 ) .. " @tmpcmdline"
|
||||||
|
end
|
||||||
|
local code = os.execute( cmd )
|
||||||
|
os.remove( "tmpcmdline" )
|
||||||
|
return code
|
||||||
|
end
|
||||||
|
|
||||||
|
_target.set_substitute_cmdline = function( self, flag )
|
||||||
|
self.can_substitute_cmdline = flag
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Builder public interface
|
||||||
|
|
||||||
|
builder = { KEEP_DIR = 0, BUILD_DIR_LINEARIZED = 1 }
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Initialization and option handling
|
||||||
|
|
||||||
|
-- Create a new builder object with the output in 'build_dir' and with the
|
||||||
|
-- specified compile, dependencies and link command
|
||||||
|
builder.new = function( build_dir )
|
||||||
|
self = {}
|
||||||
|
setmetatable( self, { __index = builder } )
|
||||||
|
self.build_dir = build_dir or ".build"
|
||||||
|
self.exe_extension = utils.is_windows() and "exe" or ""
|
||||||
|
self.clean_mode = false
|
||||||
|
self.opts = utils.options_handler()
|
||||||
|
self.args = {}
|
||||||
|
self.user_args = {}
|
||||||
|
self.build_mode = self.KEEP_DIR
|
||||||
|
self.targets = {}
|
||||||
|
self.targetargs = {}
|
||||||
|
self._tlist = {}
|
||||||
|
self.runlist = {}
|
||||||
|
self.disp_mode = 'all'
|
||||||
|
self.cmdline_macros = {}
|
||||||
|
self.c_targets = {}
|
||||||
|
self.preprocess_mode = false
|
||||||
|
self.asm_mode = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: create the build output directory
|
||||||
|
builder._create_build_dir = function( self )
|
||||||
|
if self.build_dir_created then return end
|
||||||
|
if self.build_mode ~= self.KEEP_DIR then
|
||||||
|
-- Create builds directory if needed
|
||||||
|
local mode = lfs.attributes( self.build_dir, "mode" )
|
||||||
|
if not mode or mode ~= "directory" then
|
||||||
|
if not utils.full_mkdir( self.build_dir ) then
|
||||||
|
print( "[builder] Unable to create directory " .. self.build_dir )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.build_dir_created = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add an options to the builder
|
||||||
|
builder.add_option = function( self, name, help, default, data )
|
||||||
|
self.opts:add_option( name, help, default, data )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize builder from the given command line
|
||||||
|
builder.init = function( self, args )
|
||||||
|
-- Add the default options
|
||||||
|
local opts = self.opts
|
||||||
|
opts:add_option( "build_mode", 'choose location of the object files', self.KEEP_DIR,
|
||||||
|
{ keep_dir = self.KEEP_DIR, build_dir_linearized = self.BUILD_DIR_LINEARIZED } )
|
||||||
|
opts:add_option( "build_dir", 'choose build directory', self.build_dir )
|
||||||
|
opts:add_option( "disp_mode", 'set builder display mode', 'summary', { 'all', 'summary', 'minimal' } )
|
||||||
|
-- Apply default values to all options
|
||||||
|
for i = 1, opts:get_num_opts() do
|
||||||
|
local o = opts:get_option( i )
|
||||||
|
self.args[ o.name:upper() ] = o.default
|
||||||
|
end
|
||||||
|
-- Read and interpret command line
|
||||||
|
for i = 1, #args do
|
||||||
|
local a = args[ i ]
|
||||||
|
if a:upper() == "-C" then -- clean option (-c)
|
||||||
|
self.clean_mode = true
|
||||||
|
elseif a:upper() == '-H' then -- help option (-h)
|
||||||
|
self:_show_help()
|
||||||
|
os.exit( 1 )
|
||||||
|
elseif a:upper() == "-E" then -- preprocess
|
||||||
|
self.preprocess_mode = true
|
||||||
|
elseif a:upper() == "-S" then -- generate assembler
|
||||||
|
self.asm_mode = true
|
||||||
|
elseif a:find( '-D' ) == 1 and #a > 2 then -- this is a macro definition that will be auomatically added to the compiler flags
|
||||||
|
table.insert( self.cmdline_macros, a:sub( 3 ) )
|
||||||
|
elseif a:find( '=' ) then -- builder argument (key=value)
|
||||||
|
local k, v = opts:handle_arg( a )
|
||||||
|
if not k then
|
||||||
|
self:_show_help()
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
self.args[ k:upper() ] = v
|
||||||
|
self.user_args[ k:upper() ] = true
|
||||||
|
else -- this must be the target name / target arguments
|
||||||
|
if self.targetname == nil then
|
||||||
|
self.targetname = a
|
||||||
|
else
|
||||||
|
table.insert( self.targetargs, a )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Read back the default options
|
||||||
|
self.build_mode = self.args.BUILD_MODE
|
||||||
|
self.build_dir = self.args.BUILD_DIR
|
||||||
|
self.disp_mode = self.args.DISP_MODE
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the value of the option with the given name
|
||||||
|
builder.get_option = function( self, optname )
|
||||||
|
return self.args[ optname:upper() ]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns true if the given option was specified by the user on the command line, false otherwise
|
||||||
|
builder.is_user_option = function( self, optname )
|
||||||
|
return self.user_args[ optname:upper() ]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show builder help
|
||||||
|
builder._show_help = function( self )
|
||||||
|
print( "[builder] Valid options:" )
|
||||||
|
print( " -h: help (this text)" )
|
||||||
|
print( " -c: clean target" )
|
||||||
|
print( " -E: generate preprocessed output for single file targets" )
|
||||||
|
print( " -S: generate assembler output for single file targets" )
|
||||||
|
self.opts:show_help()
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Builder configuration
|
||||||
|
|
||||||
|
-- Set the compile command
|
||||||
|
builder.set_compile_cmd = function( self, cmd )
|
||||||
|
self.comp_cmd = cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the link command
|
||||||
|
builder.set_link_cmd = function( self, cmd )
|
||||||
|
self.link_cmd = cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the assembler command
|
||||||
|
builder.set_asm_cmd = function( self, cmd )
|
||||||
|
self._asm_cmd = cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set (actually force) the object file extension
|
||||||
|
builder.set_object_extension = function( self, ext )
|
||||||
|
self.obj_extension = ext
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set (actually force) the executable file extension
|
||||||
|
builder.set_exe_extension = function( self, ext )
|
||||||
|
self.exe_extension = ext
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the clean mode
|
||||||
|
builder.set_clean_mode = function( self, isclean )
|
||||||
|
self.clean_mode = isclean
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sets the build mode
|
||||||
|
builder.set_build_mode = function( self, mode )
|
||||||
|
self.build_mode = mode
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the build directory
|
||||||
|
builder.set_build_dir = function( self, dir )
|
||||||
|
if self.build_dir_created then
|
||||||
|
print "[builder] Error: build directory already created"
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
self.build_dir = dir
|
||||||
|
self:_create_build_dir()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the current build directory
|
||||||
|
builder.get_build_dir = function( self )
|
||||||
|
return self.build_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the target arguments
|
||||||
|
builder.get_target_args = function( self )
|
||||||
|
return self.targetargs
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set a specific dependency generation command for the assembler
|
||||||
|
-- Pass 'false' to skip dependency generation for assembler files
|
||||||
|
builder.set_asm_dep_cmd = function( self, asm_dep_cmd )
|
||||||
|
self.asm_dep_cmd = asm_dep_cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set a specific dependency generation command for the compiler
|
||||||
|
-- Pass 'false' to skip dependency generation for C files
|
||||||
|
builder.set_c_dep_cmd = function( self, c_dep_cmd )
|
||||||
|
self.c_dep_cmd = c_dep_cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Save the builder configuration for a given component to a string
|
||||||
|
builder._config_to_string = function( self, what )
|
||||||
|
local ctable = {}
|
||||||
|
local state_fields
|
||||||
|
if what == 'comp' then
|
||||||
|
state_fields = { 'comp_cmd', '_asm_cmd', 'c_dep_cmd', 'asm_dep_cmd', 'obj_extension' }
|
||||||
|
elseif what == 'link' then
|
||||||
|
state_fields = { 'link_cmd' }
|
||||||
|
else
|
||||||
|
print( sf( "Invalid argument '%s' to _config_to_string", what ) )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
utils.foreach( state_fields, function( k, v ) ctable[ v ] = self[ v ] end )
|
||||||
|
return table.tostring( ctable )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check the configuration of the given component against the previous one
|
||||||
|
-- Return true if the configuration has changed
|
||||||
|
builder._compare_config = function( self, what )
|
||||||
|
local res = false
|
||||||
|
local crtstate = self:_config_to_string( what )
|
||||||
|
if not self.clean_mode then
|
||||||
|
local fconf = io.open( self.build_dir .. utils.dir_sep .. ".builddata." .. what, "rb" )
|
||||||
|
if fconf then
|
||||||
|
local oldstate = fconf:read( "*a" )
|
||||||
|
fconf:close()
|
||||||
|
if oldstate:lower() ~= crtstate:lower() then res = true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Write state to build dir
|
||||||
|
fconf = io.open( self.build_dir .. utils.dir_sep .. ".builddata." .. what, "wb" )
|
||||||
|
if fconf then
|
||||||
|
fconf:write( self:_config_to_string( what ) )
|
||||||
|
fconf:close()
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sets the way commands are displayed
|
||||||
|
builder.set_disp_mode = function( self, mode )
|
||||||
|
mode = mode:lower()
|
||||||
|
if mode ~= 'all' and mode ~= 'summary' and mode ~= "minimal" then
|
||||||
|
print( sf( "[builder] Invalid display mode '%s'", mode ) )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
self.disp_mode = mode
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Command line builders
|
||||||
|
|
||||||
|
-- Internal helper
|
||||||
|
builder._generic_cmd = function( self, args )
|
||||||
|
local compcmd = args.compiler or "gcc"
|
||||||
|
compcmd = compcmd .. " "
|
||||||
|
local flags = type( args.flags ) == 'table' and table_to_string( utils.linearize_array( args.flags ) ) or args.flags
|
||||||
|
local defines = type( args.defines ) == 'table' and table_to_string( utils.linearize_array( args.defines ) ) or args.defines
|
||||||
|
local includes = type( args.includes ) == 'table' and table_to_string( utils.linearize_array( args.includes ) ) or args.includes
|
||||||
|
local comptype = table_to_string( args.comptype ) or "-c"
|
||||||
|
compcmd = compcmd .. utils.prepend_string( defines, "-D" )
|
||||||
|
compcmd = compcmd .. utils.prepend_string( includes, "-I" )
|
||||||
|
return compcmd .. flags .. " " .. comptype .. " -o $(TARGET) $(FIRST)"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a compile command based on the specified args
|
||||||
|
builder.compile_cmd = function( self, args )
|
||||||
|
args.defines = { args.defines, self.cmdline_macros }
|
||||||
|
if self.preprocess_mode then
|
||||||
|
args.comptype = "-E"
|
||||||
|
elseif self.asm_mode then
|
||||||
|
args.comptype = "-S"
|
||||||
|
else
|
||||||
|
args.comptype = "-c"
|
||||||
|
end
|
||||||
|
return self:_generic_cmd( args )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return an assembler command based on the specified args
|
||||||
|
builder.asm_cmd = function( self, args )
|
||||||
|
args.defines = { args.defines, self.cmdline_macros }
|
||||||
|
args.compiler = args.assembler
|
||||||
|
args.comptype = self.preprocess_mode and "-E" or "-c"
|
||||||
|
return self:_generic_cmd( args )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a link command based on the specified args
|
||||||
|
builder.link_cmd = function( self, args )
|
||||||
|
local flags = type( args.flags ) == 'table' and table_to_string( utils.linearize_array( args.flags ) ) or args.flags
|
||||||
|
local libraries = type( args.libraries ) == 'table' and table_to_string( utils.linearize_array( args.libraries ) ) or args.libraries
|
||||||
|
local linkcmd = args.linker or "gcc"
|
||||||
|
linkcmd = linkcmd .. " " .. flags .. " -o $(TARGET) $(DEPENDS)"
|
||||||
|
linkcmd = linkcmd .. " " .. utils.prepend_string( libraries, "-l" )
|
||||||
|
return linkcmd
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Target handling
|
||||||
|
|
||||||
|
-- Create a return a new C to object target
|
||||||
|
builder.c_target = function( self, target, deps, comp_cmd )
|
||||||
|
return _target.new( target, deps, comp_cmd or self.comp_cmd, self, 'comp' )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a return a new ASM to object target
|
||||||
|
builder.asm_target = function( self, target, deps, asm_cmd )
|
||||||
|
return _target.new( target, deps, asm_cmd or self._asm_cmd, self, 'asm' )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the name of a dependency file name corresponding to a C source
|
||||||
|
builder.get_dep_filename = function( self, srcname )
|
||||||
|
return utils.replace_extension( self.build_dir .. utils.dir_sep .. linearize_fname( srcname ), "d" )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a return a new C dependency target
|
||||||
|
builder.dep_target = function( self, dep, depdeps, dep_cmd )
|
||||||
|
local depname = self:get_dep_filename( dep )
|
||||||
|
return _target.new( depname, depdeps, dep_cmd, self, 'dep' )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create and return a new link target
|
||||||
|
builder.link_target = function( self, out, dep, link_cmd )
|
||||||
|
local path, ext = utils.split_ext( out )
|
||||||
|
if not ext and self.exe_extension and #self.exe_extension > 0 then
|
||||||
|
out = out .. self.exe_extension
|
||||||
|
end
|
||||||
|
local t = _target.new( out, dep, link_cmd or self.link_cmd, self, 'link' )
|
||||||
|
if self:_compare_config( 'link' ) then t:force_rebuild( true ) end
|
||||||
|
t:set_substitute_cmdline( true )
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create and return a new generic target
|
||||||
|
builder.target = function( self, dest_target, deps, cmd )
|
||||||
|
return _target.new( dest_target, deps, cmd, self )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register a target (called from _target.new)
|
||||||
|
builder.register_target = function( self, name, obj )
|
||||||
|
self._tlist[ name:gsub( "\\", "/" ) ] = obj
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a registered target (nil if not found)
|
||||||
|
builder.get_registered_target = function( self, name )
|
||||||
|
return self._tlist[ name:gsub( "\\", "/" ) ]
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
-- Actual building functions
|
||||||
|
|
||||||
|
-- Return the object name corresponding to a source file name
|
||||||
|
builder.obj_name = function( self, name, ext )
|
||||||
|
local r = ext or self.obj_extension
|
||||||
|
if not r then
|
||||||
|
r = utils.is_windows() and "obj" or "o"
|
||||||
|
end
|
||||||
|
local objname = utils.replace_extension( name, r )
|
||||||
|
-- KEEP_DIR: object file in the same directory as source file
|
||||||
|
-- BUILD_DIR_LINEARIZED: object file in the build directory, linearized filename
|
||||||
|
if self.build_mode == self.KEEP_DIR then
|
||||||
|
return objname
|
||||||
|
elseif self.build_mode == self.BUILD_DIR_LINEARIZED then
|
||||||
|
return self.build_dir .. utils.dir_sep .. linearize_fname( objname )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read and interpret dependencies for each file specified in "ftable"
|
||||||
|
-- "ftable" is either a space-separated string with all the source files or an array
|
||||||
|
builder.read_depends = function( self, ftable )
|
||||||
|
if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end
|
||||||
|
-- Read dependency data
|
||||||
|
local dtable = {}
|
||||||
|
for i = 1, #ftable do
|
||||||
|
local f = io.open( self:get_dep_filename( ftable[ i ] ), "rb" )
|
||||||
|
local lines = ftable[ i ]
|
||||||
|
if f then
|
||||||
|
lines = f:read( "*a" )
|
||||||
|
f:close()
|
||||||
|
lines = lines:gsub( "\n", " " ):gsub( "\\%s+", " " ):gsub( "%s+", " " ):gsub( "^.-: (.*)", "%1" )
|
||||||
|
end
|
||||||
|
dtable[ ftable[ i ] ] = lines
|
||||||
|
end
|
||||||
|
return dtable
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create and return compile targets for the given sources
|
||||||
|
builder.create_compile_targets = function( self, ftable, res )
|
||||||
|
if type( ftable ) == 'string' then ftable = utils.string_to_table( ftable ) end
|
||||||
|
res = res or {}
|
||||||
|
ccmd, oname = "-c", "o"
|
||||||
|
if self.preprocess_mode then
|
||||||
|
ccmd, oname = '-E', "pre"
|
||||||
|
elseif self.asm_mode then
|
||||||
|
ccmd, oname = '-S', 's'
|
||||||
|
end
|
||||||
|
-- Build dependencies for all targets
|
||||||
|
for i = 1, #ftable do
|
||||||
|
local isasm = ftable[ i ]:find( "%.c$" ) == nil
|
||||||
|
-- Skip assembler targets if 'asm_dep_cmd' is set to 'false'
|
||||||
|
-- Skip C targets if 'c_dep_cmd' is set to 'false'
|
||||||
|
local skip = isasm and self.asm_dep_cmd == false
|
||||||
|
skip = skip or ( not isasm and self.c_dep_cmd == false )
|
||||||
|
local deps = self:get_dep_filename( ftable[ i ] )
|
||||||
|
local target
|
||||||
|
if not isasm then
|
||||||
|
local depcmd = skip and self.comp_cmd or ( self.c_dep_cmd or self.comp_cmd:gsub( ccmd .. " ", sf( ccmd .. " -MD -MF %s ", deps ) ) )
|
||||||
|
target = self:c_target( self:obj_name( ftable[ i ], oname ), { self:get_registered_target( deps ) or ftable[ i ] }, depcmd )
|
||||||
|
else
|
||||||
|
local depcmd = skip and self._asm_cmd or ( self.asm_dep_cmd or self._asm_cmd:gsub( ccmd .. " ", sf( ccmd .. " -MD -MF %s ", deps ) ) )
|
||||||
|
target = self:asm_target( self:obj_name( ftable[ i ], oname ), { self:get_registered_target( deps ) or ftable[ i ] }, depcmd )
|
||||||
|
end
|
||||||
|
-- Pre build step: replace dependencies with the ones from the compiler generated dependency file
|
||||||
|
local dprint = function( ... ) if self.disp_mode ~= "minimal" then print( ... ) end end
|
||||||
|
if not skip then
|
||||||
|
target:set_pre_build_function( function( t, _ )
|
||||||
|
if not self.clean_mode then
|
||||||
|
local fres = self:read_depends( ftable[ i ] )
|
||||||
|
local fdeps = fres[ ftable[ i ] ]
|
||||||
|
if #fdeps:gsub( "%s+", "" ) == 0 then fdeps = ftable[ i ] end
|
||||||
|
t:set_dependencies( fdeps )
|
||||||
|
else
|
||||||
|
if self.disp_mode ~= "minimal" then io.write( sf( "[builder] Removing %s ... ", deps ) ) end
|
||||||
|
if os.remove( deps ) then dprint "done." else dprint "failed!" end
|
||||||
|
end
|
||||||
|
end )
|
||||||
|
end
|
||||||
|
target.srcname = ftable[ i ]
|
||||||
|
-- TODO: check clean mode?
|
||||||
|
if not isasm then self.c_targets[ #self.c_targets + 1 ] = target end
|
||||||
|
table.insert( res, target )
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add a target to the list of builder targets
|
||||||
|
builder.add_target = function( self, target, help, alias )
|
||||||
|
self.targets[ target.target ] = { target = target, help = help }
|
||||||
|
alias = alias or {}
|
||||||
|
for _, v in ipairs( alias ) do
|
||||||
|
self.targets[ v ] = { target = target, help = help }
|
||||||
|
end
|
||||||
|
return target
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Make a target the default one
|
||||||
|
builder.default = function( self, target )
|
||||||
|
self.deftarget = target.target
|
||||||
|
self.targets.default = { target = target, help = "default target" }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build everything
|
||||||
|
builder.build = function( self, target )
|
||||||
|
local t = self.targetname or self.deftarget
|
||||||
|
if not t then
|
||||||
|
print( utils.col_red( "[builder] Error: build target not specified" ) )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
local trg
|
||||||
|
-- Look for single targets (C source files)
|
||||||
|
for _, ct in pairs( self.c_targets ) do
|
||||||
|
if ct.srcname == t then
|
||||||
|
trg = ct
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not trg then
|
||||||
|
if not self.targets[ t ] then
|
||||||
|
print( sf( "[builder] Error: target '%s' not found", t ) )
|
||||||
|
print( "Available targets: " )
|
||||||
|
print( " all source files" )
|
||||||
|
for k, v in pairs( self.targets ) do
|
||||||
|
if not is_phony( k ) then
|
||||||
|
print( sf( " %s - %s", k, v.help or "(no help available)" ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.deftarget and not is_phony( self.deftarget ) then
|
||||||
|
print( sf( "Default target is '%s'", self.deftarget ) )
|
||||||
|
end
|
||||||
|
os.exit( 1 )
|
||||||
|
else
|
||||||
|
if self.preprocess_mode or self.asm_mode then
|
||||||
|
print( "[builder] Error: preprocess (-E) or asm (-S) works only with single file targets." )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
trg = self.targets[ t ].target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:_create_build_dir()
|
||||||
|
-- At this point check if we have a change in the state that would require a rebuild
|
||||||
|
if self:_compare_config( 'comp' ) then
|
||||||
|
print( utils.col_yellow( "[builder] Forcing rebuild due to configuration change." ) )
|
||||||
|
self.global_force_rebuild = true
|
||||||
|
else
|
||||||
|
self.global_force_rebuild = false
|
||||||
|
end
|
||||||
|
-- Do the actual build
|
||||||
|
local res = trg:build()
|
||||||
|
if not res then print( utils.col_yellow( sf( '[builder] %s: up to date', t ) ) ) end
|
||||||
|
if self.clean_mode then
|
||||||
|
os.remove( self.build_dir .. utils.dir_sep .. ".builddata.comp" )
|
||||||
|
os.remove( self.build_dir .. utils.dir_sep .. ".builddata.link" )
|
||||||
|
end
|
||||||
|
print( utils.col_yellow( "[builder] Done building target." ) )
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create dependencies, create object files, link final object
|
||||||
|
builder.make_exe_target = function( self, target, file_list )
|
||||||
|
local odeps = self:create_compile_targets( file_list )
|
||||||
|
local exetarget = self:link_target( target, odeps )
|
||||||
|
self:default( self:add_target( exetarget ) )
|
||||||
|
return exetarget
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Other exported functions
|
||||||
|
|
||||||
|
function new_builder( build_dir )
|
||||||
|
return builder.new( build_dir )
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
local args = { ... }
|
||||||
|
local b = require "tools.build"
|
||||||
|
local builder = b.new_builder( ".build/cross-lua" )
|
||||||
|
local utils = b.utils
|
||||||
|
local sf = string.format
|
||||||
|
|
||||||
|
if not (_VERSION == "Lua 5.1" and pcall(require,"lfs")) then
|
||||||
|
print [[
|
||||||
|
|
||||||
|
cross_lua.lua must be run within Lua 5.1 and it requires the Lua Filesystem to be installed.
|
||||||
|
On most *nix distrubitions youwill find a packages lua-5.1 and lua-filesystem, or
|
||||||
|
alternalively you can install lua-rocks and use the Rocks package manager to install lfs.
|
||||||
|
]]
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
builder:init( args )
|
||||||
|
builder:set_build_mode( builder.BUILD_DIR_LINEARIZED )
|
||||||
|
local output = 'luac.cross'
|
||||||
|
local cdefs = '-DLUA_CROSS_COMPILER'
|
||||||
|
|
||||||
|
-- Lua source files and include path
|
||||||
|
local lua_files = [[
|
||||||
|
lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ldo.c ldump.c
|
||||||
|
lfunc.c lgc.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c
|
||||||
|
lparser.c lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c
|
||||||
|
ltm.c lundump.c lvm.c lzio.c
|
||||||
|
luac_cross/luac.c luac_cross/loslib.c luac_cross/print.c
|
||||||
|
../modules/linit.c
|
||||||
|
../libc/c_stdlib.c
|
||||||
|
]]
|
||||||
|
lua_files = lua_files:gsub( "\n" , "" )
|
||||||
|
local lua_full_files = utils.prepend_path( lua_files, "app/lua" )
|
||||||
|
local local_include = "-Iapp/include -Iinclude -Iapp/lua"
|
||||||
|
|
||||||
|
-- Compiler/linker options
|
||||||
|
builder:set_compile_cmd( sf( "gcc -O2 %s -Wall %s -c $(FIRST) -o $(TARGET)", local_include, cdefs ) )
|
||||||
|
builder:set_link_cmd( "gcc -o $(TARGET) $(DEPENDS) -lm" )
|
||||||
|
|
||||||
|
-- Build everything
|
||||||
|
builder:make_exe_target( output, lua_full_files )
|
||||||
|
builder:build()
|
||||||
|
|
|
@ -0,0 +1,425 @@
|
||||||
|
-- Generic utility functions
|
||||||
|
|
||||||
|
module( ..., package.seeall )
|
||||||
|
|
||||||
|
local lfs = require "lfs"
|
||||||
|
local sf = string.format
|
||||||
|
-- Taken from Lake
|
||||||
|
dir_sep = package.config:sub( 1, 1 )
|
||||||
|
is_os_windows = dir_sep == '\\'
|
||||||
|
|
||||||
|
-- Converts a string with items separated by 'sep' into a table
|
||||||
|
string_to_table = function( s, sep )
|
||||||
|
if type( s ) ~= "string" then return end
|
||||||
|
sep = sep or ' '
|
||||||
|
if s:sub( -1, -1 ) ~= sep then s = s .. sep end
|
||||||
|
s = s:gsub( sf( "^%s*", sep ), "" )
|
||||||
|
local t = {}
|
||||||
|
local fmt = sf( "(.-)%s+", sep )
|
||||||
|
for w in s:gmatch( fmt ) do table.insert( t, w ) end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Split a file name into 'path part' and 'extension part'
|
||||||
|
split_ext = function( s )
|
||||||
|
local pos
|
||||||
|
for i = #s, 1, -1 do
|
||||||
|
if s:sub( i, i ) == "." then
|
||||||
|
pos = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not pos or s:find( dir_sep, pos + 1 ) then return s end
|
||||||
|
return s:sub( 1, pos - 1 ), s:sub( pos )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Replace the extension of a given file name
|
||||||
|
replace_extension = function( s, newext )
|
||||||
|
local p, e = split_ext( s )
|
||||||
|
if e then
|
||||||
|
if newext and #newext > 0 then
|
||||||
|
s = p .. "." .. newext
|
||||||
|
else
|
||||||
|
s = p
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return 'true' if building from Windows, false otherwise
|
||||||
|
is_windows = function()
|
||||||
|
return is_os_windows
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prepend each component of a 'pat'-separated string with 'prefix'
|
||||||
|
prepend_string = function( s, prefix, pat )
|
||||||
|
if not s or #s == 0 then return "" end
|
||||||
|
pat = pat or ' '
|
||||||
|
local res = ''
|
||||||
|
local st = string_to_table( s, pat )
|
||||||
|
foreach( st, function( k, v ) res = res .. prefix .. v .. " " end )
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Like above, but consider 'prefix' a path
|
||||||
|
prepend_path = function( s, prefix, pat )
|
||||||
|
return prepend_string( s, prefix .. dir_sep, pat )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- full mkdir: create all the paths needed for a multipath
|
||||||
|
full_mkdir = function( path )
|
||||||
|
local ptables = string_to_table( path, dir_sep )
|
||||||
|
local p, res = ''
|
||||||
|
for i = 1, #ptables do
|
||||||
|
p = ( i ~= 1 and p .. dir_sep or p ) .. ptables[ i ]
|
||||||
|
res = lfs.mkdir( p )
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Concatenate the given paths to form a complete path
|
||||||
|
concat_path = function( paths )
|
||||||
|
return table.concat( paths, dir_sep )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return true if the given array contains the given element, false otherwise
|
||||||
|
array_element_index = function( arr, element )
|
||||||
|
for i = 1, #arr do
|
||||||
|
if arr[ i ] == element then return i end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Linearize an array with (possibly) embedded arrays into a simple array
|
||||||
|
_linearize_array = function( arr, res, filter )
|
||||||
|
if type( arr ) ~= "table" then return end
|
||||||
|
for i = 1, #arr do
|
||||||
|
local e = arr[ i ]
|
||||||
|
if type( e ) == 'table' and filter( e ) then
|
||||||
|
_linearize_array( e, res, filter )
|
||||||
|
else
|
||||||
|
table.insert( res, e )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
linearize_array = function( arr, filter )
|
||||||
|
local res = {}
|
||||||
|
filter = filter or function( v ) return true end
|
||||||
|
_linearize_array( arr, res, filter )
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return an array with the keys of a table
|
||||||
|
table_keys = function( t )
|
||||||
|
local keys = {}
|
||||||
|
foreach( t, function( k, v ) table.insert( keys, k ) end )
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return an array with the values of a table
|
||||||
|
table_values = function( t )
|
||||||
|
local vals = {}
|
||||||
|
foreach( t, function( k, v ) table.insert( vals, v ) end )
|
||||||
|
return vals
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns true if 'path' is a regular file, false otherwise
|
||||||
|
is_file = function( path )
|
||||||
|
return lfs.attributes( path, "mode" ) == "file"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns true if 'path' is a directory, false otherwise
|
||||||
|
is_dir = function( path )
|
||||||
|
return lfs.attributes( path, "mode" ) == "directory"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return a list of files in the given directory matching a given mask
|
||||||
|
get_files = function( path, mask, norec, level )
|
||||||
|
local t = ''
|
||||||
|
level = level or 0
|
||||||
|
for f in lfs.dir( path ) do
|
||||||
|
local fname = path .. dir_sep .. f
|
||||||
|
if lfs.attributes( fname, "mode" ) == "file" then
|
||||||
|
local include
|
||||||
|
if type( mask ) == "string" then
|
||||||
|
include = fname:find( mask )
|
||||||
|
else
|
||||||
|
include = mask( fname )
|
||||||
|
end
|
||||||
|
if include then t = t .. ' ' .. fname end
|
||||||
|
elseif lfs.attributes( fname, "mode" ) == "directory" and not fname:find( "%.+$" ) and not norec then
|
||||||
|
t = t .. " " .. get_files( fname, mask, norec, level + 1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return level > 0 and t or t:gsub( "^%s+", "" )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if the given command can be executed properly
|
||||||
|
check_command = function( cmd )
|
||||||
|
local res = os.execute( cmd .. " > .build.temp 2>&1" )
|
||||||
|
os.remove( ".build.temp" )
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Execute a command and capture output
|
||||||
|
-- From: http://stackoverflow.com/a/326715/105950
|
||||||
|
exec_capture = function( cmd, raw )
|
||||||
|
local f = assert(io.popen(cmd, 'r'))
|
||||||
|
local s = assert(f:read('*a'))
|
||||||
|
f:close()
|
||||||
|
if raw then return s end
|
||||||
|
s = string.gsub(s, '^%s+', '')
|
||||||
|
s = string.gsub(s, '%s+$', '')
|
||||||
|
s = string.gsub(s, '[\n\r]+', ' ')
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Execute the given command for each value in a table
|
||||||
|
foreach = function ( t, cmd )
|
||||||
|
if type( t ) ~= "table" then return end
|
||||||
|
for k, v in pairs( t ) do cmd( k, v ) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate header with the given #defines, return result as string
|
||||||
|
gen_header_string = function( name, defines )
|
||||||
|
local s = "// eLua " .. name:lower() .. " definition\n\n"
|
||||||
|
s = s .. "#ifndef __" .. name:upper() .. "_H__\n"
|
||||||
|
s = s .. "#define __" .. name:upper() .. "_H__\n\n"
|
||||||
|
|
||||||
|
for key,value in pairs(defines) do
|
||||||
|
s = s .. string.format("#define %-25s%-19s\n",key:upper(),value)
|
||||||
|
end
|
||||||
|
|
||||||
|
s = s .. "\n#endif\n"
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate header with the given #defines, save result to file
|
||||||
|
gen_header_file = function( name, defines )
|
||||||
|
local hname = concat_path{ "inc", name:lower() .. ".h" }
|
||||||
|
local h = assert( io.open( hname, "w" ) )
|
||||||
|
h:write( gen_header_string( name, defines ) )
|
||||||
|
h:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove the given elements from an array
|
||||||
|
remove_array_elements = function( arr, del )
|
||||||
|
del = istable( del ) and del or { del }
|
||||||
|
foreach( del, function( k, v )
|
||||||
|
local pos = array_element_index( arr, v )
|
||||||
|
if pos then table.remove( arr, pos ) end
|
||||||
|
end )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove a directory recusively
|
||||||
|
-- USE WITH CARE!! Doesn't do much checks :)
|
||||||
|
rmdir_rec = function ( dirname )
|
||||||
|
if lfs.attributes( dirname, "mode" ) ~= "directory" then return end
|
||||||
|
for f in lfs.dir( dirname ) do
|
||||||
|
local ename = string.format( "%s/%s", dirname, f )
|
||||||
|
local attrs = lfs.attributes( ename )
|
||||||
|
if attrs.mode == 'directory' and f ~= '.' and f ~= '..' then
|
||||||
|
rmdir_rec( ename )
|
||||||
|
elseif attrs.mode == 'file' or attrs.mode == 'named pipe' or attrs.mode == 'link' then
|
||||||
|
os.remove( ename )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lfs.rmdir( dirname )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Concatenates the second table into the first one
|
||||||
|
concat_tables = function( dst, src )
|
||||||
|
foreach( src, function( k, v ) dst[ k ] = v end )
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Color-related funtions
|
||||||
|
-- Currently disabled when running in Windows
|
||||||
|
-- (they can be enabled by setting WIN_ANSI_TERM)
|
||||||
|
|
||||||
|
local dcoltable = { 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' }
|
||||||
|
local coltable = {}
|
||||||
|
foreach( dcoltable, function( k, v ) coltable[ v ] = k - 1 end )
|
||||||
|
|
||||||
|
local _col_builder = function( col )
|
||||||
|
local _col_maker = function( s )
|
||||||
|
if is_os_windows and not os.getenv( "WIN_ANSI_TERM" ) then
|
||||||
|
return s
|
||||||
|
else
|
||||||
|
return( sf( "\027[%d;1m%s\027[m", coltable[ col ] + 30, s ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return _col_maker
|
||||||
|
end
|
||||||
|
|
||||||
|
col_funcs = {}
|
||||||
|
foreach( coltable, function( k, v )
|
||||||
|
local fname = "col_" .. k
|
||||||
|
_G[ fname ] = _col_builder( k )
|
||||||
|
col_funcs[ k ] = _G[ fname ]
|
||||||
|
end )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Option handling
|
||||||
|
|
||||||
|
local options = {}
|
||||||
|
|
||||||
|
options.new = function()
|
||||||
|
local self = {}
|
||||||
|
self.options = {}
|
||||||
|
setmetatable( self, { __index = options } )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument validator: boolean value
|
||||||
|
options._bool_validator = function( v )
|
||||||
|
if v == '0' or v:upper() == 'FALSE' then
|
||||||
|
return false
|
||||||
|
elseif v == '1' or v:upper() == 'TRUE' then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument validator: choice value
|
||||||
|
options._choice_validator = function( v, allowed )
|
||||||
|
for i = 1, #allowed do
|
||||||
|
if v:upper() == allowed[ i ]:upper() then return allowed[ i ] end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument validator: choice map (argument value maps to something)
|
||||||
|
options._choice_map_validator = function( v, allowed )
|
||||||
|
for k, value in pairs( allowed ) do
|
||||||
|
if v:upper() == k:upper() then return value end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument validator: string value (no validation)
|
||||||
|
options._string_validator = function( v )
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument printer: boolean value
|
||||||
|
options._bool_printer = function( o )
|
||||||
|
return "true|false", o.default and "true" or "false"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument printer: choice value
|
||||||
|
options._choice_printer = function( o )
|
||||||
|
local clist, opts = '', o.data
|
||||||
|
for i = 1, #opts do
|
||||||
|
clist = clist .. ( i ~= 1 and "|" or "" ) .. opts[ i ]
|
||||||
|
end
|
||||||
|
return clist, o.default
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument printer: choice map printer
|
||||||
|
options._choice_map_printer = function( o )
|
||||||
|
local clist, opts, def = '', o.data
|
||||||
|
local i = 1
|
||||||
|
for k, v in pairs( opts ) do
|
||||||
|
clist = clist .. ( i ~= 1 and "|" or "" ) .. k
|
||||||
|
if o.default == v then def = k end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
return clist, def
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Argument printer: string printer
|
||||||
|
options._string_printer = function( o )
|
||||||
|
return nil, o.default
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add an option of the specified type
|
||||||
|
options._add_option = function( self, optname, opttype, help, default, data )
|
||||||
|
local validators =
|
||||||
|
{
|
||||||
|
string = options._string_validator, choice = options._choice_validator,
|
||||||
|
boolean = options._bool_validator, choice_map = options._choice_map_validator
|
||||||
|
}
|
||||||
|
local printers =
|
||||||
|
{
|
||||||
|
string = options._string_printer, choice = options._choice_printer,
|
||||||
|
boolean = options._bool_printer, choice_map = options._choice_map_printer
|
||||||
|
}
|
||||||
|
if not validators[ opttype ] then
|
||||||
|
print( sf( "[builder] Invalid option type '%s'", opttype ) )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
table.insert( self.options, { name = optname, help = help, validator = validators[ opttype ], printer = printers[ opttype ], data = data, default = default } )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find an option with the given name
|
||||||
|
options._find_option = function( self, optname )
|
||||||
|
for i = 1, #self.options do
|
||||||
|
local o = self.options[ i ]
|
||||||
|
if o.name:upper() == optname:upper() then return self.options[ i ] end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 'add option' helper (automatically detects option type)
|
||||||
|
options.add_option = function( self, name, help, default, data )
|
||||||
|
local otype
|
||||||
|
if type( default ) == 'boolean' then
|
||||||
|
otype = 'boolean'
|
||||||
|
elseif data and type( data ) == 'table' and #data == 0 then
|
||||||
|
otype = 'choice_map'
|
||||||
|
elseif data and type( data ) == 'table' then
|
||||||
|
otype = 'choice'
|
||||||
|
data = linearize_array( data )
|
||||||
|
elseif type( default ) == 'string' then
|
||||||
|
otype = 'string'
|
||||||
|
else
|
||||||
|
print( sf( "Error: cannot detect option type for '%s'", name ) )
|
||||||
|
os.exit( 1 )
|
||||||
|
end
|
||||||
|
self:_add_option( name, otype, help, default, data )
|
||||||
|
end
|
||||||
|
|
||||||
|
options.get_num_opts = function( self )
|
||||||
|
return #self.options
|
||||||
|
end
|
||||||
|
|
||||||
|
options.get_option = function( self, i )
|
||||||
|
return self.options[ i ]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle an option of type 'key=value'
|
||||||
|
-- Returns both the key and the value or nil for error
|
||||||
|
options.handle_arg = function( self, a )
|
||||||
|
local si, ei, k, v = a:find( "([^=]+)=(.*)$" )
|
||||||
|
if not k or not v then
|
||||||
|
print( sf( "Error: invalid syntax in '%s'", a ) )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local opt = self:_find_option( k )
|
||||||
|
if not opt then
|
||||||
|
print( sf( "Error: invalid option '%s'", k ) )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local optv = opt.validator( v, opt.data )
|
||||||
|
if optv == nil then
|
||||||
|
print( sf( "Error: invalid value '%s' for option '%s'", v, k ) )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return k, optv
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show help for all the registered options
|
||||||
|
options.show_help = function( self )
|
||||||
|
for i = 1, #self.options do
|
||||||
|
local o = self.options[ i ]
|
||||||
|
print( sf( "\n %s: %s", o.name, o.help ) )
|
||||||
|
local values, default = o.printer( o )
|
||||||
|
if values then
|
||||||
|
print( sf( " Possible values: %s", values ) )
|
||||||
|
end
|
||||||
|
print( sf( " Default value: %s", default or "none (changes at runtime)" ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a new option handler
|
||||||
|
function options_handler()
|
||||||
|
return options.new()
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue