This repository has been archived on 2019-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
adventin/src/sdl-instead/instead.c
2009-08-26 05:25:53 +00:00

270 lines
4.6 KiB
C

#ifndef STEAD_PATH
#define STEAD_PATH "./stead"
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// #include <libintl.h>
#include <unistd.h>
#include "gui.h"
#ifdef _HAVE_ICONV
#include <iconv.h>
#endif
#include "game.h"
/* the Lua interpreter */
char *fromgame(const char *s);
char *togame(const char *s);
lua_State *L = NULL;
static int report (lua_State *L, int status)
{
if (status && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL)
msg = "(error object is not a string)";
fprintf(stderr,"Error: %s\n", msg);
game_err_msg(msg);
lua_pop(L, 1);
status = -1;
}
return status;
}
static int traceback (lua_State *L)
{
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return 1;
}
lua_getfield(L, -1, "traceback");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 2);
return 1;
}
lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback */
return 1;
}
extern int debug_sw;
static int docall (lua_State *L)
{
int status;
int base = 0;
if (debug_sw) {
base = lua_gettop(L); /* function index */
lua_pushcfunction(L, traceback); /* push traceback function */
lua_insert(L, base); /* put it under chunk and args */
}
status = lua_pcall(L, 0, LUA_MULTRET, base);
if (debug_sw)
lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */
if (status != 0)
lua_gc(L, LUA_GCCOLLECT, 0);
return status;
}
static int dofile (lua_State *L, const char *name) {
int status = luaL_loadfile(L, name) || docall(L);
return report(L, status);
}
static int dostring (lua_State *L, const char *s) {
int status = luaL_loadstring(L, s) || docall(L);
return report(L, status);
}
char *getstring(char *cmd)
{
char *s;
if (!L)
return NULL;
if (dostring(L, cmd))
return NULL;
s = (char*)lua_tostring(L, -1);
if (s)
s = fromgame(s);
return s;
}
char *instead_eval(char *s)
{
char *p;
p = getstring(s);
return p;
}
char *instead_cmd(char *s)
{
char buf[1024];
char *p = s;
while (*p) {
if (*p == '\\' || *p == '\'' || *p == '\"' || *p == '[' || *p == ']')
return NULL;
p ++;
}
s = togame(s);
snprintf(buf, sizeof(buf), "return iface:cmd('%s')", s);
free(s);
p = getstring(buf);
return p;
}
int luacall(char *cmd)
{
int rc;
if (!L)
return -1;
if (dostring(L, cmd)) {
return -1;
}
rc = lua_tonumber(L, -1);
return rc;
}
#ifdef _HAVE_ICONV
static char *curcp = "UTF-8";
static char *fromcp = NULL;
#endif
#ifdef _HAVE_ICONV
#define CHAR_MAX_LEN 4
static char *decode(iconv_t hiconv, const char *s)
{
size_t s_size, chs_size, outsz, insz;
char *inbuf, *outbuf, *chs_buf;
if (!s || hiconv == (iconv_t)(-1))
return NULL;
s_size = strlen(s) + 1;
chs_size = s_size * CHAR_MAX_LEN;
if ((chs_buf = malloc(chs_size + CHAR_MAX_LEN))==NULL)
goto exitf;
outsz = chs_size;
outbuf = chs_buf;
insz = s_size;
inbuf = (char*)s;
while (insz) {
if (iconv(hiconv, &inbuf, &insz, &outbuf, &outsz)
== (size_t)(-1))
goto exitf;
}
*outbuf++ = 0;
return chs_buf;
exitf:
if(chs_buf)
free(chs_buf);
return NULL;
}
char *fromgame(const char *s)
{
iconv_t han;
char *str;
if (!s)
return NULL;
if (!fromcp)
goto out0;
han = iconv_open(curcp, fromcp);
if (han == (iconv_t)-1)
goto out0;
if (!(str = decode(han, s)))
goto out1;
iconv_close(han);
return str;
out1:
iconv_close(han);
out0:
return strdup(s);
}
char *togame(const char *s)
{
iconv_t han;
char *str;
if (!s)
return NULL;
if (!fromcp)
goto out0;
han = iconv_open(fromcp, curcp);
if (han == (iconv_t)-1)
goto out0;
if (!(str = decode(han, s)))
goto out1;
iconv_close(han);
return str;
out1:
iconv_close(han);
out0:
return strdup(s);
}
#else
char *fromgame(const char *s)
{
if (!s)
return NULL;
return strdup(s);
}
char *togame(const char *s)
{
if (!s)
return NULL;
return strdup(s);
}
#endif
int instead_load(char *game)
{
if (dofile(L, game)) {
return -1;
}
#ifdef _HAVE_ICONV
if (fromcp)
free(fromcp);
fromcp = getstring("return game.codepage;");
#endif
return 0;
}
int instead_init(void)
{
setlocale(LC_ALL,"");
// strcpy(curcp, "UTF-8");
/* initialize Lua */
L = lua_open();
luaL_openlibs(L);
if (dofile(L,STEAD_PATH"/stead.lua")) {
return -1;
}
if (luacall(instead_gui_lua)) {
return -1;
}
/* cleanup Lua */
return 0;
}
void instead_done(void)
{
#ifdef _HAVE_ICONV
if (fromcp)
free(fromcp);
#endif
if (L)
lua_close(L);
L = NULL;
#ifdef _HAVE_ICONV
fromcp = NULL;
#endif
}