/*
** $Id:$
** C++ version of luaD_protected_run and luaD_break_run.
** Written by Michael Cuddy (mcuddy@fensende.com), based on functions
** in ldo.c
**
** All rights to derived work ceded to original copyright holder.
**
** See Copyright Notice in lua.h
*/
#ifdef THROW_INSTEAD_OF_LONGJMP

#ifndef __cplusplus
#error "try compiling ldoxx.cpp with a C++ compiler"
#endif /* __cplusplus */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern "C" {
#include "lua.h"
#include "lvm.h"
};

class lua_exception {
	int status;
public:
	lua_exception(int status_) : status(status_) { };
	int get_status() { return status; }
};

// XXX -- hack, this function shouldn't be here, it's duplicated from
// ldo.c, where it's declared static.
static void restore_stack_limit (lua_State *L) {
  if (L->top - L->stack < L->stacksize - 1)
    L->stack_last = L->stack + (L->stacksize-1);
}

extern "C" void luaD_breakrun (lua_State *L, int errcode) {
  throw lua_exception(errcode);
}

extern "C" int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
  StkId oldCbase = L->Cbase;
  StkId oldtop = L->top;
  int allowhooks = L->allowhooks;
  int status = 0;
  try {
    (*f)(L, ud);
  } catch (lua_exception &e) {  /* an error occurred: restore the state */
    status = e.get_status();
    L->allowhooks = allowhooks;
    L->Cbase = oldCbase;
    L->top = oldtop;
    restore_stack_limit(L);
  }
  return status;
}

/* }====================================================== */

#endif /* THROW_INSTEAD_OF_LONGJMP */
