| 1466 | } |
| 1467 | |
| 1468 | static int BacktraceErrorHandler(lua_State *m_state) { |
| 1469 | lua_createtable(m_state, 0, 2); |
| 1470 | |
| 1471 | // First, generate traceback BEFORE we modify the stack |
| 1472 | // We need to do this first because GetLuaTraceback expects string errors |
| 1473 | char traceback[1024]; |
| 1474 | traceback[0] = '\0'; // Initialize the buffer |
| 1475 | LuaCallstackCtx ctx; |
| 1476 | ctx.m_First = true; |
| 1477 | ctx.m_Buffer = traceback; |
| 1478 | ctx.m_BufferSize = sizeof(traceback); |
| 1479 | |
| 1480 | // If error is not a string, temporarily convert it for traceback generation |
| 1481 | if (!lua_isstring(m_state, 1)) |
| 1482 | { |
| 1483 | // Replace stack position 1 with string version for GetLuaTraceback |
| 1484 | lua_getglobal(m_state, "tostring"); |
| 1485 | if (lua_isfunction(m_state, -1)) |
| 1486 | { |
| 1487 | lua_pushvalue(m_state, 1); // Push the original error value |
| 1488 | int result = lua_pcall(m_state, 1, 1, 0); |
| 1489 | if (result == 0 && lua_isstring(m_state, -1)) |
| 1490 | { |
| 1491 | lua_replace(m_state, 1); // Replace original error with string version |
| 1492 | } |
| 1493 | else |
| 1494 | { |
| 1495 | lua_pop(m_state, 1); // Remove failed result |
| 1496 | const char* type_name = lua_typename(m_state, lua_type(m_state, 1)); |
| 1497 | lua_pushfstring(m_state, "(%s)", type_name); |
| 1498 | lua_replace(m_state, 1); // Replace with type name |
| 1499 | } |
| 1500 | } |
| 1501 | else |
| 1502 | { |
| 1503 | lua_pop(m_state, 1); // Remove non-function value |
| 1504 | const char* type_name = lua_typename(m_state, lua_type(m_state, 1)); |
| 1505 | lua_pushfstring(m_state, "(%s)", type_name); |
| 1506 | lua_replace(m_state, 1); // Replace with type name |
| 1507 | } |
| 1508 | } |
| 1509 | |
| 1510 | // Now generate traceback with string error message |
| 1511 | dmScript::GetLuaTraceback(m_state, "Sln", GetLuaStackTraceCbk, &ctx); |
| 1512 | |
| 1513 | // Store the converted error message |
| 1514 | lua_pushvalue(m_state, 1); |
| 1515 | lua_setfield(m_state, -2, "error"); |
| 1516 | |
| 1517 | // Store the traceback |
| 1518 | lua_pushstring(m_state, traceback); |
| 1519 | lua_setfield(m_state, -2, "traceback"); |
| 1520 | |
| 1521 | return 1; |
| 1522 | } |
| 1523 | |
| 1524 | static int PCallInternal(lua_State* L, int nargs, int nresult, int in_error_handler) { |
| 1525 | lua_pushcfunction(L, BacktraceErrorHandler); |
nothing calls this directly
no test coverage detected