mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-02 00:42:24 +00:00
AGS: cc_error returns stack from all script threads
From upstream 9e76800d668d8d0af7d47d815e6d1b781c7601f6
This commit is contained in:
parent
16d0d89787
commit
8e132f7b3f
@ -1675,7 +1675,7 @@ void prepare_room_sprites() {
|
||||
|
||||
if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
|
||||
for (int wb = 1 /* 0 is "no area" */;
|
||||
(wb < MAX_WALK_BEHINDS) && (wb < _GP(walkbehindobj).size()); ++wb) {
|
||||
(wb < MAX_WALK_BEHINDS) && (wb < (int)_GP(walkbehindobj).size()); ++wb) {
|
||||
const auto &wbobj = _GP(walkbehindobj)[wb];
|
||||
if (wbobj.Ddb) {
|
||||
add_to_sprite_list(wbobj.Ddb, wbobj.Pos.X, wbobj.Pos.Y,
|
||||
|
@ -315,24 +315,13 @@ void debug_script_log(const char *msg, ...) {
|
||||
debug_script_print_impl(full_msg, kDbgMsg_Debug);
|
||||
}
|
||||
|
||||
|
||||
String get_cur_script(int numberOfLinesOfCallStack) {
|
||||
String callstack;
|
||||
ccInstance *sci = ccInstance::GetCurrentInstance();
|
||||
if (sci)
|
||||
callstack = sci->GetCallStack(numberOfLinesOfCallStack);
|
||||
if (callstack.IsEmpty())
|
||||
callstack = cc_get_error().CallStack;
|
||||
return callstack;
|
||||
}
|
||||
|
||||
struct Breakpoint {
|
||||
char scriptName[80];
|
||||
int lineNumber;
|
||||
};
|
||||
|
||||
bool send_message_to_editor(const char *msg, const char *errorMsg) {
|
||||
String callStack = get_cur_script(25);
|
||||
String callStack = cc_get_error().CallStack;
|
||||
if (callStack.IsEmpty())
|
||||
return false;
|
||||
|
||||
|
@ -32,8 +32,6 @@ struct ScriptPosition;
|
||||
int check_for_messages_from_editor();
|
||||
bool send_message_to_editor(const char *msg);
|
||||
bool send_exception_to_editor(const char *qmsg);
|
||||
// Returns current script's location and callstack
|
||||
AGS::Shared::String get_cur_script(int numberOfLinesOfCallStack);
|
||||
void check_debug_keys();
|
||||
|
||||
#define DBG_NOIFACE 1
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "ags/engine/platform/base/ags_platform_driver.h"
|
||||
#include "ags/engine/platform/base/sys_main.h"
|
||||
#include "ags/plugins/plugin_engine.h"
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/engine/media/audio/audio_system.h"
|
||||
#include "ags/globals.h"
|
||||
#include "ags/ags.h"
|
||||
@ -114,7 +115,7 @@ QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) {
|
||||
"(ACI version %s)\n\n", _G(EngineVersion).LongString.GetCStr());
|
||||
}
|
||||
|
||||
alertis.Append(get_cur_script(5));
|
||||
alertis.Append(cc_get_error().CallStack);
|
||||
|
||||
if (qreason != kQuit_UserAbort)
|
||||
alertis.Append("\nError: ");
|
||||
@ -125,7 +126,7 @@ QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) {
|
||||
qmsg++;
|
||||
alertis.Format("A warning has been generated. This is not normally fatal, but you have selected "
|
||||
"to treat warnings as errors.\n"
|
||||
"(ACI version %s)\n\n%s\n", _G(EngineVersion).LongString.GetCStr(), get_cur_script(5).GetCStr());
|
||||
"(ACI version %s)\n\n%s\n", _G(EngineVersion).LongString.GetCStr(), cc_get_error().CallStack.GetCStr());
|
||||
return kQuit_GameWarning;
|
||||
} else {
|
||||
alertis.Format("An internal error has occurred. Please note down the following information.\n"
|
||||
|
@ -157,6 +157,18 @@ const char *regnames[] = { "null", "sp", "mar", "ax", "bx", "cx", "op", "dx" };
|
||||
|
||||
const char *fixupnames[] = { "null", "fix_gldata", "fix_func", "fix_string", "fix_import", "fix_datadata", "fix_stack" };
|
||||
|
||||
String cc_get_callstack(int max_lines) {
|
||||
String callstack;
|
||||
for (auto sci = _GP(InstThreads).crbegin(); sci != _GP(InstThreads).crend(); ++sci) {
|
||||
if (callstack.IsEmpty())
|
||||
callstack.Append("in the active script:\n");
|
||||
else
|
||||
callstack.Append("in the waiting script:\n");
|
||||
callstack.Append((*sci)->GetCallStack(max_lines));
|
||||
}
|
||||
return callstack;
|
||||
}
|
||||
|
||||
// Function call stack is used to temporarily store
|
||||
// values before passing them to script function
|
||||
#define MAX_FUNC_PARAMS 20
|
||||
@ -181,7 +193,7 @@ struct FunctionCallStack {
|
||||
|
||||
|
||||
ccInstance *ccInstance::GetCurrentInstance() {
|
||||
return _GP(InstThreads).size() > 0 ? _GP(InstThreads).top() : nullptr;
|
||||
return _GP(InstThreads).size() > 0 ? _GP(InstThreads).back() : nullptr;
|
||||
}
|
||||
|
||||
ccInstance *ccInstance::CreateFromScript(PScript scri) {
|
||||
@ -335,14 +347,14 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
|
||||
}
|
||||
PushValueToStack(RuntimeScriptValue().SetInt32(0)); // return address on stack
|
||||
|
||||
_GP(InstThreads).push(this); // push instance thread
|
||||
_GP(InstThreads).push_back(this); // push instance thread
|
||||
runningInst = this;
|
||||
int reterr = Run(startat);
|
||||
// Cleanup before returning, even if error
|
||||
ASSERT_STACK_SIZE(numargs);
|
||||
PopValuesFromStack(numargs);
|
||||
pc = 0;
|
||||
_GP(InstThreads).pop(); // pop instance thread
|
||||
_GP(InstThreads).pop_back(); // pop instance thread
|
||||
if (reterr != 0)
|
||||
return reterr;
|
||||
|
||||
@ -1198,7 +1210,7 @@ int ccInstance::Run(int32_t curpc) {
|
||||
}
|
||||
}
|
||||
|
||||
String ccInstance::GetCallStack(int maxLines) {
|
||||
String ccInstance::GetCallStack(int maxLines) const {
|
||||
String buffer = String::FromFormat("in \"%s\", line %d\n", runningInst->instanceof->GetSectionName(pc), line_number);
|
||||
|
||||
int linesDone = 0;
|
||||
@ -1212,13 +1224,13 @@ String ccInstance::GetCallStack(int maxLines) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void ccInstance::GetScriptPosition(ScriptPosition &script_pos) {
|
||||
void ccInstance::GetScriptPosition(ScriptPosition &script_pos) const {
|
||||
script_pos.Section = runningInst->instanceof->GetSectionName(pc);
|
||||
script_pos.Line = line_number;
|
||||
}
|
||||
|
||||
// get a pointer to a variable or function exported by the script
|
||||
RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) {
|
||||
RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) const {
|
||||
int k;
|
||||
char altName[200];
|
||||
snprintf(altName, sizeof(altName), "%s$", symname);
|
||||
@ -1234,7 +1246,7 @@ RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) {
|
||||
return rval_null;
|
||||
}
|
||||
|
||||
void ccInstance::DumpInstruction(const ScriptOperation &op) {
|
||||
void ccInstance::DumpInstruction(const ScriptOperation &op) const {
|
||||
// line_num local var should be shared between all the instances
|
||||
static int line_num = 0;
|
||||
|
||||
|
@ -159,12 +159,12 @@ public:
|
||||
int CallScriptFunction(const char *funcname, int32_t num_params, const RuntimeScriptValue *params);
|
||||
|
||||
// Get the script's execution position and callstack as human-readable text
|
||||
Shared::String GetCallStack(int maxLines);
|
||||
Shared::String GetCallStack(int max_lines = INT_MAX) const;
|
||||
// Get the script's execution position
|
||||
void GetScriptPosition(ScriptPosition &script_pos);
|
||||
void GetScriptPosition(ScriptPosition &script_pos) const;
|
||||
// Get the address of an exported symbol (function or variable) in the script
|
||||
RuntimeScriptValue GetSymbolAddress(const char *symname);
|
||||
void DumpInstruction(const ScriptOperation &op);
|
||||
RuntimeScriptValue GetSymbolAddress(const char *symname) const;
|
||||
void DumpInstruction(const ScriptOperation &op) const;
|
||||
// Tells whether this instance is in the process of executing the byte-code
|
||||
bool IsBeingRun() const;
|
||||
|
||||
|
@ -564,7 +564,7 @@ void quit_with_script_error(const char *functionName) {
|
||||
quitprintf("!Error running function '%s':\n%s", functionName, error.ErrorString.GetCStr());
|
||||
else
|
||||
quitprintf("Error running function '%s':\n%s\n\n%s", functionName,
|
||||
error.ErrorString.GetCStr(), get_cur_script(5).GetCStr());
|
||||
error.ErrorString.GetCStr(), error.CallStack.GetCStr());
|
||||
}
|
||||
|
||||
int get_nivalue(InteractionCommandList *nic, int idx, int parm) {
|
||||
|
@ -1,63 +0,0 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Script Editor run-time engine component (c) 1998 Chris Jones
|
||||
// script chunk format:
|
||||
// 00h 1 dword version - should be 2
|
||||
// 04h 1 dword sizeof(scriptblock)
|
||||
// 08h 1 dword number of ScriptBlocks
|
||||
// 0Ch n STRUCTs ScriptBlocks
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "ags/lib/std/utility.h"
|
||||
#include "ags/engine/script/cc_instance.h"
|
||||
#include "ags/shared/script/cc_common.h"
|
||||
#include "ags/shared/util/file.h"
|
||||
#include "ags/shared/util/stream.h"
|
||||
#include "ags/globals.h"
|
||||
|
||||
namespace AGS3 {
|
||||
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
class RoomStruct;
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
|
||||
using namespace AGS::Shared;
|
||||
|
||||
std::pair<String, String> cc_error_at_line(const char *error_msg) {
|
||||
ccInstance *sci = ccInstance::GetCurrentInstance();
|
||||
if (!sci) {
|
||||
return std::make_pair(String::FromFormat("Error (line %d): %s", _G(currentline), error_msg), String());
|
||||
} else {
|
||||
return std::make_pair(String::FromFormat("Error: %s\n", error_msg), ccInstance::GetCurrentInstance()->GetCallStack(5));
|
||||
}
|
||||
}
|
||||
|
||||
String cc_error_without_line(const char *error_msg) {
|
||||
return String::FromFormat("Runtime error: %s", error_msg);
|
||||
}
|
||||
|
||||
} // namespace AGS3
|
@ -129,7 +129,7 @@ Globals::Globals() {
|
||||
_animbuts = new std::vector<AnimatingGUIButton>();
|
||||
|
||||
// cc_instance.cpp globals
|
||||
_InstThreads = new std::stack<ccInstance *>();
|
||||
_InstThreads = new std::deque<ccInstance *>();
|
||||
_GlobalReturnValue = new RuntimeScriptValue();
|
||||
|
||||
// cc_options.cpp globals
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "ags/shared/core/platform.h"
|
||||
#define AGS_PLATFORM_DEFINES_PSP_VARS (AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID)
|
||||
|
||||
#include "ags/lib/std/stack.h"
|
||||
#include "ags/lib/std/queue.h"
|
||||
#include "ags/shared/ac/game_version.h"
|
||||
#include "ags/shared/util/stdio_compat.h"
|
||||
#include "ags/shared/util/string.h"
|
||||
@ -369,7 +369,7 @@ public:
|
||||
// In AGS currently only one thread is running, others are waiting in the queue.
|
||||
// An example situation is repeatedly_execute_always callback running while
|
||||
// another instance is waiting at the blocking action or Wait().
|
||||
std::stack<ccInstance *> *_InstThreads;
|
||||
std::deque<ccInstance *> *_InstThreads;
|
||||
// [IKM] 2012-10-21:
|
||||
// NOTE: This is temporary solution (*sigh*, one of many) which allows certain
|
||||
// exported functions return value as a RuntimeScriptValue object;
|
||||
|
@ -63,6 +63,80 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class deque {
|
||||
private:
|
||||
vector<T> _intern;
|
||||
public:
|
||||
deque() = default;
|
||||
typedef typename vector<T>::iterator iterator;
|
||||
typedef typename const vector<T>::const_iterator const_iterator;
|
||||
typedef typename vector<T>::reverse_iterator reverse_iterator;
|
||||
typedef typename const vector<T>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
void clear() {
|
||||
_intern.clear();
|
||||
}
|
||||
void insert(const T &item) {
|
||||
_intern.push_back(item);
|
||||
}
|
||||
void push_back(const T &item) {
|
||||
_intern.push_back(item);
|
||||
}
|
||||
void push_front(const T &item) {
|
||||
_intern.push_front(item);
|
||||
}
|
||||
void pop_back() {
|
||||
_intern.pop_back();
|
||||
}
|
||||
void pop_front() {
|
||||
_intern.remove_at(0);
|
||||
}
|
||||
const T &front() const {
|
||||
return _intern.front();
|
||||
}
|
||||
const T &back() const {
|
||||
return _intern.back();
|
||||
}
|
||||
|
||||
void resize(size_t newSize) {
|
||||
_intern.resize(newSize);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return _intern.size();
|
||||
}
|
||||
|
||||
T at(size_t idx) {
|
||||
return _intern[idx];
|
||||
}
|
||||
|
||||
const_iterator cbegin() {
|
||||
return _intern.cbegin();
|
||||
}
|
||||
const_iterator cend() {
|
||||
return _intern.cend();
|
||||
}
|
||||
reverse_iterator rbegin() {
|
||||
return _intern.rbegin();
|
||||
}
|
||||
reverse_iterator rend() {
|
||||
return _intern.rend();
|
||||
}
|
||||
const_reverse_iterator rbegin() const {
|
||||
return _intern.rbegin();
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return _intern.rend();
|
||||
}
|
||||
const_reverse_iterator crbegin() const {
|
||||
return _intern.crbegin();
|
||||
}
|
||||
const_reverse_iterator crend() const {
|
||||
return _intern.crend();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
} // namespace AGS3
|
||||
|
||||
|
@ -279,7 +279,6 @@ MODULE_OBJS = \
|
||||
engine/script/runtime_script_value.o \
|
||||
engine/script/script.o \
|
||||
engine/script/script_api.o \
|
||||
engine/script/script_engine.o \
|
||||
engine/script/script_runtime.o \
|
||||
engine/script/system_imports.o \
|
||||
plugins/ags_plugin.o \
|
||||
|
@ -42,10 +42,8 @@ int ccGetOption(int optbit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns full script error message and callstack (if possible)
|
||||
extern std::pair<String, String> cc_error_at_line(const char *error_msg);
|
||||
// Returns script error message without location or callstack
|
||||
extern String cc_error_without_line(const char *error_msg);
|
||||
// Returns current running script callstack as a human-readable text
|
||||
extern String cc_get_callstack(int max_lines = INT_MAX);
|
||||
|
||||
void cc_clear_error() {
|
||||
_GP(ccError) = ScriptError();
|
||||
@ -71,15 +69,12 @@ void cc_error(const char *descr, ...) {
|
||||
String displbuf = String::FromFormatV(descr, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (_G(currentline) > 0) {
|
||||
// [IKM] Implementation is project-specific
|
||||
std::pair<String, String> errinfo = cc_error_at_line(displbuf.GetCStr());
|
||||
_GP(ccError).ErrorString = errinfo.first;
|
||||
_GP(ccError).CallStack = errinfo.second;
|
||||
} else {
|
||||
_GP(ccError).ErrorString = cc_error_without_line(displbuf.GetCStr());
|
||||
_GP(ccError).CallStack = "";
|
||||
}
|
||||
String callstack = cc_get_callstack();
|
||||
if ((_G(currentline) > 0) && callstack.IsEmpty())
|
||||
_GP(ccError).ErrorString = String::FromFormat("Error (line %d): %s", _G(currentline), displbuf.GetCStr());
|
||||
else
|
||||
_GP(ccError).ErrorString = String::FromFormat("Error: %s", displbuf.GetCStr());
|
||||
_GP(ccError).CallStack = callstack;
|
||||
|
||||
_GP(ccError).HasError = 1;
|
||||
_GP(ccError).Line = _G(currentline);
|
||||
|
Loading…
x
Reference in New Issue
Block a user