| 571 | } |
| 572 | |
| 573 | static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = NULL) |
| 574 | { |
| 575 | if (!thread) |
| 576 | thread = L; |
| 577 | |
| 578 | if (thread == L) |
| 579 | lua_pushthread(L); |
| 580 | else |
| 581 | { |
| 582 | lua_pushthread(thread); |
| 583 | lua_xmove(thread, L, 1); |
| 584 | } |
| 585 | |
| 586 | lua_swap(L); |
| 587 | |
| 588 | int base = lua_gettop(L); |
| 589 | |
| 590 | bool force_unknown = false; |
| 591 | |
| 592 | if (lua_istable(L, base) && lua_getmetatable(L, base)) |
| 593 | { |
| 594 | lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_EXCEPTION_META_TOKEN); |
| 595 | bool is_exception = lua_rawequal(L, -1, -2); |
| 596 | lua_settop(L, base); |
| 597 | |
| 598 | if (is_exception) |
| 599 | { |
| 600 | // If it is an exception from the same thread, return as is |
| 601 | lua_getfield(L, base, "thread"); |
| 602 | bool same_thread = lua_rawequal(L, -1, base-1); |
| 603 | lua_settop(L, base); |
| 604 | |
| 605 | if (same_thread) |
| 606 | { |
| 607 | lua_remove(L, base-1); |
| 608 | return false; |
| 609 | } |
| 610 | |
| 611 | // Create a new exception for this thread |
| 612 | lua_newtable(L); |
| 613 | luaL_where(L, slevel); |
| 614 | lua_setfield(L, -2, "where"); |
| 615 | lua_pushstring(L, "coroutine resume failed"); |
| 616 | lua_setfield(L, -2, "message"); |
| 617 | lua_getfield(L, -2, "verbose"); |
| 618 | lua_setfield(L, -2, "verbose"); |
| 619 | lua_swap(L); |
| 620 | lua_setfield(L, -2, "cause"); |
| 621 | } |
| 622 | else |
| 623 | force_unknown = true; |
| 624 | } |
| 625 | |
| 626 | // Promote non-table to table, and do some sanity checks |
| 627 | if (!lua_istable(L, base) || force_unknown) |
| 628 | { |
| 629 | lua_newtable(L); |
| 630 | lua_swap(L); |
no test coverage detected