19#include "cmark_wrap.h"
28#include "nlua_audio.h"
30#include "nlua_commodity.h"
33#include "nlua_faction.h"
36#include "nlua_linopt.h"
39#include "nlua_outfit.h"
40#include "nlua_pilot.h"
41#include "nlua_player.h"
43#include "nlua_safelanes.h"
44#include "nlua_shiplog.h"
47#include "nlua_system.h"
59static int nlua_envs = LUA_NOREF;
64typedef struct LuaCache_ {
73static int nlua_package_preload( lua_State *L );
82static int nlua_errTraceInternal( lua_State *L,
int idx );
110 const char *str = luaL_checkstring( L, 1 );
111 lua_pushstring( L, _( str ) );
127 const char *stra = luaL_checkstring( L, 1 );
128 const char *strb = luaL_checkstring( L, 2 );
129 int n = luaL_checkinteger( L, 3 );
130 lua_pushstring( L, n_( stra, strb, n ) );
145 const char *msgctxt = luaL_checkstring( L, 1 );
146 const char *msgid = luaL_checkstring( L, 2 );
162 const char *str = luaL_checkstring( L, 1 );
163 lua_pushstring( L, str );
170 double n = luaL_checknumber( L, 1 );
171 lua_pushnumber( L, log2( n ) );
181 const char *var = luaL_checkstring( L, 1 );
182 if ( strcmp( var,
"HOME" ) )
184 lua_pushstring( L,
"lua_home" );
196 ERR( _(
"LUA PANIC: %s" ), lua_tostring( L, -1 ) );
209 lua_newtable(
naevL );
210 nlua_envs = luaL_ref(
naevL, LUA_REGISTRYINDEX );
225 const char *s = luaL_checklstring( L, 1, &l );
226 const char *chunkname = luaL_optstring( L, 2, s );
227 int status = luaL_loadbuffer( L, s, l, chunkname );
251int nlua_warn( lua_State *L,
int idx )
253 const char *msg = luaL_checkstring( L, idx );
255 nlua_errTraceInternal( L, idx );
256 LOGERR(
"%s", lua_tostring( L, -1 ) );
271 for (
int i = 0; i <
array_size( lua_cache ); i++ ) {
274 luaL_unref(
naevL, LUA_REGISTRYINDEX,
289int nlua_dobufenv( nlua_env env,
const char *buff,
size_t sz,
const char *name )
296 if ( conf.fpu_except )
299 ret = luaL_loadbuffer(
naevL, buff, sz, name );
303 if ( conf.fpu_except )
307 ret = nlua_pcall( env, 0, LUA_MULTRET );
319int nlua_dofileenv( nlua_env env,
const char *filename )
321 if ( luaL_loadfile(
naevL, filename ) != 0 )
323 if ( nlua_pcall( env, 0, LUA_MULTRET ) != 0 )
335int nlua_dochunkenv( nlua_env env,
int chunk,
const char *name )
339 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, chunk );
340 ret = nlua_pcall( env, 0, LUA_MULTRET );
344 lua_pushstring(
naevL, name );
345 nlua_setenv(
naevL, env,
"__name" );
351void nlua_pushEnvTable( lua_State *L )
353 lua_rawgeti( L, LUA_REGISTRYINDEX, nlua_envs );
362nlua_env nlua_newEnv(
const char *name )
367 lua_newtable(
naevL );
368 lua_pushvalue(
naevL, -1 );
369 ref = luaL_ref(
naevL, LUA_REGISTRYINDEX );
372 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, nlua_envs );
373 lua_pushvalue(
naevL, -2 );
374 lua_rawseti(
naevL, -2, ref );
377 if ( name != NULL ) {
378 lua_pushstring(
naevL, name );
379 nlua_setenv(
naevL, ref,
"__name" );
383 lua_newtable(
naevL );
384 lua_pushvalue(
naevL, LUA_GLOBALSINDEX );
385 lua_setfield(
naevL, -2,
"__index" );
386 lua_setmetatable(
naevL, -2 );
389 lua_pushvalue(
naevL, -1 );
391 lua_setfield(
naevL, -2,
"require" );
396 nlua_getenv(
naevL, ref,
"package" );
397 lua_newtable(
naevL );
398 lua_pushvalue(
naevL, -1 );
399 nlua_setenv(
naevL, ref, NLUA_LOAD_TABLE );
400 lua_setfield(
naevL, -2,
"loaded" );
401 lua_newtable(
naevL );
402 lua_setfield(
naevL, -2,
"preload" );
403 lua_pushstring(
naevL,
"?.lua;" LUA_INCLUDE_PATH
"?.lua" );
404 lua_setfield(
naevL, -2,
"path" );
405 lua_pushstring(
naevL,
"" );
406 lua_setfield(
naevL, -2,
"cpath" );
407 lua_getfield(
naevL, -1,
"loaders" );
408 for (
int i = 0;
loaders[i] != NULL; i++ ) {
410 lua_rawseti(
naevL, -2, i + 1 );
415 lua_pushvalue(
naevL, -1 );
416 lua_setfield(
naevL, -2,
"_G" );
420 lua_pushboolean(
naevL, 1 );
421 lua_setfield(
naevL, -2,
"__debugging" );
425 lua_newtable(
naevL );
426 lua_setfield(
naevL, -2,
"naev" );
432 WARN( _(
"Unable to load common script '%s'!" ), LUA_COMMON_PATH );
436 LUA_COMMON_PATH ) == 0 ) {
437 if ( nlua_pcall( ref, 0, 0 ) != 0 ) {
438 WARN( _(
"Failed to run '%s':\n%s" ), LUA_COMMON_PATH,
439 lua_tostring(
naevL, -1 ) );
443 WARN( _(
"Failed to load '%s':\n%s" ), LUA_COMMON_PATH,
444 lua_tostring(
naevL, -1 ) );
458void nlua_freeEnv( nlua_env env )
462 if ( env == LUA_NOREF )
466 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, nlua_envs );
467 lua_pushnil(
naevL );
468 lua_rawseti(
naevL, -2, env );
472 luaL_unref(
naevL, LUA_REGISTRYINDEX, env );
480void nlua_pushenv( lua_State *L, nlua_env env )
482 lua_rawgeti( L, LUA_REGISTRYINDEX, env );
493void nlua_getenv( lua_State *L, nlua_env env,
const char *name )
495 nlua_pushenv( L, env );
496 lua_getfield( L, -1, name );
508void nlua_setenv( lua_State *L, nlua_env env,
const char *name )
511 nlua_pushenv( L, env );
513 lua_setfield( L, -2, name );
527void nlua_register( nlua_env env,
const char *libname,
const luaL_Reg *l,
530 if ( luaL_newmetatable(
naevL, libname ) ) {
532 lua_pushvalue(
naevL, -1 );
533 lua_setfield(
naevL, -2,
"__index" );
535 luaL_register(
naevL, NULL, l );
537 nlua_getenv(
naevL, env,
"naev" );
538 lua_pushvalue(
naevL, -2 );
539 lua_setfield(
naevL, -2, libname );
541 nlua_setenv(
naevL, env, libname );
552 lua_State *L = luaL_newstate();
554 WARN( _(
"Failed to create new Lua state." ) );
568 const char *
override[] = {
570 "dofile",
"getfenv",
"load",
"loadfile", NULL };
575 lua_getglobal( L,
"table" );
576 lua_getglobal( L,
"unpack" );
577 lua_setfield( L, -2,
"unpack" );
580 lua_setglobal( L,
"unpack" );
583 for (
int i = 0;
override[i] != NULL; i++ ) {
585 lua_setglobal( L,
override[i] );
592 lua_register( L,
"warn",
cli_warn );
603 lua_setglobal( L,
"io" );
606 lua_setfield( L, -2,
"getenv" );
607 lua_setglobal( L,
"os" );
610 lua_getglobal( L,
"math" );
612 lua_setfield( L, -2,
"log2" );
614 lua_setfield( L, -2,
"mod" );
627 return strcmp( lc1->
path, lc2->
path );
630static int nlua_package_preload( lua_State *L )
632 const char *name = luaL_checkstring( L, 1 );
634 lua_getglobal( L,
"package" );
635 if ( !lua_istable( L, -1 ) ) {
637 lua_pushstring( L, _(
" package not found." ) );
641 lua_getfield( L, -1,
"preload" );
643 if ( !lua_istable( L, -1 ) )
644 luaL_error( L, LUA_QL(
"package.preload" )
" must be a table" );
645 lua_getfield( L, -1, name );
646 if ( lua_isnil( L, -1 ) )
647 lua_pushfstring( L,
"\n\tno field package.preload['%s']", name );
662 size_t bufsize, l = 0;
665 const char *packagepath, *start, *end;
666 const char *name = luaL_checkstring( L, 1 );
670 lua_getglobal( L,
"package" );
671 if ( !lua_istable( L, -1 ) ) {
673 lua_pushstring( L, _(
" package not found." ) );
676 lua_getfield( L, -1,
"path" );
677 if ( !lua_isstring( L, -1 ) ) {
679 lua_pushstring( L, _(
" package.path not found." ) );
682 packagepath = lua_tostring( L, -1 );
689 end = strchr( start,
';' );
692 end = &start[strlen( start )];
694 strncpy( tmpname, start, end - start );
695 tmpname[end - start] =
'\0';
696 q = strchr( tmpname,
'?' );
698 snprintf( path_filename,
sizeof( path_filename ),
"%s%s", tmpname,
702 snprintf( path_filename,
sizeof( path_filename ),
"%s%s%s", tmpname,
709 q = strrchr( path_filename,
'.' );
710 for (
int i = 0; i < q - path_filename; i++ )
711 if ( path_filename[i] ==
'.' )
712 path_filename[i] =
'/';
716 const LuaCache_t lcq = { .path = path_filename };
717 lc = bsearch( &lcq, lua_cache,
array_size( lua_cache ),
720 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, lc->
idx );
726 if ( PHYSFS_exists( path_filename ) ) {
733 l +=
scnprintf( &tried_paths[l],
sizeof( tried_paths ) - l,
734 _(
"\n no ndata path '%s'" ), path_filename );
739 lua_pushstring( L, tried_paths );
745 luaL_loadbuffer( L, buf, bufsize, path_filename );
751 lc->
path = strdup( path_filename );
752 lua_pushvalue( L, -1 );
753 lc->
idx = luaL_ref(
naevL, LUA_REGISTRYINDEX );
770 const char *name = luaL_checkstring( L, 1 );
772 if ( strcmp( name,
"utf8" ) == 0 )
773 lua_pushcfunction( L, luaopen_utf8 );
774 else if ( strcmp( name,
"enet" ) == 0 && conf.lua_enet )
775 lua_pushcfunction( L, luaopen_enet );
776 else if ( strcmp( name,
"cmark" ) == 0 )
777 lua_pushcfunction( L, luaopen_cmark );
778 else if ( strcmp( name,
"yaml" ) == 0 )
779 lua_pushcfunction( L, luaopen_yaml );
809 const char *filename = luaL_checkstring( L, 1 );
812 int envtab = lua_upvalueindex( 1 );
816 lua_getfield( L, envtab, NLUA_LOAD_TABLE );
817 if ( !lua_isnil( L, -1 ) ) {
818 lua_getfield( L, -1, filename );
820 if ( !lua_isnil( L, -1 ) ) {
826 luaL_error( L, _(
"_LOADED must be a table" ) );
828 lua_getglobal( L,
"package" );
829 if ( !lua_istable( L, -1 ) )
830 luaL_error( L, _(
"package must be a table" ) );
831 lua_getfield( L, -1,
"loaders" );
833 if ( !lua_istable( L, -1 ) )
834 luaL_error( L, _(
"package.loaders must be a table" ) );
835 lua_pushliteral( L,
"" );
836 for (
int i = 1;; i++ ) {
837 lua_rawgeti( L, -2, i );
838 if ( lua_isnil( L, -1 ) )
839 luaL_error( L, _(
"module '%s' not found:%s" ), filename,
840 lua_tostring( L, -2 ) );
841 lua_pushstring( L, filename );
843 if ( lua_isfunction( L, -1 ) )
845 else if ( lua_isstring( L, -1 ) )
855 lua_pushvalue( L, envtab );
856 lua_setfenv( L, -2 );
859 lua_pushstring( L, filename );
861 if (lua_pcall(L, 1, 1, 0) != 0) {
870 if ( lua_isnil( L, -1 ) ) {
872 lua_pushboolean( L, 1 );
875 lua_getfield( L, envtab, NLUA_LOAD_TABLE );
876 lua_pushvalue( L, -2 );
877 lua_setfield( L, -2, filename );
948 return nlua_errTraceInternal( L, 1 );
951static int nlua_errTraceInternal( lua_State *L,
int idx )
954 const char *str = luaL_checkstring( L, idx );
955 if ( strcmp( str, NLUA_DONE ) == 0 )
960 lua_getglobal( L,
"debug" );
961 if ( !lua_istable( L, -1 ) ) {
965 lua_getfield( L, -1,
"traceback" );
966 if ( !lua_isfunction( L, -1 ) ) {
970 lua_pushvalue( L, -3 );
971 lua_pushinteger( L, 2 );
985int nlua_pcall( nlua_env env,
int nargs,
int nresults )
987 int errf, ret, prev_env;
990 errf = lua_gettop(
naevL ) - nargs;
992 lua_insert(
naevL, errf );
997 if ( conf.fpu_except )
1006 nlua_pushenv(
naevL, env );
1007 lua_setfenv(
naevL, -2 - nargs );
1008 ret = lua_pcall(
naevL, nargs, nresults, errf );
1013 lua_remove(
naevL, errf );
1015 if ( conf.fpu_except )
1031 nlua_getenv(
naevL, env, name );
1032 if ( !lua_isnil(
naevL, -1 ) )
1033 return luaL_ref(
naevL, LUA_REGISTRYINDEX );
1034 lua_pop(
naevL, 1 );
1049 nlua_getenv(
naevL, env, name );
1050 if ( lua_type(
naevL, -1 ) == type )
1051 return luaL_ref(
naevL, LUA_REGISTRYINDEX );
1052 lua_pop(
naevL, 1 );
1065 if ( objref == LUA_NOREF )
1067 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, objref );
1068 lua_getfield(
naevL, -1, name );
1069 lua_remove(
naevL, -2 );
1070 if ( !lua_isnil(
naevL, -1 ) )
1071 return luaL_ref(
naevL, LUA_REGISTRYINDEX );
1072 lua_pop(
naevL, 1 );
1081 lua_pushvalue( L, idx );
1082 return luaL_ref( L, LUA_REGISTRYINDEX );
1090 if ( idx != LUA_NOREF )
1091 luaL_unref( L, LUA_REGISTRYINDEX, idx );
1099 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, nlua_envs );
1100 lua_pushnil(
naevL );
1101 while ( lua_next(
naevL, -2 ) != 0 ) {
1102 int env = lua_tointeger(
naevL, -2 );
1103 lua_getfield(
naevL, -1,
"__resize" );
1104 if ( !lua_isnil(
naevL, -1 ) ) {
1105 lua_pushinteger(
naevL, SCREEN_W );
1106 lua_pushinteger(
naevL, SCREEN_H );
1107 nlua_pcall( env, 2, 0 );
1108 lua_pop(
naevL, 1 );
1110 lua_pop(
naevL, 2 );
1112 lua_pop(
naevL, 1 );
1120 if ( lua_isnoneornil( L, idx ) ) {
1122 for (
int i = 0; i <
array_size( tags ); i++ ) {
1123 lua_pushstring( L, tags[i] );
1124 lua_pushboolean( L, 1 );
1125 lua_rawset( L, -3 );
1129 const char *s = luaL_checkstring( L, idx );
1130 for (
int i = 0; i <
array_size( tags ); i++ ) {
1131 if ( strcmp( s, tags[i] ) == 0 ) {
1132 lua_pushboolean( L, 1 );
1136 lua_pushboolean( L, 0 );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
int cli_warn(lua_State *L)
Barebones warn implementation for Lua, allowing scripts to print warnings to stderr.
int cli_printRaw(lua_State *L)
Prints raw markup to the console.
int cli_print(lua_State *L)
Replacement for the internal Lua print to print to both the console and the terminal.
void cli_printCoreString(const char *s, int escape)
Prints a string.
void debug_disableFPUExcept(void)
Disables FPU exceptions.
void debug_enableFPUExcept(void)
Enables FPU exceptions. Artificially limited to Linux until link issues are figured out.
const char * pgettext_var(const char *msgctxt, const char *msgid)
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
static int nlua_require(lua_State *L)
include( string module )
void nlua_unref(lua_State *L, int idx)
Removes a reference set with nlua_ref.
static int nlua_log2(lua_State *L)
Implements the Lua function math.log2 (base-2 logarithm).
static int nlua_loadBasic(lua_State *L)
Loads specially modified basic stuff.
int nlua_refenv(nlua_env env, const char *name)
Gets the reference of a global in a lua environment.
static int nlua_pgettext(lua_State *L)
gettext support with context.
int nlua_ref(lua_State *L, int idx)
Creates a new reference to a Lua structure at a position.
static int nlua_panic(lua_State *L)
Handles what to do when Lua panics.
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
static lua_State * nlua_newState(void)
Wrapper around luaL_newstate.
static int nlua_gettext_noop(lua_State *L)
gettext support (noop). Does not actually do anything, but gets detected by gettext.
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
int nlua_helperTags(lua_State *L, int idx, char *const *tags)
Helper function to deal with tags.
static int nlua_gettext(lua_State *L)
gettext support.
static const lua_CFunction loaders[]
int nlua_reffield(int objref, const char *name)
Gets the reference to the specified field from an object reference.
static int nlua_package_loader_croot(lua_State *L)
load( string module ) – searcher function to replace package.loaders[4] (Lua 5.1),...
static char * common_script
static int nlua_package_loader_lua(lua_State *L)
load( string module ) – searcher function to replace package.loaders[2] (Lua 5.1),...
void lua_clearCache(void)
Clears the cached stuff.
void nlua_resize(void)
Propagates a resize event to all the environments forcibly.
static int lua_cache_cmp(const void *p1, const void *p2)
Compares two Lua caches.
int nlua_errTrace(lua_State *L)
Gets a trace from Lua.
static int nlua_ngettext(lua_State *L)
gettext support for singular and plurals.
static int nlua_os_getenv(lua_State *L)
Implements the Lua function os.getenv. In the sandbox we only make a fake $HOME visible.
static int luaB_loadstring(lua_State *L)
Replacement for the internal Lua loadstring().
static int nlua_package_loader_c(lua_State *L)
load( string module ) – searcher function to replace package.loaders[3] (Lua 5.1),...
static const luaL_Reg gettext_methods[]
int nlua_loadAudio(nlua_env env)
Loads the audio library.
int nlua_loadCommodity(nlua_env env)
Loads the commodity library.
int nlua_loadData(nlua_env env)
Loads the data library.
int nlua_loadDiff(nlua_env env)
Loads the diff Lua library.
int nlua_loadFaction(nlua_env env)
Loads the faction library.
int nlua_loadFile(nlua_env env)
Loads the file library.
int nlua_loadJump(nlua_env env)
Loads the jump library.
int nlua_loadLinOpt(nlua_env env)
Loads the linopt library.
int nlua_loadNaev(nlua_env env)
Loads the Naev Lua library.
int nlua_loadNews(nlua_env env)
Loads the news library.
int nlua_loadOutfit(nlua_env env)
Loads the outfit library.
int nlua_loadPilot(nlua_env env)
Loads the pilot library.
int nlua_loadPlayer(nlua_env env)
Loads the player Lua library.
int nlua_loadRnd(nlua_env env)
Loads the Random Number Lua library.
int nlua_loadSafelanes(nlua_env env)
Loads the safelanes Lua library.
int nlua_loadShiplog(nlua_env env)
Loads the mission Lua library.
int nlua_loadSpfx(nlua_env env)
Loads the spfx library.
int nlua_loadSpob(nlua_env env)
Loads the spob library.
int nlua_loadSystem(nlua_env env)
Loads the system library.
int nlua_loadTime(nlua_env env)
Loads the Time Lua library.
int nlua_loadVar(nlua_env env)
Loads the mission variable Lua library.
int nlua_loadVector(nlua_env env)
Loads the vector metatable.
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Cache structure for loading chunks.