[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Throwback
- From: Sean Conner <sean@...>
- Date: Wed, 13 May 2015 03:00:33 -0400
It was thus said that the Great Gavin Wraith once stated:
> I was pleased to get an email from a man who wanted to introduce
> his son to programming using Lua. He ended his email with:
>
> > Anyway, my conclusion is this would be a good way to introduce my son to
> > programming, but the main obstacle is the debugging! Throwback into the
> > editor would be ideal, if that could be arranged.
>
> RISC OS has a module, DDEUtils, which makes throwback very straightforward.
> To use it, I need to define a function with a prototype
>
> void throw (const char *filename, int linenumber, const char *message);
>
> This I have done (using ARM assembler) and tested. I get a window
> opening showing the message, which when clicked on opens the file
> specified by filename at line number linenumber. OK so far.
>
> I have been going through the Lua sources trying to understand what
> happens when an error is raised. The difficulty, from my point of
> view, is that the various error functions appear to be simply concatenating
> lots of error messages. But I need an error datatype
>
> typedef struct err {
> char *filename; int linenumber; char *message; } err;
>
> not just char *message;. I need to extract the requisite filename and
> linenumber. Am I trying to squeeze my big foot into a glass slipper here?
> Any helpful tips would be much appreciated.
It's not hard, but it's hard to explain. Let me try.
At work, I embed Lua within a larger application, and when calling the
main script (written in Lua), I do (basically):
lua_getglobal(L,"error_handler");
lua_getglobal(L,"main_function");
lua_pushinteger(L,1); /* some parameter to main_function() */
rc = lua_pcall(L,1,LUA_MULTRET,-2);
if (rc != 0)
{
/*--------------------------------------------
; an error happened; error_handler() was called. We can arrange
; to have it return what we need---see below. Rest of code
; deleted
;-------------------------------------------------
}
So I call the main script and funnel any errors to a handler. This can be
written in C (using the Lua API) or Lua. Anyway, the one I have is written
in Lua. In *that* function:
function error_handler(...)
{
local stack = {}
for i = 1 , 10 do
local info = debug.getinfo(i,"Si")
if not info then break end
table.insert(stack,string.format(" [%s(%d)]",info.source,info.currentline)
end
syslog('error',"stack=%s",table.concat(stack))
return ...
}
And in syslog(), I get:
stack= [@foo/src/ddt.lua(92)] [@foo/src/BAR/baz.lua(88)] [@foo/src/foo.lua(213)]
Line 92 of ddt.lua is error_handler(); the actual problem is in baz.lua on
line 88. So, if we change the error handler a bit:
function error_handler(errmsg)
{
-- --------------------------------------
-- 2nd entry on the call stack is were the error is.
-- grab the location
-- -----------------------------
local info = debug.getinfo(2,"Si")
-- ----------------------------------------
-- if so, return some addtional information about
-- the error (location) so we won't have to parse
-- it out of the error message.
-- ----------------------------------------
if info then
return errmsg,info.source:sub(2,-1),info.currentline
else
-- umm ... yeah ...
end
}
And going back to our C code above:
rc = lua_pcall(L,1,LUA_MULTRET,-2);
if (rc != 0)
{
throw(
lua_tostring(L,-1), /* the filename */
lua_tointeger(L,-2),/* the location */
lua_tostring(L,-3) /* the error message */
);
}
You could do everything in Lua (except for calling throw()). Assuming
there's a Lua function throw() (built using the C API) that does the actual
throw, in pure Lua, the only difference would be:
-- we can use the same error_handler() function as above
okay,a,b,c = xpcall(function() main_function(1) end,error_handler)
if not okay then
throw(a,b,c)
end
I think this is enough information to get you going.
-spc (I hope ... )