summaryrefslogtreecommitdiff
path: root/libs/lua/luastate.cc
blob: d0555701a7410e20d80387812c47c6263e545d71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <assert.h>
#include "lua/luastate.h"

// from lauxlib.c
static int panic (lua_State *L) {
	lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
			lua_tostring(L, -1));
	return 0;  /* return to Lua to abort */
}

LuaState::LuaState()
	: L (luaL_newstate ())
{
	assert (L);
	init ();
}

LuaState::LuaState(lua_State *ls)
	: L (ls)
{
	assert (L);
	init ();
}

LuaState::~LuaState() {
	lua_close (L);
}

void
LuaState::init() {
	lua_atpanic (L, &panic);
	luaL_openlibs (L);
	lua_pushlightuserdata (L, this);
	lua_pushcclosure (L, &LuaState::_print, 1);
	lua_setglobal (L, "print");
}

int
LuaState::do_command (std::string cmd) {
	int result = luaL_dostring (L, cmd.c_str());
	if (result != 0) {
		print ("Error: " + std::string (lua_tostring (L, -1)));
	}
	return result;
}

int
LuaState::do_file (std::string fn) {
	int result = luaL_dofile (L, fn.c_str());
	if (result != 0) {
		print ("Error: " + std::string (lua_tostring (L, -1)));
	}
	return result;
}

void
LuaState::collect_garbage () {
	lua_gc (L, LUA_GCCOLLECT, 0);
}

void
LuaState::collect_garbage_step (int debt) {
	lua_gc (L, LUA_GCSTEP, debt);
}

void
LuaState::tweak_rt_gc () {
	/* GC runs same speed as  memory allocation */
	lua_gc (L, LUA_GCSETPAUSE, 100);
	lua_gc (L, LUA_GCSETSTEPMUL, 100);
}

void
LuaState::sandbox (bool rt_safe) {
	do_command ("dofile = nil require = nil dofile = nil package = nil debug = nil os.exit = nil os.setlocale = nil rawget = nil rawset = nil coroutine = nil module = nil");
	if (rt_safe) {
		do_command ("os = nil io = nil loadfile = nil");
	}
}


void
LuaState::print (std::string text) {
	Print (text); /* EMIT SIGNAL */
}

int
LuaState::_print (lua_State *L) {
	LuaState* const luaState = static_cast <LuaState*> (lua_touserdata (L, lua_upvalueindex (1)));
	std::string text;
	int n = lua_gettop(L);  /* number of arguments */
	int i;
	lua_getglobal(L, "tostring");
	for (i=1; i<=n; i++) {
		const char *s;
		size_t l;
		lua_pushvalue(L, -1);  /* function to be called */
		lua_pushvalue(L, i);   /* value to print */
		lua_call(L, 1, 1);
		s = lua_tolstring(L, -1, &l);  /* get result */
		if (s == NULL)
			return luaL_error(L, "'tostring' must return a string to 'print'");
		if (i > 1) text += " ";
		text += std::string (s, l);
		lua_pop(L, 1);  /* pop result */
	}
	luaState->print (text);
	return 0;
}