From d68b1144b8dd1514e63372103e05db4af1903c57 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 15 Oct 2013 12:05:09 +0200 Subject: [PATCH] Nasal: recursive method calling. New functions naCallMethodCtx and naCallMethod to replace NasalSystem::callMethod from FlightGear. This has just added an unneeded level of indirection and fits better directly into Nasal. naSetErrorHandler can be used to register an error handler/logging function. --- simgear/nasal/code.c | 48 +++++++++++++++++++++++++++++++++++++++++++ simgear/nasal/nasal.h | 22 ++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/simgear/nasal/code.c b/simgear/nasal/code.c index bac8b92b..395a3cdd 100644 --- a/simgear/nasal/code.c +++ b/simgear/nasal/code.c @@ -936,3 +936,51 @@ naRef naContinue(naContext ctx) if(!ctx->callParent) naModUnlock(); return result; } + +static void logError(naContext ctx) +{ + int i; + printf("logError\n"); + printf("Nasal runtime error: %s\n", naGetError(ctx)); + printf(" at %s\n", naStr_data(naGetSourceFile(ctx, 0))); + printf(", line %d\n", naGetLine(ctx, 0)); + for(i = 1; i < naStackDepth(ctx); ++i ) + printf( " called from: %s, line %d", + naStr_data(naGetSourceFile(ctx, i)), + naGetLine(ctx, i)); +} + +static naErrorHandler error_handler = &logError; +naErrorHandler naSetErrorHandler(naErrorHandler cb) +{ + naErrorHandler old_handler = error_handler; + error_handler = cb; + return old_handler; +} + +static int call_count = 0; +naRef naCallMethodCtx( naContext ctx, + naRef code, + naRef self, + int argc, + naRef* args, + naRef locals ) +{ + naRef result; + if(call_count) naModUnlock(); + call_count++; + result = naCall(ctx, code, argc, args, self, locals); + if(naGetError(ctx) && error_handler) + error_handler(ctx); + call_count--; + if(call_count) naModLock(); + return result; +} + +naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals) +{ + naContext ctx = naNewContext(); + naRef result = naCallMethodCtx(ctx, code, self, argc, args, locals); + naFreeContext(ctx); + return result; +} diff --git a/simgear/nasal/nasal.h b/simgear/nasal/nasal.h index 0464c94c..ba7947fc 100644 --- a/simgear/nasal/nasal.h +++ b/simgear/nasal/nasal.h @@ -103,6 +103,28 @@ naRef naCall(naContext ctx, naRef func, int argc, naRef* args, // naModUnlock() first if the lock is already held. naRef naContinue(naContext ctx); +// Does a naCall() in a given context. Wrapped here to make lock +// tracking easier. Extension functions are called with the lock, but +// we have to release it before making a new naCall(). So rather than +// drop the lock in every extension function that might call back into +// Nasal, we keep a stack depth counter here and only unlock/lock +// around the naCall if it isn't the first one. +naRef naCallMethodCtx( naContext ctx, + naRef code, + naRef self, + int argc, + naRef* args, + naRef locals ); + +// Same as naCallMethodCtx but creates (and afterwards destroyes) a new context +naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals); + +typedef void (*naErrorHandler)(naContext); + +// Register a handler to be called if an error is raised during the execution of +// naCallMethodCtx or naCallMethod. +naErrorHandler naSetErrorHandler(naErrorHandler cb); + // Throw an error from the current call stack. This function makes a // longjmp call to a handler in naCall() and DOES NOT RETURN. It is // intended for use in library code that cannot otherwise report an -- 2.39.5