Lunatic: print -> OSD_Printf, error reporting.

git-svn-id: https://svn.eduke32.com/eduke32@3319 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-12-25 16:13:41 +00:00
parent 255c84c5a2
commit 41bfa1b841
11 changed files with 147 additions and 18 deletions

View file

@ -19,6 +19,9 @@ typedef struct
void L_SetupDebugTraceback(lua_State *L);
void L_CheckAndRegisterFunction(lua_State *L, void *regkeyaddr);
// Callback on Lua error. <str> must be used immediately or strdup'd.
void (*L_ErrorFunc)(const char *str);
int L_CreateState(L_State *estate, const char *name, void (*StateSetupFunc)(lua_State *));
void L_DestroyState(L_State *estate);
int L_RunOnce(L_State *estate, const char *fn);

View file

@ -112,6 +112,7 @@ void L_DestroyState(L_State *estate)
estate->L = NULL;
}
void (*L_ErrorFunc)(const char *) = NULL;
int L_RunString(L_State *estate, char *buf, int dofreebuf)
{
@ -139,7 +140,7 @@ int L_RunString(L_State *estate, char *buf, int dofreebuf)
if (i == LUA_ERRSYNTAX)
{
OSD_Printf("state \"%s\" syntax error: %s\n", estate->name,
OSD_Printf(OSD_ERROR "state \"%s\" syntax error: %s\n", estate->name,
lua_tostring(L, -1)); // get err msg
lua_pop(L, 2); // pop errmsg and debug.traceback
return 3;
@ -159,11 +160,13 @@ int L_RunString(L_State *estate, char *buf, int dofreebuf)
if (i == LUA_ERRRUN)
{
int32_t stringp = (lua_type(L, -1)==LUA_TSTRING);
// get error message if possible
OSD_Printf("state \"%s\" runtime error: %s\n", estate->name,
stringp ? lua_tostring(L, -1) : "??? (errmsg not a string)");
const char *errstr = (lua_type(L, -1)==LUA_TSTRING) ?
lua_tostring(L, -1) : "??? (errmsg not a string)";
OSD_Printf(OSD_ERROR "state \"%s\" runtime error: %s\n", estate->name, errstr);
if (L_ErrorFunc)
L_ErrorFunc(errstr);
lua_pop(L, 2); // pop errmsg and debug.traceback
return 4;
}

View file

@ -3013,6 +3013,10 @@ void G_DisplayRest(int32_t smoothratio)
if (g_Debug)
G_ShowCacheLocks();
#ifdef LUNATIC
El_DisplayErrors();
#endif
if (VOLUMEONE)
{
if (ud.show_help == 0 && g_showShareware > 0 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)

View file

@ -20,10 +20,8 @@ local rawset = rawset
local setmetatable = setmetatable
local setfenv = setfenv
local tonumber = tonumber
local type = type
local print = print
local tostring = tostring
local type = type
--== First, load the definitions common to the game's and editor's Lua interface.
@ -61,6 +59,10 @@ local cansee = defs_c.cansee
local strip_const = defs_c.strip_const
local setmtonce = defs_c.setmtonce
-- Must be after loading "defs_common" which redefines "print" to use
-- OSD_Printf()
local print = print
---=== EDuke32 game definitions ===---
@ -963,7 +965,7 @@ G_.error = our_error
G_.ipairs = ipairs
G_.pairs = pairs
G_.pcall = pcall
G_.print = print -- TODO: --> initprintf or OSD_Printf; why not needed on linux?
G_.print = print
G_.module = our_module
G_.next = next
G_.require = our_require

View file

@ -16,6 +16,15 @@ local setmetatable = setmetatable
local decl = decl
local getfenv = getfenv
decl "void OSD_Printf(const char *fmt, ...);"
print = function(str)
str = tostring(str)
if (type(str) ~= "string") then
error("invalid argument to print: must be convertible to a string")
end
ffiC.OSD_Printf("%s\n", str)
end
local print=print

View file

@ -44,6 +44,7 @@ updatesectorz;
updatesectorbreadth;
gethitickms;
OSD_Printf;

View file

@ -44,6 +44,7 @@ updatesectorz;
updatesectorbreadth;
gethitickms;
OSD_Printf;

View file

@ -5,6 +5,8 @@
#include <lualib.h>
#include <lauxlib.h>
#include "build.h" // printext256
#include "lunatic_game.h"
#include "osd.h"
@ -101,6 +103,92 @@ void El_PrintTimes(void)
OSD_Printf(" },\n}\n");
}
////////// ERROR REPORTING //////////
#define EL_MAXERRORS 2
static int32_t el_numErrors=0, el_tooMuchErrors;
static char *el_errorMsgs[EL_MAXERRORS];
// Compare against all other error messages.
// Strictly seen, this is quadratic-time, but EL_MAXERRORS is small and
// errors should be fixed anyway.
static int32_t cmp_against_others(const char *str, int32_t slen)
{
int32_t i;
for (i=0; i<el_numErrors; i++)
if (!Bstrncmp(str, el_errorMsgs[i], slen))
return 1;
return 0;
}
static void El_OnError(const char *str)
{
if (!el_tooMuchErrors)
{
char *errstr = NULL;
const char *nl = Bstrchr(str, '\n');
// First, check whether the error message matches an already saved one
if (nl)
{
// cut off string after the newline
if (cmp_against_others(str, nl-str))
return;
}
else
{
// save string fully
if (cmp_against_others(str, Bstrlen(str)))
return;
}
// If the (EL_MAXERRORS+1)'th distinct error appeared, we have too many.
if (el_numErrors==EL_MAXERRORS)
{
el_tooMuchErrors = 1;
return;
}
// Otherwise, allocate storage for the potentially clipped error string...
if (nl)
{
errstr = Bmalloc(nl-str+1);
if (errstr)
{
Bmemcpy(errstr, str, nl-str);
errstr[nl-str] = 0;
}
}
else
{
errstr = Bstrdup(str);
}
// ...and save it:
if (errstr)
el_errorMsgs[el_numErrors++] = errstr;
}
}
void El_ClearErrors(void)
{
int32_t i;
for (i=0; i<EL_MAXERRORS; i++)
{
Bfree(el_errorMsgs[i]);
el_errorMsgs[i] = NULL;
}
el_numErrors = el_tooMuchErrors = 0;
}
void El_DisplayErrors(void)
{
int32_t i;
for (i=0; i<el_numErrors; i++)
printext256(8, 8+8*i, 242, 0, el_errorMsgs[i], 0);
if (el_tooMuchErrors)
printext256(8, 8+8*EL_MAXERRORS, 242, 0, "(more distinct errors ...)", 0);
}
////////// STATE CREATION/DESTRUCTIION //////////
@ -124,6 +212,8 @@ static void El_StateSetup(lua_State *L)
// 0: success, <0: failure
int32_t El_CreateState(L_State *estate, const char *name)
{
L_ErrorFunc = El_OnError;
return L_CreateState(estate, name, &El_StateSetup);
}
@ -223,15 +313,20 @@ int32_t El_CallEvent(L_State *estate, int32_t eventidx, int32_t iActor, int32_t
if (i == LUA_ERRRUN)
{
const char *errstr;
if (lua_isboolean(L, -1))
{
lua_pop(L, 1);
return 0;
}
errstr = lua_tostring(L, -1);
Bassert(lua_type(L, -1)==LUA_TSTRING);
OSD_Printf("event \"%s\" (state \"%s\") runtime error: %s\n", EventNames[eventidx],
estate->name, lua_tostring(L, -1)); // get err msg
OSD_Printf(OSD_ERROR "event \"%s\" (state \"%s\") runtime error: %s\n",
EventNames[eventidx], estate->name, errstr);
if (L_ErrorFunc)
L_ErrorFunc(errstr);
lua_pop(L, 1);
return -1;
}
@ -247,6 +342,8 @@ int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t
if (i == LUA_ERRRUN)
{
const char *errstr;
if (lua_isboolean(L, -1))
{
int32_t killit = lua_toboolean(L, -1);
@ -255,8 +352,11 @@ int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t
}
Bassert(lua_type(L, -1)==LUA_TSTRING);
OSD_Printf("actor %d (sprite %d, state \"%s\") runtime error: %s\n", actortile, iActor,
estate->name, lua_tostring(L, -1)); // get err msg
errstr = lua_tostring(L, -1);
OSD_Printf(OSD_ERROR "actor %d (sprite %d, state \"%s\") runtime error: %s\n",
actortile, iActor, estate->name, errstr);
if (L_ErrorFunc)
L_ErrorFunc(errstr);
lua_pop(L, 1);
return -1;
}

View file

@ -28,6 +28,9 @@ extern double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES];
// -- functions --
void El_PrintTimes(void);
void El_ClearErrors(void);
void El_DisplayErrors(void);
int32_t El_CreateState(L_State *estate, const char *name);
void El_DestroyState(L_State *estate);

View file

@ -16,12 +16,13 @@ end
local function checkfail(funcstr, expectedmsg)
local status, errmsg = pcall(DBG_.loadstring(funcstr))
if (status) then
print('ERROR: '..funcstr.." DIDN'T fail")
print('^21ERROR:^O '..funcstr.." DIDN'T fail")
else
if (expectedmsg==nil or string.find(errmsg, expectedmsg, 1, true)) then
print('SUCCESS: '..funcstr.." failed: "..errmsg)
print("^11SUCCESS:^O "..funcstr.." failed: "..errmsg)
else
print('ERROR*: '..funcstr.." failed: "..errmsg..
-- XXX: beginning with "^10" is counted as error in OSD_Printf()
print("^10ERROR*:^O "..funcstr.." failed: "..errmsg..
", but expected error message was: "..expectedmsg)
end
end
@ -182,13 +183,14 @@ checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table
-- the cdata returned by player[] can't be made into a pointer!
checkfail("do local pl=player[0]; i=pl[1]; end")
checkfail("do local ud=gv.ud.camera; end", "dummy variable: read access forbidden") -- test for proper decl()
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnum")
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnums")
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
gameevent(gv.EVENT_JUMP,
function(actori, playeri, dist)
printf("jump i=%d p=%d d=%d", actori, playeri, dist)
error("greetings from EVENT_JUMP")
end
)
@ -263,6 +265,7 @@ gameactor(1680, TROOPSTRENGTH, "TROOPSTAND", -- LIZTROOP
if (hs.n == 300) then
printf("hitscan: %s", tostring(hs:getstats()))
hs:reset()
error("greetings from LIZTROOP actor")
end
if (dist < 4096) then

View file

@ -1371,7 +1371,7 @@ static inline void prelevel(char g)
{
i = L_RunOnce(&g_ElState, "test.elua");
if (i)
OSD_Printf("Error running the test ELua script (code %d)\n", i);
OSD_Printf(OSD_ERROR "Error running the test ELua script (code %d)\n", i);
else
initprintf("ELua test script run ok!\n");
}