lua-users home
lua-l archive

Re: Throwback

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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 ... )

AltStyle によって変換されたページ (->オリジナル) /