示例#1
0
int do_pcall_with_traceback(
    lua_State * L,
    int narg,
    int nresults,
    BOOL is_async /* Hackish. This may be too specific to lua-alchemy. */
  )
{
  /* WARNING: Panic alert! Use L*_FN checkers here! */

  SPAM((
      "do_pcall_with_traceback(): begin (%s)", (is_async) ? "async" : "sync"
    ));

  LCALL_ARGS(L, stack, 1 + narg); /* The function itself with arguments */
  int status = 0;

  BOOL old_async = set_async_state(L, is_async);

  lua_pushcfunction(L, db_errorfb);  /* push traceback function */
  lua_insert(L, LBASE(L, stack));  /* put it under chunk and args */

  LCHECK_FN(L, stack, 1 + narg + 1, fatal_error);

  SPAM(("do_pcall_with_traceback(): before call"));

  status = lua_pcall(L, narg, nresults, LBASE(L, stack));

  lua_remove(L, LBASE(L, stack));  /* remove traceback function */

  set_async_state(L, old_async);

  if (status != 0)
  {
    SPAM(("do_pcall_with_traceback(): after call ERROR"));

    /* force a complete garbage collection in case of errors */
    lua_gc(L, LUA_GCCOLLECT, 0);

    LCHECK_FN(L, stack, 1, fatal_error);
  }
  else
  {
    SPAM(("do_pcall_with_traceback(): after call OK"));

    if (nresults != LUA_MULTRET)
    {
      LCHECK_FN(L, stack, nresults, fatal_error);
    }
  }

  SPAM(("do_pcall_with_traceback(): end"));

  return status;
}
示例#2
0
/*
* Create an ActionScript value from the lua stack starting
* at index start and ending at index end.  If collapse_array == 1,
* an empty return will be transformed into AS3_Undefined() and a
* return of length 1 will just return the specific value.
* Otherwise an array is returned.
*/
AS3_Val create_as3_value_from_lua_stack(
    lua_State * L,
    int start,
    int end,
    BOOL collapse_array
  )
{
  /* WARNING: Panic alert! Use L*_FN checkers here! */

  LCALL(L, stack);
  AS3_Val ret;

  SPAM(("create_as3_value_from_lua_stack(): begin"));

  if (collapse_array == TRUE && start > end)
  {
    ret = AS3_Null();
  }
  else if (collapse_array == TRUE && start == end)
  {
    ret = get_as3_value_from_lua_stack(L, start);
  }
  else
  {
    int i;

    ret = AS3_Array("");
    for (i = start; i <= end; ++i)
    {
      AS3_Val value;
      AS3_Val r;

      /*SPAM(("create_as3_value_from_lua_stack() + 1 begin"));*/

      value = get_as3_value_from_lua_stack(L, i);
      r = AS3_CallTS("push", ret, "AS3ValType", value);
      SAFE_RELEASE(r); /* Ignoring result */

      SAFE_RELEASE(value);

      /*SPAM(("create_as3_value_from_lua_stack() + 1 end"));*/
    }
  }

#ifdef DO_SPAM
  SPAM(("create_as3_value_from_lua_stack(): end"));
  AS3_Trace(
      AS3_Call(
          getQualifiedClassName_method, NULL, AS3_Array("AS3ValType", ret)
        )
    );
#endif /* DO_SPAM */

  LCHECK_FN(L, stack, 0, fatal_error);

  return ret;
}
示例#3
0
/*
* Take the Lua stack item at index i and convert it into an
* ActionScript value.
*/
AS3_Val get_as3_value_from_lua_stack_type(lua_State * L, int i, int type)
{
  /* WARNING: Panic alert! Use L*_FN checkers here! */

  LCALL(L, stack);

  AS3_Val value;
  switch (type)
  {
    case LUA_TSTRING:  /* strings */
      {
        size_t length = 0;
        const char * str = lua_tolstring(L, i, &length);
        if (str == NULL)  /* NOTE: This is unreachable. Assert instead */
        {
          length = 6;
          str = "(null)";
        }
        /* NOTE: Alchemy .5a truncates embedded zeroes in string
        * regardless to the passed length
        */
        value = AS3_StringN(str, length);
      }
      break;

    case LUA_TBOOLEAN:  /* booleans */
      value = lua_toboolean(L, i) ? AS3_True() : AS3_False();
      break;

    case LUA_TNUMBER:  /* numbers */
      value = AS3_Number(lua_tonumber(L, i));
      break;

    case LUA_TNONE: /* fall through */
    case LUA_TNIL:  /* nil */
      value = AS3_Null();
      break;

    case LUA_TUSERDATA:  /* userdata */
      {
        void * userdata = lua_touserdata(L, i);
        lua_getfield(L, LUA_REGISTRYINDEX, AS3LUA_METATABLE);
        if (userdata == NULL || !lua_getmetatable(L, i))
        {
          lua_pop(L, 1); /* Pop AS3LUA_METATABLE */
          value = as3_value_from_foreign_userdata(L, i);
        }
        else if (!lua_rawequal(L, -2, -1))
        {
          lua_pop(L, 2); /* Pop AS3LUA_METATABLE and userdata metatable */
          value = as3_value_from_foreign_userdata(L, i);
        }
        else
        {
          lua_pop(L, 2); /* Pop AS3LUA_METATABLE and userdata metatable */
          AS3LuaUserData * userdata = (AS3LuaUserData *)lua_touserdata(L, i);
          value = userdata->value;
          /*
          * We just created one more reference to the AS3 value,
          * as it still lives inside Lua.
          * (And will probably be collected by GC.)
          */
          AS3_Acquire(value);
        }
      }
      break;

    case LUA_TFUNCTION: /* function */
      value = setup_callback(L, i);
      break;

    case LUA_TLIGHTUSERDATA: /* TODO: blackbox this type */
    case LUA_TTABLE: /* TODO: deal with this type */
    case LUA_TTHREAD: /* TODO: blackbox this type */
      value = AS3_String(lua_typename(L, type));
      break;

    default:  /* unreachable */
      fatal_error("unknown Lua type");
      break;
  }

#ifdef DO_SPAM
  SPAM(("get_as3_value_from_lua_stack(): end"));
  AS3_Trace(
      AS3_Call(
          getQualifiedClassName_method, NULL, AS3_Array("AS3ValType", value)
        )
    );
#endif /* DO_SPAM */

  LCHECK_FN(L, stack, 0, fatal_error);

  return value;
}
示例#4
0
/*
* Function used as a callback for all Lua functions passed through
* get_as3_value_from_lua_stack()
*/
AS3_Val as3_lua_callback(void * data, AS3_Val args)
{
  /* WARNING: Panic alert! Use L*_FN checkers here! */

  SPAM(("as3_lua_callback(): begin"));

  AS3_Val res;
  LuaFunctionCallbackData * func_data = (LuaFunctionCallbackData *) data;
  int nargs = 0;
  int status = 0;
  int results_base = 0;
  lua_State * L = func_data->L;
  if (L == NULL)
  {
    /* TODO: Should we crash here?
    fatal_error("state expired"); / * Does not return * /
    */
    sztrace("as3_lua_callback: state expired");
    return AS3_Undefined();
  }

  { /* A new scope for LCALL to work (C89 conformance) */
    LCALL(L, stack);

    /* TODO: Cache that with lua_ref, it is faster */
    lua_getfield(L, LUA_REGISTRYINDEX, AS3LUA_CALLBACKS);

    /* TODO: Assert we have a table here */

    lua_rawgeti(L, -1, func_data->ref); /* push stored function */

    if (lua_istable(L, -1) == 0) /* Probably nil */
    {
      lua_pop(L, 1); /* Pop bad callback table */
      LCHECK_FN(L, stack, 0, fatal_error);

      fatal_error("function callback not found"); /* Does not return */
    }

    lua_rawgeti(L, -1, AS3LUA_CBFNINDEX); /* push stored callback function */

 #ifdef DO_SPAM
  {
    SPAM(("as3_lua_callback(): AS3 arguments"));
    AS3_Val a = AS3_CallS("join", args, AS3_Undefined());
    AS3_Trace(a);
    SAFE_RELEASE(a);
  }
#endif /* DO_SPAM */


    /* TODO: Assert we have Lua function (or other callable object) on the top of the stack */

    LCHECK_FN(L, stack, 2 + 1, fatal_error);

    nargs = push_as3_array_to_lua_stack(L, args); /* push arguments */

#ifdef DO_SPAM
    /* TODO: Remove */
    lua_pushcfunction(L, as3_trace);
    dump_lua_stack(L, LBASE(L, stack) + 2 + 1);
    lua_pushliteral(L, "ARGUMENTS");
    lua_pushnumber(L, nargs);
    lua_call(L, 3, 0);
#endif /* DO_SPAM */

    LCHECK_FN(L, stack, 2 + 1 + nargs, fatal_error);

    results_base = LBASE(L, stack) + 2;
    status = do_pcall_with_traceback(L, nargs, LUA_MULTRET);
    if (status != 0)
    {
      const char * msg = NULL;

      LCHECK_FN(L, stack, 2 + 1, fatal_error); /* Tables and error message */
      lua_remove(L, -2); /* Remove AS3LUA_CALLBACKS table */
      lua_remove(L, -2); /* Remove holder table */
      LCHECK_FN(L, stack, 1, fatal_error); /* Only error message */

      /* Error message is on stack */
      /* NOTE: It is not necessary string! If we want to preserve its type, see lua_DoString. */

      if (lua_tostring(L, -1) == NULL)
      {
        lua_pop(L, 1);
        lua_pushliteral(L, "(non-string)");
      }

      LCHECK_FN(L, stack, 1, fatal_error);

      lua_pushliteral(L, "Error in Lua callback:\n");
      lua_insert(L, -2);

      LCHECK_FN(L, stack, 2, fatal_error);

      lua_concat(L, 2);

      LCHECK_FN(L, stack, 1, fatal_error);

      sztrace((char *)lua_tostring(L, -1));

      /* TODO: ?! */
      /* lua_error(L); */

      msg = lua_tostring(L, -1);
      lua_pop(L, 1);

/*
      fatal_error(msg); / * Does not return * /
*/
    }

    /* Process results */

#ifdef DO_SPAM
    /* TODO: Remove */
    /*
    lua_pushcfunction(L, as3_trace);
    lua_pushliteral(L, "STACK");
    dump_lua_stack(L, results_base);
    lua_call(L, 2, 0);
    */
#endif /* DO_SPAM */

    res = create_as3_value_from_lua_stack(L, results_base + 1, LTOP(L, stack), TRUE);

#ifdef DO_SPAM
    SPAM(("as3_lua_callback() result type"));
    AS3_Trace(AS3_Call(getQualifiedClassName_method, NULL, AS3_Array("AS3ValType", res)));
#endif /* DO_SPAM */

    lua_settop(L, LBASE(L, stack)); /* Cleanup results and two holder tables */

    SPAM(("as3_lua_callback(): end"));

    return res;
  }

  /* Unreachable */
}