mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-23 04:33:09 +00:00
SCI: Expand kernel breakpoint pattern matching for negative matches
See matchKernelBreakpointPattern() for samples. The main envisioned use is DoSound*,!DoSoundUpdateCues to match all DoSound sub-functions except DoSoundUpdateCues.
This commit is contained in:
parent
e7b6a257b9
commit
c7d631cb66
@ -3993,6 +3993,9 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
|
||||
debugPrintf("Sets a breakpoint on execution of a kernel function.\n");
|
||||
debugPrintf("Usage: %s <name> [<action>]\n", argv[0]);
|
||||
debugPrintf("Example: %s DrawPic\n", argv[0]);
|
||||
debugPrintf(" %s DoSoundPlay,DoSoundStop\n", argv[0]);
|
||||
debugPrintf(" %s DoSound*\n", argv[0]);
|
||||
debugPrintf(" %s DoSound*,!DoSoundUpdateCues\n", argv[0]);
|
||||
debugPrintf(" %s DrawPic log\n", argv[0]);
|
||||
debugPrintf("See bp_action usage for possible actions.\n");
|
||||
return true;
|
||||
@ -4008,11 +4011,7 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
// Check if any kernel functions match, to catch typos
|
||||
Common::String name = argv[1];
|
||||
bool wildcard = name.lastChar() == '*';
|
||||
Common::String prefix = name;
|
||||
if (wildcard)
|
||||
prefix.deleteLastChar();
|
||||
Common::String pattern = argv[1];
|
||||
bool found = false;
|
||||
const Kernel::KernelFunctionArray &kernelFuncs = _engine->getKernel()->_kernelFuncs;
|
||||
for (uint id = 0; id < kernelFuncs.size() && !found; id++) {
|
||||
@ -4020,14 +4019,14 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
|
||||
const KernelSubFunction *kernelSubCall = kernelFuncs[id].subFunctions;
|
||||
if (!kernelSubCall) {
|
||||
Common::String kname = kernelFuncs[id].name;
|
||||
if (name == kname || (wildcard && kname.hasPrefix(prefix)))
|
||||
if (matchKernelBreakpointPattern(pattern, kname))
|
||||
found = true;
|
||||
} else {
|
||||
uint kernelSubCallCount = kernelFuncs[id].subFunctionCount;
|
||||
for (uint subId = 0; subId < kernelSubCallCount; subId++) {
|
||||
if (kernelSubCall->name) {
|
||||
Common::String kname = kernelSubCall->name;
|
||||
if (name == kname || (wildcard && kname.hasPrefix(prefix)))
|
||||
if (matchKernelBreakpointPattern(pattern, kname))
|
||||
found = true;
|
||||
}
|
||||
kernelSubCall++;
|
||||
@ -4036,13 +4035,13 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
debugPrintf("No kernel functions match %s.\n", name.c_str());
|
||||
debugPrintf("No kernel functions match %s.\n", pattern.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
Breakpoint bp;
|
||||
bp._type = BREAK_KERNEL;
|
||||
bp._name = name;
|
||||
bp._name = pattern;
|
||||
bp._action = action;
|
||||
|
||||
_debugState._breakpoints.push_back(bp);
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "sci/engine/script.h"
|
||||
#include "sci/engine/scriptdebug.h"
|
||||
|
||||
#include "common/algorithm.h"
|
||||
|
||||
namespace Sci {
|
||||
|
||||
//#define VM_DEBUG_SEND
|
||||
@ -782,6 +784,49 @@ bool SciEngine::checkAddressBreakpoint(const reg32_t &address) {
|
||||
return found;
|
||||
}
|
||||
|
||||
bool matchKernelBreakpointPattern(const Common::String &pattern, const Common::String &name) {
|
||||
// Pattern:
|
||||
// A comma-separated list of atoms.
|
||||
// An atom is a (possibly empty) word, optionally with a ! prefix (for
|
||||
// a negative-match), and/or a * suffix (for a prefix-match).
|
||||
|
||||
// The last matching atom in the pattern takes effect.
|
||||
|
||||
// Examples:
|
||||
// FrameOut : matches only FrameOut
|
||||
// * : matches everything
|
||||
// *,!FrameOut : matches everything except FrameOut
|
||||
// InitBresen,DoBresen : matches InitBresen and DoBresen
|
||||
// DoSound*,!DoSoundUpdateCues : matches all DoSound sub-functions except
|
||||
// DoSoundUpdateCues
|
||||
|
||||
bool result = false;
|
||||
|
||||
Common::String::const_iterator i = pattern.begin();
|
||||
while (i != pattern.end()) {
|
||||
Common::String::const_iterator next = Common::find(i, pattern.end(), ',');
|
||||
bool negative = *i == '!';
|
||||
|
||||
if (negative)
|
||||
i++;
|
||||
|
||||
Common::String atom(i, next - i);
|
||||
|
||||
bool wildcard = atom.lastChar() == '*';
|
||||
if (wildcard)
|
||||
atom.deleteLastChar();
|
||||
|
||||
if ((!wildcard && atom == name) || (wildcard && name.hasPrefix(atom)))
|
||||
result = !negative;
|
||||
|
||||
i = next;
|
||||
if (i != pattern.end())
|
||||
++i; // skip comma
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SciEngine::checkKernelBreakpoint(const Common::String &name) {
|
||||
if (!(_debugState._activeBreakpointTypes & BREAK_KERNEL))
|
||||
return false;
|
||||
@ -793,11 +838,7 @@ bool SciEngine::checkKernelBreakpoint(const Common::String &name) {
|
||||
if (bp->_action == BREAK_NONE || bp->_type != BREAK_KERNEL)
|
||||
continue;
|
||||
|
||||
bool wildcard = bp->_name.lastChar() == '*';
|
||||
Common::String prefix = bp->_name;
|
||||
if (wildcard)
|
||||
prefix.deleteLastChar();
|
||||
if (bp->_name == name || (wildcard && name.hasPrefix(prefix))) {
|
||||
if (matchKernelBreakpointPattern(bp->_name, name)) {
|
||||
if (bp->_action == BREAK_BREAK) {
|
||||
if (!found)
|
||||
_console->debugPrintf("Break on k%s\n", name.c_str());
|
||||
|
@ -39,6 +39,8 @@ void logBacktrace();
|
||||
|
||||
bool printObject(reg_t obj);
|
||||
|
||||
bool matchKernelBreakpointPattern(const Common::String &pattern, const Common::String &name);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user