Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Copyright (C) 2009-2011 Cor Entertainment, LLC
- Copyright assigned by Max Eliaser
- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- Another file has been made, which contains only the "sharedTable" utilities.
- This version, also by Max Eliaser, is available elsewhere, and is released
- into the public domain. You can get a copy here:
- TODO: make this version, host it, put URL here
- If that version is unavailable for some reason, email Max at
- <maxxedout@comcast.net>
- */
- #include <lua5.1/lua.h>
- #include <lua5.1/lualib.h>
- #include <lua5.1/lauxlib.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /*#include "qcommon.h"*/
- #include "../server/server.h"
- cvar_t *ldeveloper;
- #define curr_console (con_curDebuggedCon?con_curDebuggedCon:con_curAlternateCon)
- #define PARANOID
- #ifdef PARANOID
- static void qlua_checkConsole (lua_State *luaVM_local) {
- int scriptID;
- lua_getglobal (luaVM_local, "selfID");
- scriptID = lua_tointeger(luaVM_local, -1);
- assert (scriptID == (curr_console));
- }
- #else
- #define qlua_checkConsole(x)
- #endif
- //functions which start with "LUA" (all-caps) are used within scripts
- //functions which start with "qlua" (no caps) are lua-related but not used directly within scripts.
- void qlua_clearStack (lua_State **luaVM_local ) {
- lua_settop (*luaVM_local, 0);
- }
- //for debugging
- void qlua_printStack (lua_State *L) {
- int i;
- for (i = 1; i <= lua_gettop(L); i++)
- printf ("%d: %s\n", i, lua_typename(L, lua_type(L, i)));
- printf ("===========\n");
- }
- /*
- This state will not contain or run any actual code.
- On other scripts, a single table called sharedTable will show up, but that
- table will be empty; instead, it will be made to act as a proxy for a table
- called sharedTable on luaVMShared which has all the actual data.
- */
- lua_State *luaVMShared;
- //wrapper around the addText function for use within lua scripts
- int LUA_Cbuf_AddText (lua_State *luaVM_local) {
- int sID;
- const char *msg;
- qlua_checkConsole (luaVM_local);
- sID = curr_console-1;
- if (!lua_isstring (luaVM_local, 1)){
- lua_pushstring (luaVM_local, "qconsole_send: Wrong agument type!\n");
- lua_error (luaVM_local);
- }
- msg = lua_tostring (luaVM_local, 1);
- if (scripts[sID]->cmd_console.cursize + strlen(msg) > scripts[sID]->cmd_console.maxsize){
- lua_pushstring (luaVM_local, "qconsole_send: Overflow!\n");
- lua_error (luaVM_local);
- }
- Abuf_AddText (&(scripts[sID]->cmd_console), (char *)msg);
- return 0;
- }
- int LUA_Cbuf_Execute (lua_State *luaVM_local) {
- int tmpCon = con_toPrintTo;
- qboolean discard = false;
- int starting_consize;
- int sID;
- qlua_checkConsole (luaVM_local);
- if ( !strcmp ( lua_tostring (luaVM_local, 1), "private" ) ){
- con_toPrintTo = curr_console;
- } else if ( !strcmp (lua_tostring (luaVM_local, 1), "public" ) ){
- if (dedicated->integer)
- broadcastInstead = true;
- con_toPrintTo = DISPLAYED_CONSOLE;
- } else if ( !strcmp ( lua_tostring (luaVM_local, 1), "devel" ) ){
- //If ldeveloper is 1, "devel" is like "public," otherwise output goes
- //to the bit bucket. For info which is useful for developers but is
- //confusing for everyone else.
- if (!ldeveloper->integer){
- discard = true;
- con_toPrintTo = curr_console;
- } else
- con_toPrintTo = DISPLAYED_CONSOLE;
- } else {
- retassert(lua_pushfstring ( luaVM_local, "qconsole_do: argument 1 must be 'devel,' 'private' or 'public.'\n(Got %s)\n",
- lua_tostring(luaVM_local, 1) ) );
- lua_error (luaVM_local);
- }
- sID = curr_console-1;
- if (discard)
- starting_consize = scripts[sID]->con_output.cursize;
- if (!Abuf_Execute (&(scripts[sID]->cmd_console))) {
- lua_pushstring (luaVM_local, "qconsole_do: one of the commands failed.\n");
- lua_error (luaVM_local);
- }
- if (discard)
- scripts[sID]->con_output.cursize = starting_consize;
- con_toPrintTo = tmpCon;
- broadcastInstead = false;
- return 0;
- }
- int LUA_con_alternateOutput (lua_State *luaVM_local) {
- if ( strcmp (lua_tostring (luaVM_local, 1), "private" ) == 0 ){
- SZ_Clip(&(scripts[curr_console-1]->con_output));
- lua_pushstring (luaVM_local, scripts[curr_console-1]->con_output_buf);
- } else if ( strcmp (lua_tostring (luaVM_local, 1), "public" ) == 0 ){
- lua_pushstring (luaVM_local, (char *)(publicMsgOutputBuf + scripts[curr_console-1]->publicMsgItemsReadSoFar));
- scripts[curr_console-1]->publicMsgItemsReadSoFar = publicMsgOutputBufCount;
- } else {
- retassert(lua_pushfstring ( luaVM_local, "qconsole_get: argument 1 must be either 'private' or 'public.'\n(Got %s)\n",
- lua_tostring(luaVM_local, 1) ) );
- lua_error (luaVM_local);
- }
- return 1;
- }
- int LUA_clr_con_alternateOutput (lua_State *luaVM_local) {
- qlua_checkConsole (luaVM_local);
- scripts[curr_console-1]->con_output.cursize = 0;
- return 0;
- }
- /*
- Equivalent to the following Lua code:
- function getStringFromCommand (command)
- qconsole_do ("devel")
- qconsole_clr()
- qconsole_send (command)
- qconsole_do ("private")
- local text = string.sub(qconsole_get ("private"), 1, -2) -- get rid of extraneous newline
- qconsole_clr()
- return text
- end
- Since crossing the boundary between C and Lua is expensive, and this is
- probably the single most common function used by scripts, it's worthwhile to
- write it in C.
- */
- int LUA_getStringFromCommand (lua_State *luaVM_local) {
- int sID;
- qboolean discard = false;
- const char *msg;
- int tmpCon = con_toPrintTo;
- qlua_checkConsole (luaVM_local);
- if (!lua_isstring (luaVM_local, 1)) {
- lua_pushstring (luaVM_local, "getStringFromCommand: Wrong argument type!\n");
- lua_error (luaVM_local);
- }
- sID = curr_console-1;
- if (!ldeveloper->integer) {
- discard = true;
- con_toPrintTo = curr_console;
- } else
- con_toPrintTo = DISPLAYED_CONSOLE;
- if (!Abuf_Execute (&(scripts[sID]->cmd_console))) {
- lua_pushstring (luaVM_local, "getStringFromCommand: one of the previous commands failed.\n");
- lua_error (luaVM_local);
- }
- scripts[sID]->con_output.cursize = 0;
- con_toPrintTo = curr_console;
- msg = lua_tostring (luaVM_local, 1);
- if (scripts[sID]->cmd_console.cursize + strlen(msg) > scripts[sID]->cmd_console.maxsize){
- lua_pushstring (luaVM_local, "getStringFromCommand: Overflow!\n");
- lua_error (luaVM_local);
- }
- Abuf_AddText (&(scripts[sID]->cmd_console), (char *)msg);
- if (!Abuf_Execute (&(scripts[sID]->cmd_console))) {
- lua_pushstring (luaVM_local, "getStringFromCommand: one of the commands failed.\n");
- lua_error (luaVM_local);
- }
- scripts[sID]->con_output.cursize--; //get rid of extraneous newline
- SZ_Clip(&(scripts[sID]->con_output));
- lua_pushstring (luaVM_local, scripts[sID]->con_output_buf);
- scripts[sID]->con_output.cursize = 0;
- con_toPrintTo = tmpCon;
- return 1;
- }
- int LUA_com_printf (lua_State *luaVM_local) {
- const char *s;
- int tmpCon = con_toPrintTo;
- s = lua_tostring (luaVM_local, 1);
- if (!s){
- lua_pushstring (luaVM_local, "qconsole_print: must have exactly 1 argument which must be a string.\n");
- lua_error (luaVM_local);
- }
- con_toPrintTo = DISPLAYED_CONSOLE;
- Com_Printf ("%s\n", s);
- con_toPrintTo = tmpCon;
- return 0;
- }
- qboolean qlua_interrupt ( lua_State **luaVM_local, char *message ){
- int old_currentInterruptedScript;
- qboolean ret;
- if (con_curDebuggedCon){
- return true;
- printf ("WTPF?!\n");
- }
- old_currentInterruptedScript = currentInterruptedScript;
- lua_getglobal (*luaVM_local, "selfID");
- currentInterruptedScript = (int)lua_tonumber(*luaVM_local, -1);
- lua_pop (*luaVM_local, 1);
- assert (lua_checkstack ( *luaVM_local, 8));
- lua_getglobal ( *luaVM_local, "_interrupt");
- lua_pushstring ( *luaVM_local, message);
- if (qlua_pcall (currentInterruptedScript, 1, 0)){
- fprintf (stderr, "Debugger started on interrupting %d with message %s\n", currentInterruptedScript, message);
- currentInterruptedScript = old_currentInterruptedScript;
- return false;
- }
- ret = Abuf_Execute(&(scripts[currentInterruptedScript-1]->cmd_console));
- qlua_clearStack (luaVM_local);Paste Name / Title:
- currentInterruptedScript = old_currentInterruptedScript;
- return ret;
- }
- void qlua_initVM ( lua_State **luaVM_local) {
- int env_stackpos; //stack position of the thread's environment table
- lua_getglobal (luaVMShared, "states");
- *luaVM_local = lua_newthread (luaVMShared);
- lua_pushinteger (luaVMShared, con_curAlternateCon);
- lua_settable (luaVMShared, -3);
- lua_pop (luaVMShared, 1);
- lua_pushthread (*luaVM_local);
- #ifdef METHOD_A
- //Method A: Create a new table for the environment, and call luaL_openlibs
- lua_newtable (*luaVM_local);
- #else
- //Method B: Create a deep copy of the "main" environment,
- lua_getglobal (luaVMShared, "memoizing_deepcopy");
- lua_pushvalue (luaVMShared, LUA_GLOBALSINDEX);
- if (lua_pcall (luaVMShared, 1, 1, 0))
- fprintf (stderr, "error copying _G! %s\n", lua_tostring (luaVMShared, -1));
- lua_xmove (luaVMShared, *luaVM_local, 1);
- #endif
- lua_setfenv (*luaVM_local, -2);
- lua_getfenv (*luaVM_local, -1);
- env_stackpos = lua_gettop (*luaVM_local);
- #ifdef METHOD_A
- luaL_openlibs (*luaVM_local);
- #endif
- lua_checkstack (*luaVM_local, 5);
- //lpack library
- luaopen_pack (*luaVM_local);
- //register custom functions (API)
- lua_register ( *luaVM_local, "qconsole_send", LUA_Cbuf_AddText);
- lua_register ( *luaVM_local, "qconsole_do", LUA_Cbuf_Execute);
- lua_register ( *luaVM_local, "qconsole_get", LUA_con_alternateOutput);
- lua_register ( *luaVM_local, "qconsole_clr", LUA_clr_con_alternateOutput);
- lua_register ( *luaVM_local, "qconsole_print", LUA_com_printf);
- lua_register ( *luaVM_local, "getStringFromCommand", LUA_getStringFromCommand);
- // create the sharedTable proxy
- lua_getglobal ( luaVMShared, "sharedTable");
- lua_xmove ( luaVMShared, *luaVM_local, 1);
- lua_setfield ( *luaVM_local, env_stackpos, "sharedTable");
- //other misc variables we define go here
- lua_pushnumber ( *luaVM_local, con_curAlternateCon);
- lua_setfield ( *luaVM_local, env_stackpos, "selfID");
- luaL_loadfile ( *luaVM_local, "data1/lua/sys/interrupt_wrapper.lua" );
- if (lua_pcall ( *luaVM_local, 0, 0, 0))
- fprintf (stderr, "error loading interrupt wrapper!\n");
- //new print() function
- luaL_loadfile ( *luaVM_local, "data1/lua/sys/qprint.lua" );
- if (lua_pcall ( *luaVM_local, 0, 0, 0))
- fprintf (stderr, "Couldn't override print()!\n");
- //initialize debugger module
- qlua_init_debugger ( *luaVM_local );
- }
- qboolean qlua_doString (lua_State **luaVM_local, char *script ) {
- int old_currentInterruptedScript = currentInterruptedScript;
- lua_settop (*luaVM_local, 0);
- lua_getglobal (*luaVM_local, "selfID");
- currentInterruptedScript = (int)lua_tonumber(*luaVM_local, -1);
- lua_pop (*luaVM_local, 1);
- lua_getglobal (*luaVM_local, "print");
- luaL_loadstring (*luaVM_local, script);
- if (lua_pcall (*luaVM_local, 0, 0, 1)){
- Abuf_Execute(&(scripts[currentInterruptedScript-1]->cmd_console));
- currentInterruptedScript = old_currentInterruptedScript;
- return false;
- }
- currentInterruptedScript = old_currentInterruptedScript;
- lua_getglobal (*luaVM_local, "noinit");
- if (lua_isnil(*luaVM_local, -1) && !(int)lua_tonumber(*luaVM_local, -1) )
- return qlua_interrupt (luaVM_local, "init");
- return true;
- }
- qboolean qlua_doFile (lua_State **luaVM_local, char *scriptName ) {
- int old_currentInterruptedScript = currentInterruptedScript;
- lua_settop (*luaVM_local, 0);
- lua_getglobal (*luaVM_local, "selfID");
- currentInterruptedScript = (int)lua_tonumber(*luaVM_local, -1);
- lua_pop (*luaVM_local, 1);
- //load print as the error handler for printing any syntax errors found
- //during parsing
- lua_getglobal (*luaVM_local, "print");
- luaL_loadfile (*luaVM_local, scriptName);
- if (lua_pcall (*luaVM_local, 0, 0, 1)){
- Abuf_Execute(&(scripts[currentInterruptedScript-1]->cmd_console));
- currentInterruptedScript = old_currentInterruptedScript;
- return false;
- }
- strncpy (scripts[currentInterruptedScript-1]->scriptName, scriptName, 1024);
- currentInterruptedScript = old_currentInterruptedScript;
- lua_getglobal (*luaVM_local, "noinit");
- if (lua_isnil(*luaVM_local, -1) && !(int)lua_tonumber(*luaVM_local, -1) )
- return qlua_interrupt (luaVM_local, "init");
- return true;
- }
- void qlua_close (lua_State *luaVM_local) {
- lua_close (luaVM_local);
- }
- void qlua_init (void){
- const char *old_package_path;
- ldeveloper = Cvar_Get ("ldeveloper", "1", 0); //eventually will be 0
- luaVMShared = lua_open();
- luaL_openlibs (luaVMShared);
- //add the "require" path
- lua_getglobal ( luaVMShared, "package" );
- lua_getfield ( luaVMShared, -1, "path" );
- old_package_path = lua_tostring ( luaVMShared, -1 );
- retassert( lua_pushfstring ( luaVMShared,
- "%s;data1/lua/?;./data1/lua/?.lua;./arena/lua/?;./arena/lua/?.lua;"
- "./data1/lua/include/?;./data1/lua/include/?.lua;"
- "./arena/lua/include/?;./arena/lua/include/?.lua;"
- "./data1/lua/auxlib/?;./data1/lua/auxlib/?.lua;"
- "./arena/lua/auxlib/?;./arena/lua/auxlib/?.lua;"
- "./data1/lua/sys/?;./data1/lua/sys/?.lua;", //no arena/sys!
- old_package_path ) );
- lua_setfield ( luaVMShared, -3, "path" );
- luaL_loadfile ( luaVMShared, "data1/lua/sys/memoizing_deepcopy.lua" );
- if (lua_pcall ( luaVMShared, 0, 0, 0))
- fprintf (stderr, "error loading memoizing deep copy!\n");
- lua_newtable (luaVMShared);
- lua_setglobal (luaVMShared, "sharedTable");
- lua_newtable (luaVMShared);
- lua_setglobal (luaVMShared, "states");
- qlua_initPcallThread ();
- }
- void qlua_shutdown (void){
- lua_close (luaVMShared);
- qlua_shutdownPcallThread ();
- }
Add Comment
Please, Sign In to add comment