Files
itgmania212121/stepmania/src/LuaHelpers.cpp
T

206 lines
4.4 KiB
C++
Raw Normal View History

2004-02-14 21:08:12 +00:00
#include "global.h"
#include "LuaHelpers.h"
#include "LuaFunctions.h"
#include "RageUtil.h"
#include "RageLog.h"
2004-04-05 05:22:32 +00:00
#include <csetjmp>
#include <cassert>
2004-02-14 21:08:12 +00:00
LuaFunctionList *g_LuaFunctionList = NULL;
#if defined(_WINDOWS)
#pragma comment(lib, "lua-5.0/lua.lib")
/* "interaction between '_setjmp' and C++ object destruction is non-portable"
* We don't care; we'll throw a fatal exception immediately anyway. */
#pragma warning (disable : 4611)
#endif
2004-05-26 20:52:42 +00:00
#if defined (DARWIN)
extern void NORETURN longjmp(jmp_buf env, int val);
#endif
2004-02-14 21:08:12 +00:00
struct ChunkReaderData
{
const CString *buf;
bool done;
ChunkReaderData() { buf = NULL; done = false; }
};
const char *ChunkReaderString( lua_State *L, void *ptr, size_t *size )
{
ChunkReaderData *data = (ChunkReaderData *) ptr;
if( data->done )
return NULL;
data->done = true;
*size = data->buf->size();
const char *ret = data->buf->data();
return ret;
}
void Lua::PushStack( lua_State *L, int out )
{
/* XXX: stack bounds */
lua_pushnumber( L, out );
}
void Lua::PushStack( lua_State *L, bool out )
{
/* XXX: stack bounds */
lua_pushboolean( L, out );
}
void Lua::PushStack( lua_State *L, void *out )
{
if( out )
lua_pushlightuserdata( L, out );
else
lua_pushnil( L );
}
void Lua::PushStack( lua_State *L, const CString &out )
{
lua_pushstring( L, out );
}
void Lua::PopStack( lua_State *L, CString &out )
{
/* There must be at least one entry on the stack. */
ASSERT( lua_gettop(L) > 0 );
ASSERT( lua_isstring(L, -1) );
out = lua_tostring( L, -1 );
lua_pop( L, -1 );
}
2004-02-25 23:58:47 +00:00
bool Lua::GetStack( lua_State *L, int pos, int &out )
{
if( pos < 0 )
pos = lua_gettop(L) - pos - 1;
if( pos < 1 )
return false;
out = (int) lua_tonumber( L, pos );
return true;
}
2004-02-14 21:08:12 +00:00
void LoadFromString( lua_State *L, const CString &str )
{
ChunkReaderData data;
data.buf = &str;
int ret = lua_load( L, ChunkReaderString, &data, "in" );
if( ret )
{
CString err;
Lua::PopStack( L, err );
RageException::Throw( "Error loading script \"%s\": %s", str.c_str(), err.c_str() );
}
}
static jmp_buf jbuf;
static CString jbuf_error;
2004-02-24 08:00:04 +00:00
static int LuaPanic( lua_State *L )
2004-02-14 21:08:12 +00:00
{
CString err;
Lua::PopStack( L, err );
/* Grr. We can't throw an exception from here: it'll explode going through the
* Lua stack for some reason. Get it off the stack with a longjmp and throw
* an exception from there. */
jbuf_error = err;
longjmp( jbuf, 1 );
}
bool Lua::RunExpression( const CString &str )
{
try {
if( setjmp(jbuf) )
throw jbuf_error;
lua_State *L = lua_open();
ASSERT( L );
lua_atpanic( L, LuaPanic );
luaopen_base( L );
2004-02-15 00:42:45 +00:00
luaopen_math( L );
luaopen_string( L );
2004-02-14 21:08:12 +00:00
lua_settop(L, 0); // luaopen_* pushes stuff onto the stack that we don't need
Lua::RegisterFunctions( L );
LoadFromString( L, "return " + str );
RAGE_ASSERT_M( lua_gettop(L) == 1, ssprintf("%i", lua_gettop(L)) );
int ret = lua_pcall(L, 0, 1, 0);
if( ret )
{
CString err;
Lua::PopStack( L, err );
2004-02-15 21:28:36 +00:00
RageException::Throw( "Runtime error running \"%s\": %s", str.c_str(), err.c_str() );
2004-02-14 21:08:12 +00:00
}
RAGE_ASSERT_M( lua_gettop(L) == 1, ssprintf("%i", lua_gettop(L)) );
/* Don't accept a function as a return value; if you really want to use a function
* as a boolean, convert it before returning. */
if( lua_isfunction( L, -1 ) )
throw CString( "result is a function; did you forget \"()\"?" );
2004-02-14 21:08:12 +00:00
bool result = !!lua_toboolean( L, -1 );
lua_pop( L, -1 );
lua_close( L );
return result;
2004-02-15 21:28:36 +00:00
} catch( const CString &err ) {
RageException::Throw( "Error running \"%s\": %s", str.c_str(), err.c_str() );
2004-02-14 21:08:12 +00:00
}
}
void Lua::Fail( lua_State *L, const CString &err )
{
lua_pushstring( L, err );
lua_error( L );
}
void Lua::RegisterFunctions( lua_State *L )
{
for( const LuaFunctionList *p = g_LuaFunctionList; p; p=p->next )
lua_register( L, p->name, p->func );
}
LuaFunctionList::LuaFunctionList( CString name_, lua_CFunction func_ )
{
name = name_;
func = func_;
next = g_LuaFunctionList;
g_LuaFunctionList = this;
}
2004-02-25 23:58:47 +00:00
LuaFunction_NoArgs( MonthOfYear, GetLocalTime().tm_mon+1 );
2004-02-14 21:08:12 +00:00
LuaFunction_NoArgs( DayOfMonth, GetLocalTime().tm_mday );
LuaFunction_NoArgs( Hour, GetLocalTime().tm_hour );
LuaFunction_NoArgs( Minute, GetLocalTime().tm_min );
LuaFunction_NoArgs( Second, GetLocalTime().tm_sec );
LuaFunction_NoArgs( Year, GetLocalTime().tm_year+1900 );
LuaFunction_NoArgs( Weekday, GetLocalTime().tm_wday );
LuaFunction_NoArgs( DayOfYear, GetLocalTime().tm_yday );
/*
* Copyright (c) 2004 by the person(s) listed below. All rights reserved.
* Glenn Maynard
*/