Converted the expression engine to C++, did the usual cleanup.
This commit is contained in:
parent
c956d18f78
commit
a2ce61ac6c
193
src/emu/cheat.c
193
src/emu/cheat.c
@ -108,7 +108,6 @@
|
||||
#include "uimenu.h"
|
||||
#include "cheat.h"
|
||||
#include "debug/debugcpu.h"
|
||||
#include "debug/express.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@ -198,7 +197,7 @@ cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols,
|
||||
}
|
||||
|
||||
// add a variable to the symbol table for our value
|
||||
symtable_add_register(&symbols, "param", &m_value, cheat_manager::variable_get, NULL);
|
||||
symbols.add("param", symbol_table::READ_ONLY, &m_value);
|
||||
}
|
||||
|
||||
|
||||
@ -432,20 +431,17 @@ void cheat_script::save(mame_file &cheatfile) const
|
||||
|
||||
cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction)
|
||||
: m_next(NULL),
|
||||
m_condition(NULL),
|
||||
m_expression(NULL),
|
||||
m_condition(&symbols),
|
||||
m_expression(&symbols),
|
||||
m_arglist(manager.machine().m_respool)
|
||||
{
|
||||
const char *expression = NULL;
|
||||
try
|
||||
{
|
||||
// read the condition if present
|
||||
const char *expression = xml_get_attribute_string(&entrynode, "condition", NULL);
|
||||
expression = xml_get_attribute_string(&entrynode, "condition", NULL);
|
||||
if (expression != NULL)
|
||||
{
|
||||
EXPRERR experr = expression_parse(expression, &symbols, &debug_expression_callbacks, &manager.machine(), &m_condition);
|
||||
if (experr != EXPRERR_NONE)
|
||||
throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, entrynode.line, expression, exprerr_to_string(experr));
|
||||
}
|
||||
m_condition.parse(expression);
|
||||
|
||||
// if this is an action, parse the expression
|
||||
if (isaction)
|
||||
@ -453,10 +449,7 @@ cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &s
|
||||
expression = entrynode.value;
|
||||
if (expression == NULL || expression[0] == 0)
|
||||
throw emu_fatalerror("%s.xml(%d): missing expression in action tag\n", filename, entrynode.line);
|
||||
|
||||
EXPRERR experr = expression_parse(expression, &symbols, &debug_expression_callbacks, &manager.machine(), &m_expression);
|
||||
if (experr != EXPRERR_NONE)
|
||||
throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, entrynode.line, expression, exprerr_to_string(experr));
|
||||
m_expression.parse(expression);
|
||||
}
|
||||
|
||||
// otherwise, parse the attributes and arguments
|
||||
@ -495,28 +488,13 @@ cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &s
|
||||
validate_format(filename, entrynode.line);
|
||||
}
|
||||
}
|
||||
catch (emu_fatalerror &)
|
||||
catch (expression_error &err)
|
||||
{
|
||||
// call our destructor and re-throw
|
||||
this->~script_entry();
|
||||
throw;
|
||||
throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, entrynode.line, expression, err.code_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// script_entry - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
cheat_script::script_entry::~script_entry()
|
||||
{
|
||||
if (m_condition != NULL)
|
||||
expression_free(m_condition);
|
||||
if (m_expression != NULL)
|
||||
expression_free(m_expression);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute - execute a single script entry
|
||||
//-------------------------------------------------
|
||||
@ -524,25 +502,32 @@ cheat_script::script_entry::~script_entry()
|
||||
void cheat_script::script_entry::execute(cheat_manager &manager, UINT64 &argindex)
|
||||
{
|
||||
// evaluate the condition
|
||||
if (m_condition != NULL)
|
||||
if (!m_condition.is_empty())
|
||||
{
|
||||
UINT64 result;
|
||||
EXPRERR error = expression_execute(m_condition, &result);
|
||||
if (error != EXPRERR_NONE)
|
||||
mame_printf_warning("Error executing conditional expression \"%s\": %s\n", expression_original_string(m_condition), exprerr_to_string(error));
|
||||
|
||||
// if the condition is false, or we got an error, don't execute
|
||||
if (error != EXPRERR_NONE || result == 0)
|
||||
try
|
||||
{
|
||||
UINT64 result = m_condition.execute();
|
||||
if (result == 0)
|
||||
return;
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
mame_printf_warning("Error executing conditional expression \"%s\": %s\n", m_condition.original_string(), err.code_string());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is an action, execute it
|
||||
if (m_expression != NULL)
|
||||
if (!m_expression.is_empty())
|
||||
{
|
||||
UINT64 result;
|
||||
EXPRERR error = expression_execute(m_expression, &result);
|
||||
if (error != EXPRERR_NONE)
|
||||
mame_printf_warning("Error executing expression \"%s\": %s\n", expression_original_string(m_expression), exprerr_to_string(error));
|
||||
try
|
||||
{
|
||||
m_expression.execute();
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
mame_printf_warning("Error executing expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a string to display, compute it
|
||||
@ -580,17 +565,17 @@ void cheat_script::script_entry::save(mame_file &cheatfile) const
|
||||
if (!m_format)
|
||||
{
|
||||
mame_fprintf(&cheatfile, "\t\t\t<action");
|
||||
if (m_condition != NULL)
|
||||
mame_fprintf(&cheatfile, " condition=\"%s\"", cheat_manager::quote_expression(tempstring, *m_condition));
|
||||
mame_fprintf(&cheatfile, ">%s</action>\n", cheat_manager::quote_expression(tempstring, *m_expression));
|
||||
if (!m_condition.is_empty())
|
||||
mame_fprintf(&cheatfile, " condition=\"%s\"", cheat_manager::quote_expression(tempstring, m_condition));
|
||||
mame_fprintf(&cheatfile, ">%s</action>\n", cheat_manager::quote_expression(tempstring, m_expression));
|
||||
}
|
||||
|
||||
// output an output
|
||||
else
|
||||
{
|
||||
mame_fprintf(&cheatfile, "\t\t\t<output format=\"%s\"", m_format.cstr());
|
||||
if (m_condition != NULL)
|
||||
mame_fprintf(&cheatfile, " condition=\"%s\"", cheat_manager::quote_expression(tempstring, *m_condition));
|
||||
if (!m_condition.is_empty())
|
||||
mame_fprintf(&cheatfile, " condition=\"%s\"", cheat_manager::quote_expression(tempstring, m_condition));
|
||||
if (m_line != 0)
|
||||
mame_fprintf(&cheatfile, " line=\"%d\"", m_line);
|
||||
if (m_justify == JUSTIFY_CENTER)
|
||||
@ -657,7 +642,7 @@ void cheat_script::script_entry::validate_format(const char *filename, int line)
|
||||
|
||||
cheat_script::script_entry::output_argument::output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode)
|
||||
: m_next(NULL),
|
||||
m_expression(NULL),
|
||||
m_expression(&symbols),
|
||||
m_count(0)
|
||||
{
|
||||
// first extract attributes
|
||||
@ -668,20 +653,15 @@ cheat_script::script_entry::output_argument::output_argument(cheat_manager &mana
|
||||
if (expression == NULL || expression[0] == 0)
|
||||
throw emu_fatalerror("%s.xml(%d): missing expression in argument tag\n", filename, argnode.line);
|
||||
|
||||
EXPRERR experr = expression_parse(expression, &symbols, &debug_expression_callbacks, &manager.machine(), &m_expression);
|
||||
if (experr != EXPRERR_NONE)
|
||||
throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, argnode.line, expression, exprerr_to_string(experr));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// output_argument - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
cheat_script::script_entry::output_argument::~output_argument()
|
||||
{
|
||||
if (m_expression != NULL)
|
||||
expression_free(m_expression);
|
||||
// parse it
|
||||
try
|
||||
{
|
||||
m_expression.parse(expression);
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, argnode.line, expression, err.code_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -694,9 +674,14 @@ int cheat_script::script_entry::output_argument::values(UINT64 &argindex, UINT64
|
||||
{
|
||||
for (argindex = 0; argindex < m_count; argindex++)
|
||||
{
|
||||
EXPRERR error = expression_execute(m_expression, &result[argindex]);
|
||||
if (error != EXPRERR_NONE)
|
||||
mame_printf_warning("Error executing argument expression \"%s\": %s\n", expression_original_string(m_expression), exprerr_to_string(error));
|
||||
try
|
||||
{
|
||||
result[argindex] = m_expression.execute();
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
mame_printf_warning("Error executing argument expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
|
||||
}
|
||||
}
|
||||
return m_count;
|
||||
}
|
||||
@ -713,7 +698,7 @@ void cheat_script::script_entry::output_argument::save(mame_file &cheatfile) con
|
||||
mame_fprintf(&cheatfile, "\t\t\t\t<argument");
|
||||
if (m_count != 1)
|
||||
mame_fprintf(&cheatfile, " count=\"%d\"", (int)m_count);
|
||||
mame_fprintf(&cheatfile, ">%s</argument>\n", cheat_manager::quote_expression(tempstring, *m_expression));
|
||||
mame_fprintf(&cheatfile, ">%s</argument>\n", cheat_manager::quote_expression(tempstring, m_expression));
|
||||
}
|
||||
|
||||
|
||||
@ -734,11 +719,10 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
m_off_script(NULL),
|
||||
m_change_script(NULL),
|
||||
m_run_script(NULL),
|
||||
m_symbols(NULL),
|
||||
m_symbols(&manager.machine(), &globaltable),
|
||||
m_state(SCRIPT_STATE_OFF),
|
||||
m_numtemp(DEFAULT_TEMP_VARIABLES),
|
||||
m_argindex(0),
|
||||
m_tempvar(NULL)
|
||||
m_argindex(0)
|
||||
{
|
||||
// reset scripts
|
||||
try
|
||||
@ -750,7 +734,6 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
|
||||
// allocate memory for the cheat
|
||||
m_numtemp = tempcount;
|
||||
m_tempvar = auto_alloc_array_clear(&manager.machine(), UINT64, tempcount);
|
||||
|
||||
// get the description
|
||||
const char *description = xml_get_attribute_string(&cheatnode, "desc", NULL);
|
||||
@ -759,11 +742,10 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
m_description = description;
|
||||
|
||||
// create the symbol table
|
||||
m_symbols = symtable_alloc(&globaltable, &manager.machine());
|
||||
symtable_add_register(m_symbols, "argindex", &m_argindex, cheat_manager::variable_get, NULL);
|
||||
m_symbols.add("argindex", symbol_table::READ_ONLY, &m_argindex);
|
||||
astring tempname;
|
||||
for (int curtemp = 0; curtemp < tempcount; curtemp++)
|
||||
symtable_add_register(m_symbols, tempname.format("temp%d", curtemp), &m_tempvar[curtemp], cheat_manager::variable_get, cheat_manager::variable_set);
|
||||
m_symbols.add(tempname.format("temp%d", curtemp), symbol_table::READ_WRITE);
|
||||
|
||||
// read the first comment node
|
||||
xml_data_node *commentnode = xml_get_sibling(cheatnode.child, "comment");
|
||||
@ -784,7 +766,7 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
if (paramnode != NULL)
|
||||
{
|
||||
// load this parameter
|
||||
m_parameter = auto_alloc(&manager.machine(), cheat_parameter(manager, *m_symbols, filename, *paramnode));
|
||||
m_parameter = auto_alloc(&manager.machine(), cheat_parameter(manager, m_symbols, filename, *paramnode));
|
||||
|
||||
// only one parameter allowed
|
||||
paramnode = xml_get_sibling(paramnode->next, "parameter");
|
||||
@ -796,7 +778,7 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
for (xml_data_node *scriptnode = xml_get_sibling(cheatnode.child, "script"); scriptnode != NULL; scriptnode = xml_get_sibling(scriptnode->next, "script"))
|
||||
{
|
||||
// load this entry
|
||||
cheat_script *curscript = auto_alloc(&manager.machine(), cheat_script(manager, *m_symbols, filename, *scriptnode));
|
||||
cheat_script *curscript = auto_alloc(&manager.machine(), cheat_script(manager, m_symbols, filename, *scriptnode));
|
||||
|
||||
// if we have a script already for this slot, it is an error
|
||||
cheat_script *&slot = script_for_state(curscript->state());
|
||||
@ -821,14 +803,11 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
|
||||
|
||||
cheat_entry::~cheat_entry()
|
||||
{
|
||||
if (m_symbols != NULL)
|
||||
symtable_free(m_symbols);
|
||||
auto_free(&m_manager.machine(), m_on_script);
|
||||
auto_free(&m_manager.machine(), m_off_script);
|
||||
auto_free(&m_manager.machine(), m_change_script);
|
||||
auto_free(&m_manager.machine(), m_run_script);
|
||||
auto_free(&m_manager.machine(), m_parameter);
|
||||
auto_free(&m_manager.machine(), m_tempvar);
|
||||
}
|
||||
|
||||
|
||||
@ -1110,7 +1089,8 @@ cheat_script *&cheat_entry::script_for_state(script_state state)
|
||||
cheat_manager::cheat_manager(running_machine &machine)
|
||||
: m_machine(machine),
|
||||
m_cheatlist(machine.m_respool),
|
||||
m_disabled(true)
|
||||
m_disabled(true),
|
||||
m_symtable(&machine)
|
||||
{
|
||||
// if the cheat engine is disabled, we're done
|
||||
if (!options_get_bool(machine.options(), OPTION_CHEAT))
|
||||
@ -1120,27 +1100,20 @@ cheat_manager::cheat_manager(running_machine &machine)
|
||||
machine.add_notifier(MACHINE_NOTIFY_FRAME, frame_update_static);
|
||||
|
||||
// create a global symbol table
|
||||
m_symtable = symtable_alloc(NULL, &machine);
|
||||
symtable_add_register(m_symtable, "frame", &m_framecount, variable_get, NULL);
|
||||
symtable_add_function(m_symtable, "frombcd", NULL, 1, 1, execute_frombcd);
|
||||
symtable_add_function(m_symtable, "tobcd", NULL, 1, 1, execute_tobcd);
|
||||
|
||||
// load the cheats
|
||||
reload();
|
||||
m_symtable.add("frame", symbol_table::READ_ONLY, &m_framecount);
|
||||
m_symtable.add("frombcd", NULL, 1, 1, execute_frombcd);
|
||||
m_symtable.add("tobcd", NULL, 1, 1, execute_tobcd);
|
||||
|
||||
// we rely on the debugger expression callbacks; if the debugger isn't
|
||||
// enabled, we must jumpstart them manually
|
||||
if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0)
|
||||
debug_cpu_init(&machine);
|
||||
}
|
||||
|
||||
// configure for memory access (shared with debugger)
|
||||
debug_cpu_configure_memory(machine, m_symtable);
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~cheat_manager - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
cheat_manager::~cheat_manager()
|
||||
{
|
||||
// load the cheats
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
@ -1324,9 +1297,9 @@ astring &cheat_manager::get_output_astring(int row, int justify)
|
||||
// document
|
||||
//-------------------------------------------------
|
||||
|
||||
const char *cheat_manager::quote_expression(astring &string, parsed_expression &expression)
|
||||
const char *cheat_manager::quote_expression(astring &string, const parsed_expression &expression)
|
||||
{
|
||||
string.cpy(expression_original_string(&expression));
|
||||
string.cpy(expression.original_string());
|
||||
|
||||
string.replace(0, " && ", " and ");
|
||||
string.replace(0, " &&", " and ");
|
||||
@ -1357,31 +1330,11 @@ const char *cheat_manager::quote_expression(astring &string, parsed_expression &
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// variable_get - return the value of a variable
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 cheat_manager::variable_get(void *globalref, void *ref)
|
||||
{
|
||||
return *(UINT64 *)ref;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// variable_set - set the value of a variable
|
||||
//-------------------------------------------------
|
||||
|
||||
void cheat_manager::variable_set(void *globalref, void *ref, UINT64 value)
|
||||
{
|
||||
*(UINT64 *)ref = value;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_frombcd - convert a value from BCD
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 cheat_manager::execute_frombcd(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
UINT64 cheat_manager::execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
UINT64 value = param[0];
|
||||
UINT64 multiplier = 1;
|
||||
@ -1401,7 +1354,7 @@ UINT64 cheat_manager::execute_frombcd(void *globalref, void *ref, UINT32 params,
|
||||
// execute_tobcd - convert a value to BCD
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 cheat_manager::execute_tobcd(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
UINT64 cheat_manager::execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
UINT64 value = param[0];
|
||||
UINT64 result = 0;
|
||||
@ -1488,7 +1441,7 @@ void cheat_manager::load_cheats(const char *filename)
|
||||
for (xml_data_node *cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != NULL; cheatnode = xml_get_sibling(cheatnode->next, "cheat"))
|
||||
{
|
||||
// load this entry
|
||||
cheat_entry *curcheat = auto_alloc(&m_machine, cheat_entry(*this, *m_symtable, filename, *cheatnode));
|
||||
cheat_entry *curcheat = auto_alloc(&m_machine, cheat_entry(*this, m_symtable, filename, *cheatnode));
|
||||
|
||||
// make sure we're not a duplicate
|
||||
cheat_entry *scannode = NULL;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#ifndef __CHEAT_H__
|
||||
#define __CHEAT_H__
|
||||
|
||||
#include "debug/express.h"
|
||||
#include "ui.h"
|
||||
|
||||
|
||||
@ -66,8 +67,6 @@ DECLARE_ENUM_OPERATORS(script_state)
|
||||
//**************************************************************************
|
||||
|
||||
class cheat_manager;
|
||||
typedef struct _symbol_table symbol_table;
|
||||
typedef struct _parsed_expression parsed_expression;
|
||||
|
||||
|
||||
// ======================> number_and_format
|
||||
@ -180,7 +179,6 @@ private:
|
||||
public:
|
||||
// construction/destruction
|
||||
script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction);
|
||||
~script_entry();
|
||||
|
||||
// getters
|
||||
script_entry *next() const { return m_next; }
|
||||
@ -198,7 +196,6 @@ private:
|
||||
public:
|
||||
// construction/destruction
|
||||
output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode);
|
||||
~output_argument();
|
||||
|
||||
// getters
|
||||
output_argument *next() const { return m_next; }
|
||||
@ -211,7 +208,7 @@ private:
|
||||
private:
|
||||
// internal state
|
||||
output_argument * m_next; // link to next argument
|
||||
parsed_expression * m_expression; // expression for argument
|
||||
parsed_expression m_expression; // expression for argument
|
||||
UINT64 m_count; // number of repetitions
|
||||
};
|
||||
|
||||
@ -220,8 +217,8 @@ private:
|
||||
|
||||
// internal state
|
||||
script_entry * m_next; // link to next entry
|
||||
parsed_expression * m_condition; // condition under which this is executed
|
||||
parsed_expression * m_expression; // expression to execute
|
||||
parsed_expression m_condition; // condition under which this is executed
|
||||
parsed_expression m_expression; // expression to execute
|
||||
astring m_format; // string format to print
|
||||
simple_list<output_argument> m_arglist; // list of arguments
|
||||
INT8 m_line; // which line to print on
|
||||
@ -304,11 +301,10 @@ private:
|
||||
cheat_script * m_off_script; // script to run when turning off
|
||||
cheat_script * m_change_script; // script to run when value changes
|
||||
cheat_script * m_run_script; // script to run each frame when on
|
||||
symbol_table * m_symbols; // symbol table for this cheat
|
||||
symbol_table m_symbols; // symbol table for this cheat
|
||||
script_state m_state; // current cheat state
|
||||
UINT32 m_numtemp; // number of temporary variables
|
||||
UINT64 m_argindex; // argument index variable
|
||||
UINT64 * m_tempvar; // value of the temporary variables
|
||||
|
||||
// constants
|
||||
static const int DEFAULT_TEMP_VARIABLES = 10;
|
||||
@ -323,7 +319,6 @@ class cheat_manager
|
||||
public:
|
||||
// construction/destruction
|
||||
cheat_manager(running_machine &machine);
|
||||
~cheat_manager();
|
||||
|
||||
// getters
|
||||
running_machine &machine() const { return m_machine; }
|
||||
@ -342,11 +337,9 @@ public:
|
||||
astring &get_output_astring(int row, int justify);
|
||||
|
||||
// global helpers
|
||||
static const char *quote_expression(astring &string, parsed_expression &expression);
|
||||
static UINT64 variable_get(void *globalref, void *ref);
|
||||
static void variable_set(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 execute_frombcd(void *globalref, void *ref, UINT32 params, const UINT64 *param);
|
||||
static UINT64 execute_tobcd(void *globalref, void *ref, UINT32 params, const UINT64 *param);
|
||||
static const char *quote_expression(astring &string, const parsed_expression &expression);
|
||||
static UINT64 execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param);
|
||||
static UINT64 execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param);
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
@ -363,7 +356,7 @@ private:
|
||||
UINT8 m_numlines; // number of lines available for output
|
||||
INT8 m_lastline; // last line used for output
|
||||
bool m_disabled; // true if the cheat engine is disabled
|
||||
symbol_table * m_symtable; // global symbol table
|
||||
symbol_table m_symtable; // global symbol table
|
||||
|
||||
// constants
|
||||
static const int CHEAT_VERSION = 1;
|
||||
@ -371,4 +364,3 @@ private:
|
||||
|
||||
|
||||
#endif /* __CHEAT_H__ */
|
||||
|
||||
|
@ -461,7 +461,7 @@ static void I386OP(decode_two_byte)(i386_state *cpustate)
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static UINT64 i386_debug_segbase(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
static UINT64 i386_debug_segbase(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
legacy_cpu_device *device = (legacy_cpu_device *)ref;
|
||||
i386_state *cpustate = get_safe_token(device);
|
||||
@ -482,7 +482,7 @@ static UINT64 i386_debug_segbase(void *globalref, void *ref, UINT32 params, cons
|
||||
return result;
|
||||
}
|
||||
|
||||
static UINT64 i386_debug_seglimit(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
static UINT64 i386_debug_seglimit(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
legacy_cpu_device *device = (legacy_cpu_device *)ref;
|
||||
i386_state *cpustate = get_safe_token(device);
|
||||
@ -501,8 +501,8 @@ static UINT64 i386_debug_seglimit(void *globalref, void *ref, UINT32 params, con
|
||||
|
||||
static CPU_DEBUG_INIT( i386 )
|
||||
{
|
||||
symtable_add_function(device->debug()->symtable(), "segbase", (void *)device, 1, 1, i386_debug_segbase);
|
||||
symtable_add_function(device->debug()->symtable(), "seglimit", (void *)device, 1, 1, i386_debug_seglimit);
|
||||
device->debug()->symtable().add("segbase", (void *)device, 1, 1, i386_debug_segbase);
|
||||
device->debug()->symtable().add("seglimit", (void *)device, 1, 1, i386_debug_seglimit);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -92,12 +92,12 @@ static cheat_system cheat;
|
||||
|
||||
static void debug_command_exit(running_machine &machine);
|
||||
|
||||
static UINT64 execute_min(void *globalref, void *ref, UINT32 params, const UINT64 *param);
|
||||
static UINT64 execute_max(void *globalref, void *ref, UINT32 params, const UINT64 *param);
|
||||
static UINT64 execute_if(void *globalref, void *ref, UINT32 params, const UINT64 *param);
|
||||
static UINT64 execute_min(symbol_table &table, void *ref, int params, const UINT64 *param);
|
||||
static UINT64 execute_max(symbol_table &table, void *ref, int params, const UINT64 *param);
|
||||
static UINT64 execute_if(symbol_table &table, void *ref, int params, const UINT64 *param);
|
||||
|
||||
static UINT64 global_get(void *globalref, void *ref);
|
||||
static void global_set(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 global_get(symbol_table &table, void *ref);
|
||||
static void global_set(symbol_table &table, void *ref, UINT64 value);
|
||||
|
||||
static void execute_help(running_machine *machine, int ref, int params, const char **param);
|
||||
static void execute_print(running_machine *machine, int ref, int params, const char **param);
|
||||
@ -232,9 +232,9 @@ void debug_command_init(running_machine *machine)
|
||||
int itemnum;
|
||||
|
||||
/* add a few simple global functions */
|
||||
symtable_add_function(symtable, "min", NULL, 2, 2, execute_min);
|
||||
symtable_add_function(symtable, "max", NULL, 2, 2, execute_max);
|
||||
symtable_add_function(symtable, "if", NULL, 3, 3, execute_if);
|
||||
symtable->add("min", NULL, 2, 2, execute_min);
|
||||
symtable->add("max", NULL, 2, 2, execute_max);
|
||||
symtable->add("if", NULL, 3, 3, execute_if);
|
||||
|
||||
/* add all single-entry save state globals */
|
||||
for (itemnum = 0; itemnum < MAX_GLOBALS; itemnum++)
|
||||
@ -254,7 +254,7 @@ void debug_command_init(running_machine *machine)
|
||||
sprintf(symname, ".%s", strrchr(name, '/') + 1);
|
||||
global_array[itemnum].base = base;
|
||||
global_array[itemnum].size = valsize;
|
||||
symtable_add_register(symtable, symname, &global_array, global_get, global_set);
|
||||
symtable->add(symname, &global_array, global_get, global_set);
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,7 +397,7 @@ static void debug_command_exit(running_machine &machine)
|
||||
execute_min - return the minimum of two values
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 execute_min(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
static UINT64 execute_min(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
return (param[0] < param[1]) ? param[0] : param[1];
|
||||
}
|
||||
@ -407,7 +407,7 @@ static UINT64 execute_min(void *globalref, void *ref, UINT32 params, const UINT6
|
||||
execute_max - return the maximum of two values
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 execute_max(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
static UINT64 execute_max(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
return (param[0] > param[1]) ? param[0] : param[1];
|
||||
}
|
||||
@ -417,7 +417,7 @@ static UINT64 execute_max(void *globalref, void *ref, UINT32 params, const UINT6
|
||||
execute_if - if (a) return b; else return c;
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 execute_if(void *globalref, void *ref, UINT32 params, const UINT64 *param)
|
||||
static UINT64 execute_if(symbol_table &table, void *ref, int params, const UINT64 *param)
|
||||
{
|
||||
return param[0] ? param[1] : param[2];
|
||||
}
|
||||
@ -432,7 +432,7 @@ static UINT64 execute_if(void *globalref, void *ref, UINT32 params, const UINT64
|
||||
global_get - symbol table getter for globals
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 global_get(void *globalref, void *ref)
|
||||
static UINT64 global_get(symbol_table &table, void *ref)
|
||||
{
|
||||
global_entry *global = (global_entry *)ref;
|
||||
switch (global->size)
|
||||
@ -450,7 +450,7 @@ static UINT64 global_get(void *globalref, void *ref)
|
||||
global_set - symbol table setter for globals
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void global_set(void *globalref, void *ref, UINT64 value)
|
||||
static void global_set(symbol_table &table, void *ref, UINT64 value)
|
||||
{
|
||||
global_entry *global = (global_entry *)ref;
|
||||
switch (global->size)
|
||||
@ -475,22 +475,24 @@ static void global_set(void *globalref, void *ref, UINT64 value)
|
||||
|
||||
int debug_command_parameter_number(running_machine *machine, const char *param, UINT64 *result)
|
||||
{
|
||||
EXPRERR err;
|
||||
|
||||
/* NULL parameter does nothing and returns no error */
|
||||
if (param == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* evaluate the expression; success if no error */
|
||||
err = expression_evaluate(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result);
|
||||
if (err == EXPRERR_NONE)
|
||||
try
|
||||
{
|
||||
parsed_expression expression(debug_cpu_get_visible_symtable(machine), param, result);
|
||||
return TRUE;
|
||||
|
||||
/* print an error pointing to the character that caused it */
|
||||
debug_console_printf(machine, "Error in expression: %s\n", param);
|
||||
debug_console_printf(machine, " %*s^", EXPRERR_ERROR_OFFSET(err), "");
|
||||
debug_console_printf(machine, "%s\n", exprerr_to_string(err));
|
||||
return FALSE;
|
||||
}
|
||||
catch (expression_error &error)
|
||||
{
|
||||
/* print an error pointing to the character that caused it */
|
||||
debug_console_printf(machine, "Error in expression: %s\n", param);
|
||||
debug_console_printf(machine, " %*s^", error.offset(), "");
|
||||
debug_console_printf(machine, "%s\n", error.code_string());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -502,7 +504,6 @@ int debug_command_parameter_number(running_machine *machine, const char *param,
|
||||
int debug_command_parameter_cpu(running_machine *machine, const char *param, device_t **result)
|
||||
{
|
||||
UINT64 cpunum;
|
||||
EXPRERR err;
|
||||
|
||||
/* if no parameter, use the visible CPU */
|
||||
if (param == NULL)
|
||||
@ -522,8 +523,11 @@ int debug_command_parameter_cpu(running_machine *machine, const char *param, dev
|
||||
return TRUE;
|
||||
|
||||
/* then evaluate as an expression; on an error assume it was a tag */
|
||||
err = expression_evaluate(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, &cpunum);
|
||||
if (err != EXPRERR_NONE)
|
||||
try
|
||||
{
|
||||
parsed_expression expression(debug_cpu_get_visible_symtable(machine), param, &cpunum);
|
||||
}
|
||||
catch (expression_error &)
|
||||
{
|
||||
debug_console_printf(machine, "Unable to find CPU '%s'\n", param);
|
||||
return FALSE;
|
||||
@ -574,27 +578,26 @@ int debug_command_parameter_cpu_space(running_machine *machine, const char *para
|
||||
an expression parameter
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int debug_command_parameter_expression(running_machine *machine, const char *param, parsed_expression **result)
|
||||
static int debug_command_parameter_expression(running_machine *machine, const char *param, parsed_expression &result)
|
||||
{
|
||||
EXPRERR err;
|
||||
|
||||
/* NULL parameter does nothing and returns no error */
|
||||
if (param == NULL)
|
||||
{
|
||||
*result = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* parse the expression; success if no error */
|
||||
err = expression_parse(param, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, result);
|
||||
if (err == EXPRERR_NONE)
|
||||
try
|
||||
{
|
||||
result.parse(param);
|
||||
return TRUE;
|
||||
|
||||
/* output an error */
|
||||
debug_console_printf(machine, "Error in expression: %s\n", param);
|
||||
debug_console_printf(machine, " %*s^", EXPRERR_ERROR_OFFSET(err), "");
|
||||
debug_console_printf(machine, "%s\n", exprerr_to_string(err));
|
||||
return FALSE;
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
/* output an error */
|
||||
debug_console_printf(machine, "Error in expression: %s\n", param);
|
||||
debug_console_printf(machine, " %*s^", err.offset(), "");
|
||||
debug_console_printf(machine, "%s\n", err.code_string());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1160,7 +1163,7 @@ static void execute_comment_save(running_machine *machine, int ref, int params,
|
||||
|
||||
static void execute_bpset(running_machine *machine, int ref, int params, const char *param[])
|
||||
{
|
||||
parsed_expression *condition = NULL;
|
||||
parsed_expression condition(debug_cpu_get_global_symtable(machine));
|
||||
device_t *cpu;
|
||||
const char *action = NULL;
|
||||
UINT64 address;
|
||||
@ -1171,7 +1174,7 @@ static void execute_bpset(running_machine *machine, int ref, int params, const c
|
||||
return;
|
||||
|
||||
/* param 2 is the condition */
|
||||
if (!debug_command_parameter_expression(machine, param[1], &condition))
|
||||
if (!debug_command_parameter_expression(machine, param[1], condition))
|
||||
return;
|
||||
|
||||
/* param 3 is the action */
|
||||
@ -1183,7 +1186,7 @@ static void execute_bpset(running_machine *machine, int ref, int params, const c
|
||||
return;
|
||||
|
||||
/* set the breakpoint */
|
||||
bpnum = cpu->debug()->breakpoint_set(address, condition, action);
|
||||
bpnum = cpu->debug()->breakpoint_set(address, (condition.is_empty()) ? NULL : condition.original_string(), action);
|
||||
debug_console_printf(machine, "Breakpoint %X set\n", bpnum);
|
||||
}
|
||||
|
||||
@ -1300,7 +1303,7 @@ static void execute_bplist(running_machine *machine, int ref, int params, const
|
||||
|
||||
static void execute_wpset(running_machine *machine, int ref, int params, const char *param[])
|
||||
{
|
||||
parsed_expression *condition = NULL;
|
||||
parsed_expression condition(debug_cpu_get_global_symtable(machine));
|
||||
address_space *space;
|
||||
const char *action = NULL;
|
||||
UINT64 address, length;
|
||||
@ -1329,7 +1332,7 @@ static void execute_wpset(running_machine *machine, int ref, int params, const c
|
||||
}
|
||||
|
||||
/* param 4 is the condition */
|
||||
if (!debug_command_parameter_expression(machine, param[3], &condition))
|
||||
if (!debug_command_parameter_expression(machine, param[3], condition))
|
||||
return;
|
||||
|
||||
/* param 5 is the action */
|
||||
@ -1341,7 +1344,7 @@ static void execute_wpset(running_machine *machine, int ref, int params, const c
|
||||
return;
|
||||
|
||||
/* set the watchpoint */
|
||||
wpnum = space->cpu->debug()->watchpoint_set(*space, type, address, length, condition, action);
|
||||
wpnum = space->cpu->debug()->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? NULL : condition.original_string(), action);
|
||||
debug_console_printf(machine, "Watchpoint %X set\n", wpnum);
|
||||
}
|
||||
|
||||
@ -2544,7 +2547,7 @@ static void execute_symlist(running_machine *machine, int ref, int params, const
|
||||
|
||||
if (cpu != NULL)
|
||||
{
|
||||
symtable = cpu->debug()->symtable();
|
||||
symtable = &cpu->debug()->symtable();
|
||||
debug_console_printf(machine, "CPU '%s' symbols:\n", cpu->tag());
|
||||
}
|
||||
else
|
||||
@ -2554,19 +2557,12 @@ static void execute_symlist(running_machine *machine, int ref, int params, const
|
||||
}
|
||||
|
||||
/* gather names for all symbols */
|
||||
for (symnum = 0; symnum < 100000; symnum++)
|
||||
for (symbol_entry *entry = symtable->first(); entry != NULL; entry = entry->next())
|
||||
{
|
||||
const symbol_entry *entry;
|
||||
const char *name = symtable_find_indexed(symtable, symnum, &entry);
|
||||
|
||||
/* if we didn't get anything, we're done */
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
/* only display "register" type symbols */
|
||||
if (entry->type == SMT_REGISTER)
|
||||
if (!entry->is_function())
|
||||
{
|
||||
namelist[count++] = name;
|
||||
namelist[count++] = entry->name();
|
||||
if (count >= ARRAY_LENGTH(namelist))
|
||||
break;
|
||||
}
|
||||
@ -2579,13 +2575,13 @@ static void execute_symlist(running_machine *machine, int ref, int params, const
|
||||
/* iterate over symbols and print out relevant ones */
|
||||
for (symnum = 0; symnum < count; symnum++)
|
||||
{
|
||||
const symbol_entry *entry = symtable_find(symtable, namelist[symnum]);
|
||||
UINT64 value = (*entry->info.reg.getter)(symtable_get_globalref(entry->table), entry->ref);
|
||||
const symbol_entry *entry = symtable->find(namelist[symnum]);
|
||||
assert(entry != NULL);
|
||||
UINT64 value = entry->value();
|
||||
|
||||
/* only display "register" type symbols */
|
||||
debug_console_printf(machine, "%s = %s", namelist[symnum], core_i64_hex_format(value, 0));
|
||||
if (entry->info.reg.setter == NULL)
|
||||
if (!entry->is_lval())
|
||||
debug_console_printf(machine, " (read-only)");
|
||||
debug_console_printf(machine, "\n");
|
||||
}
|
||||
|
@ -338,10 +338,15 @@ static CMDERR internal_parse_command(running_machine *machine, const char *origi
|
||||
/* if it smells like an assignment expression, treat it as such */
|
||||
if (isexpr && paramcount == 1)
|
||||
{
|
||||
UINT64 expresult;
|
||||
EXPRERR exprerr = expression_evaluate(command_start, debug_cpu_get_visible_symtable(machine), &debug_expression_callbacks, machine, &expresult);
|
||||
if (exprerr != EXPRERR_NONE)
|
||||
return MAKE_CMDERR_EXPRESSION_ERROR(EXPRERR_ERROR_OFFSET(exprerr));
|
||||
try
|
||||
{
|
||||
UINT64 expresult;
|
||||
parsed_expression expression(debug_cpu_get_visible_symtable(machine), command_start, &expresult);
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
return MAKE_CMDERR_EXPRESSION_ERROR(err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -121,30 +121,13 @@ static UINT64 expression_read_memory_region(running_machine *machine, const char
|
||||
static void expression_write_memory(void *param, const char *name, int space, UINT32 address, int size, UINT64 data);
|
||||
static void expression_write_program_direct(address_space *space, int opcode, offs_t address, int size, UINT64 data);
|
||||
static void expression_write_memory_region(running_machine *machine, const char *rgntag, offs_t address, int size, UINT64 data);
|
||||
static EXPRERR expression_validate(void *param, const char *name, int space);
|
||||
static expression_error::error_code expression_validate(void *param, const char *name, int space);
|
||||
|
||||
/* variable getters/setters */
|
||||
static UINT64 get_wpaddr(void *globalref, void *ref);
|
||||
static UINT64 get_wpdata(void *globalref, void *ref);
|
||||
static UINT64 get_cpunum(void *globalref, void *ref);
|
||||
static UINT64 get_tempvar(void *globalref, void *ref);
|
||||
static void set_tempvar(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 get_beamx(void *globalref, void *ref);
|
||||
static UINT64 get_beamy(void *globalref, void *ref);
|
||||
static UINT64 get_frame(void *globalref, void *ref);
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
GLOBAL CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
const express_callbacks debug_expression_callbacks =
|
||||
{
|
||||
expression_read_memory,
|
||||
expression_write_memory,
|
||||
expression_validate
|
||||
};
|
||||
static UINT64 get_cpunum(symbol_table &table, void *ref);
|
||||
static UINT64 get_beamx(symbol_table &table, void *ref);
|
||||
static UINT64 get_beamy(symbol_table &table, void *ref);
|
||||
static UINT64 get_frame(symbol_table &table, void *ref);
|
||||
|
||||
|
||||
|
||||
@ -170,22 +153,25 @@ void debug_cpu_init(running_machine *machine)
|
||||
global->wpindex = 1;
|
||||
|
||||
/* create a global symbol table */
|
||||
global->symtable = symtable_alloc(NULL, machine);
|
||||
global->symtable = global_alloc(symbol_table(machine));
|
||||
|
||||
// configure our base memory accessors
|
||||
debug_cpu_configure_memory(*machine, *global->symtable);
|
||||
|
||||
/* add "wpaddr", "wpdata", "cycles", "cpunum", "logunmap" to the global symbol table */
|
||||
symtable_add_register(global->symtable, "wpaddr", NULL, get_wpaddr, NULL);
|
||||
symtable_add_register(global->symtable, "wpdata", NULL, get_wpdata, NULL);
|
||||
symtable_add_register(global->symtable, "cpunum", NULL, get_cpunum, NULL);
|
||||
symtable_add_register(global->symtable, "beamx", (void *)first_screen, get_beamx, NULL);
|
||||
symtable_add_register(global->symtable, "beamy", (void *)first_screen, get_beamy, NULL);
|
||||
symtable_add_register(global->symtable, "frame", (void *)first_screen, get_frame, NULL);
|
||||
global->symtable->add("wpaddr", symbol_table::READ_ONLY, &global->wpaddr);
|
||||
global->symtable->add("wpdata", symbol_table::READ_ONLY, &global->wpdata);
|
||||
global->symtable->add("cpunum", NULL, get_cpunum);
|
||||
global->symtable->add("beamx", (void *)first_screen, get_beamx);
|
||||
global->symtable->add("beamy", (void *)first_screen, get_beamy);
|
||||
global->symtable->add("frame", (void *)first_screen, get_frame);
|
||||
|
||||
/* add the temporary variables to the global symbol table */
|
||||
for (regnum = 0; regnum < NUM_TEMP_VARIABLES; regnum++)
|
||||
{
|
||||
char symname[10];
|
||||
sprintf(symname, "temp%d", regnum);
|
||||
symtable_add_register(global->symtable, symname, &global->tempvar[regnum], get_tempvar, set_tempvar);
|
||||
global->symtable->add(symname, symbol_table::READ_WRITE, &global->tempvar[regnum]);
|
||||
}
|
||||
|
||||
/* first CPU is visible by default */
|
||||
@ -199,6 +185,12 @@ void debug_cpu_init(running_machine *machine)
|
||||
}
|
||||
|
||||
|
||||
void debug_cpu_configure_memory(running_machine &machine, symbol_table &table)
|
||||
{
|
||||
table.configure_memory(&machine, expression_validate, expression_read_memory, expression_write_memory);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
debug_cpu_flush_traces - flushes all traces;
|
||||
this is useful if a trace is going on when we
|
||||
@ -277,7 +269,7 @@ symbol_table *debug_cpu_get_global_symtable(running_machine *machine)
|
||||
|
||||
symbol_table *debug_cpu_get_visible_symtable(running_machine *machine)
|
||||
{
|
||||
return machine->debugcpu_data->visiblecpu->debug()->symtable();
|
||||
return &machine->debugcpu_data->visiblecpu->debug()->symtable();
|
||||
}
|
||||
|
||||
|
||||
@ -1071,8 +1063,8 @@ static void debug_cpu_exit(running_machine &machine)
|
||||
debugcpu_private *global = machine.debugcpu_data;
|
||||
|
||||
/* free the global symbol table */
|
||||
if (global != NULL && global->symtable != NULL)
|
||||
symtable_free(global->symtable);
|
||||
if (global != NULL)
|
||||
global_free(global->symtable);
|
||||
}
|
||||
|
||||
|
||||
@ -1523,7 +1515,7 @@ static void expression_write_memory_region(running_machine *machine, const char
|
||||
appropriate name
|
||||
-------------------------------------------------*/
|
||||
|
||||
static EXPRERR expression_validate(void *param, const char *name, int space)
|
||||
static expression_error::error_code expression_validate(void *param, const char *name, int space)
|
||||
{
|
||||
running_machine *machine = (running_machine *)param;
|
||||
device_t *device = NULL;
|
||||
@ -1538,12 +1530,12 @@ static EXPRERR expression_validate(void *param, const char *name, int space)
|
||||
{
|
||||
device = expression_get_device(machine, name);
|
||||
if (device == NULL)
|
||||
return EXPRERR_INVALID_MEMORY_NAME;
|
||||
return expression_error::INVALID_MEMORY_NAME;
|
||||
}
|
||||
if (device == NULL)
|
||||
device = debug_cpu_get_visible_cpu(machine);
|
||||
if (cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL)) == NULL)
|
||||
return EXPRERR_NO_SUCH_MEMORY_SPACE;
|
||||
return expression_error::NO_SUCH_MEMORY_SPACE;
|
||||
break;
|
||||
|
||||
case EXPSPACE_PROGRAM_PHYSICAL:
|
||||
@ -1554,12 +1546,12 @@ static EXPRERR expression_validate(void *param, const char *name, int space)
|
||||
{
|
||||
device = expression_get_device(machine, name);
|
||||
if (device == NULL)
|
||||
return EXPRERR_INVALID_MEMORY_NAME;
|
||||
return expression_error::INVALID_MEMORY_NAME;
|
||||
}
|
||||
if (device == NULL)
|
||||
device = debug_cpu_get_visible_cpu(machine);
|
||||
if (cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL)) == NULL)
|
||||
return EXPRERR_NO_SUCH_MEMORY_SPACE;
|
||||
return expression_error::NO_SUCH_MEMORY_SPACE;
|
||||
break;
|
||||
|
||||
case EXPSPACE_OPCODE:
|
||||
@ -1568,22 +1560,22 @@ static EXPRERR expression_validate(void *param, const char *name, int space)
|
||||
{
|
||||
device = expression_get_device(machine, name);
|
||||
if (device == NULL)
|
||||
return EXPRERR_INVALID_MEMORY_NAME;
|
||||
return expression_error::INVALID_MEMORY_NAME;
|
||||
}
|
||||
if (device == NULL)
|
||||
device = debug_cpu_get_visible_cpu(machine);
|
||||
if (cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM) == NULL)
|
||||
return EXPRERR_NO_SUCH_MEMORY_SPACE;
|
||||
return expression_error::NO_SUCH_MEMORY_SPACE;
|
||||
break;
|
||||
|
||||
case EXPSPACE_REGION:
|
||||
if (name == NULL)
|
||||
return EXPRERR_MISSING_MEMORY_NAME;
|
||||
return expression_error::MISSING_MEMORY_NAME;
|
||||
if (memory_region(machine, name) == NULL)
|
||||
return EXPRERR_INVALID_MEMORY_NAME;
|
||||
return expression_error::INVALID_MEMORY_NAME;
|
||||
break;
|
||||
}
|
||||
return EXPRERR_NONE;
|
||||
return expression_error::NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -1596,7 +1588,7 @@ static EXPRERR expression_validate(void *param, const char *name, int space)
|
||||
get_beamx - get beam horizontal position
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_beamx(void *globalref, void *ref)
|
||||
static UINT64 get_beamx(symbol_table &table, void *ref)
|
||||
{
|
||||
screen_device *screen = reinterpret_cast<screen_device *>(ref);
|
||||
return (screen != NULL) ? screen->hpos() : 0;
|
||||
@ -1607,7 +1599,7 @@ static UINT64 get_beamx(void *globalref, void *ref)
|
||||
get_beamy - get beam vertical position
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_beamy(void *globalref, void *ref)
|
||||
static UINT64 get_beamy(symbol_table &table, void *ref)
|
||||
{
|
||||
screen_device *screen = reinterpret_cast<screen_device *>(ref);
|
||||
return (screen != NULL) ? screen->vpos() : 0;
|
||||
@ -1618,67 +1610,21 @@ static UINT64 get_beamy(void *globalref, void *ref)
|
||||
get_frame - get current frame number
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_frame(void *globalref, void *ref)
|
||||
static UINT64 get_frame(symbol_table &table, void *ref)
|
||||
{
|
||||
screen_device *screen = reinterpret_cast<screen_device *>(ref);
|
||||
return (screen != NULL) ? screen->frame_number() : 0;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_tempvar - getter callback for the
|
||||
'tempX' symbols
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_tempvar(void *globalref, void *ref)
|
||||
{
|
||||
return *(UINT64 *)ref;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
set_tempvar - setter callback for the
|
||||
'tempX' symbols
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void set_tempvar(void *globalref, void *ref, UINT64 value)
|
||||
{
|
||||
*(UINT64 *)ref = value;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_wpaddr - getter callback for the
|
||||
'wpaddr' symbol
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_wpaddr(void *globalref, void *ref)
|
||||
{
|
||||
running_machine *machine = (running_machine *)globalref;
|
||||
return machine->debugcpu_data->wpaddr;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_wpdata - getter callback for the
|
||||
'wpdata' symbol
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_wpdata(void *globalref, void *ref)
|
||||
{
|
||||
running_machine *machine = (running_machine *)globalref;
|
||||
return machine->debugcpu_data->wpdata;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_cpunum - getter callback for the
|
||||
'cpunum' symbol
|
||||
-------------------------------------------------*/
|
||||
|
||||
static UINT64 get_cpunum(void *globalref, void *ref)
|
||||
static UINT64 get_cpunum(symbol_table &table, void *ref)
|
||||
{
|
||||
running_machine *machine = (running_machine *)globalref;
|
||||
running_machine *machine = reinterpret_cast<running_machine *>(table.globalref());
|
||||
device_t *target = machine->debugcpu_data->visiblecpu;
|
||||
|
||||
device_execute_interface *exec = NULL;
|
||||
@ -1709,7 +1655,7 @@ device_debug::device_debug(device_t &device)
|
||||
m_state(NULL),
|
||||
m_disasm(NULL),
|
||||
m_flags(0),
|
||||
m_symtable(symtable_alloc(debug_cpu_get_global_symtable(device.machine), (void *)&device)),
|
||||
m_symtable(&device, debug_cpu_get_global_symtable(device.machine)),
|
||||
m_instrhook(NULL),
|
||||
m_dasm_override(NULL),
|
||||
m_opwidth(0),
|
||||
@ -1741,23 +1687,23 @@ device_debug::device_debug(device_t &device)
|
||||
{
|
||||
// add a global symbol for the current instruction pointer
|
||||
if (m_exec != NULL)
|
||||
symtable_add_register(m_symtable, "cycles", NULL, get_cycles, NULL);
|
||||
m_symtable.add("cycles", NULL, get_cycles);
|
||||
|
||||
// add entries to enable/disable unmap reporting for each space
|
||||
if (m_memory != NULL)
|
||||
{
|
||||
if (m_memory->space(AS_PROGRAM) != NULL)
|
||||
symtable_add_register(m_symtable, "logunmap", (void *)m_memory->space(AS_PROGRAM), get_logunmap, set_logunmap);
|
||||
m_symtable.add("logunmap", (void *)m_memory->space(AS_PROGRAM), get_logunmap, set_logunmap);
|
||||
if (m_memory->space(AS_DATA) != NULL)
|
||||
symtable_add_register(m_symtable, "logunmapd", (void *)m_memory->space(AS_DATA), get_logunmap, set_logunmap);
|
||||
m_symtable.add("logunmapd", (void *)m_memory->space(AS_DATA), get_logunmap, set_logunmap);
|
||||
if (m_memory->space(AS_IO) != NULL)
|
||||
symtable_add_register(m_symtable, "logunmapi", (void *)m_memory->space(AS_IO), get_logunmap, set_logunmap);
|
||||
m_symtable.add("logunmapi", (void *)m_memory->space(AS_IO), get_logunmap, set_logunmap);
|
||||
}
|
||||
|
||||
// add all registers into it
|
||||
astring tempstr;
|
||||
for (const device_state_entry *entry = m_state->state_first(); entry != NULL; entry = entry->next())
|
||||
symtable_add_register(m_symtable, tempstr.cpy(entry->symbol()).tolower(), (void *)(FPTR)entry->index(), get_cpu_reg, set_state);
|
||||
m_symtable.add(tempstr.cpy(entry->symbol()).tolower(), (void *)(FPTR)entry->index(), get_state, set_state);
|
||||
}
|
||||
|
||||
// set up execution-related stuff
|
||||
@ -1767,8 +1713,8 @@ device_debug::device_debug(device_t &device)
|
||||
m_opwidth = min_opcode_bytes();
|
||||
|
||||
// if no curpc, add one
|
||||
if (m_state != NULL && symtable_find(m_symtable, "curpc") == NULL)
|
||||
symtable_add_register(m_symtable, "curpc", NULL, get_current_pc, 0);
|
||||
if (m_state != NULL && m_symtable.find("curpc") == NULL)
|
||||
m_symtable.add("curpc", NULL, get_current_pc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1779,10 +1725,6 @@ device_debug::device_debug(device_t &device)
|
||||
|
||||
device_debug::~device_debug()
|
||||
{
|
||||
// free the symbol table
|
||||
if (m_symtable != NULL)
|
||||
symtable_free(m_symtable);
|
||||
|
||||
// free breakpoints and watchpoints
|
||||
breakpoint_clear_all();
|
||||
watchpoint_clear_all();
|
||||
@ -2337,10 +2279,10 @@ void device_debug::halt_on_next_instruction(const char *fmt, ...)
|
||||
// returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::breakpoint_set(offs_t address, parsed_expression *condition, const char *action)
|
||||
int device_debug::breakpoint_set(offs_t address, const char *condition, const char *action)
|
||||
{
|
||||
// allocate a new one
|
||||
breakpoint *bp = auto_alloc(m_device.machine, breakpoint(m_device.machine->debugcpu_data->bpindex++, address, condition, action));
|
||||
breakpoint *bp = auto_alloc(m_device.machine, breakpoint(m_symtable, m_device.machine->debugcpu_data->bpindex++, address, condition, action));
|
||||
|
||||
// hook it into our list
|
||||
bp->m_next = m_bplist;
|
||||
@ -2426,12 +2368,12 @@ void device_debug::breakpoint_enable_all(bool enable)
|
||||
// returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::watchpoint_set(address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition, const char *action)
|
||||
int device_debug::watchpoint_set(address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action)
|
||||
{
|
||||
assert(space.spacenum() < ARRAY_LENGTH(m_wplist));
|
||||
|
||||
// allocate a new one
|
||||
watchpoint *wp = auto_alloc(m_device.machine, watchpoint(m_device.machine->debugcpu_data->bpindex++, space, type, address, length, condition, action));
|
||||
watchpoint *wp = auto_alloc(m_device.machine, watchpoint(m_symtable, m_device.machine->debugcpu_data->bpindex++, space, type, address, length, condition, action));
|
||||
|
||||
// hook it into our list
|
||||
wp->m_next = m_wplist[space.spacenum()];
|
||||
@ -3115,9 +3057,9 @@ UINT32 device_debug::dasm_wrapped(astring &buffer, offs_t pc)
|
||||
// current instruction pointer
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 device_debug::get_current_pc(void *globalref, void *ref)
|
||||
UINT64 device_debug::get_current_pc(symbol_table &table, void *ref)
|
||||
{
|
||||
device_t *device = reinterpret_cast<device_t *>(globalref);
|
||||
device_t *device = reinterpret_cast<device_t *>(table.globalref());
|
||||
return device->debug()->pc();
|
||||
}
|
||||
|
||||
@ -3127,9 +3069,9 @@ UINT64 device_debug::get_current_pc(void *globalref, void *ref)
|
||||
// 'cycles' symbol
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 device_debug::get_cycles(void *globalref, void *ref)
|
||||
UINT64 device_debug::get_cycles(symbol_table &table, void *ref)
|
||||
{
|
||||
device_t *device = reinterpret_cast<device_t *>(globalref);
|
||||
device_t *device = reinterpret_cast<device_t *>(table.globalref());
|
||||
return device->debug()->m_exec->cycles_remaining();
|
||||
}
|
||||
|
||||
@ -3139,9 +3081,9 @@ UINT64 device_debug::get_cycles(void *globalref, void *ref)
|
||||
// symbols
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 device_debug::get_logunmap(void *globalref, void *ref)
|
||||
UINT64 device_debug::get_logunmap(symbol_table &table, void *ref)
|
||||
{
|
||||
address_space *space = reinterpret_cast<address_space *>(ref);
|
||||
address_space *space = reinterpret_cast<address_space *>(table.globalref());
|
||||
return space->log_unmap();
|
||||
}
|
||||
|
||||
@ -3151,9 +3093,9 @@ UINT64 device_debug::get_logunmap(void *globalref, void *ref)
|
||||
// symbols
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::set_logunmap(void *globalref, void *ref, UINT64 value)
|
||||
void device_debug::set_logunmap(symbol_table &table, void *ref, UINT64 value)
|
||||
{
|
||||
address_space *space = reinterpret_cast<address_space *>(ref);
|
||||
address_space *space = reinterpret_cast<address_space *>(table.globalref());
|
||||
space->set_log_unmap(value ? true : false);
|
||||
}
|
||||
|
||||
@ -3163,9 +3105,9 @@ void device_debug::set_logunmap(void *globalref, void *ref, UINT64 value)
|
||||
// state symbols
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT64 device_debug::get_cpu_reg(void *globalref, void *ref)
|
||||
UINT64 device_debug::get_state(symbol_table &table, void *ref)
|
||||
{
|
||||
device_t *device = reinterpret_cast<device_t *>(globalref);
|
||||
device_t *device = reinterpret_cast<device_t *>(table.globalref());
|
||||
return device->debug()->m_state->state(reinterpret_cast<FPTR>(ref));
|
||||
}
|
||||
|
||||
@ -3175,9 +3117,9 @@ UINT64 device_debug::get_cpu_reg(void *globalref, void *ref)
|
||||
// state symbols
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::set_state(void *globalref, void *ref, UINT64 value)
|
||||
void device_debug::set_state(symbol_table &table, void *ref, UINT64 value)
|
||||
{
|
||||
device_t *device = reinterpret_cast<device_t *>(globalref);
|
||||
device_t *device = reinterpret_cast<device_t *>(table.globalref());
|
||||
device->debug()->m_state->set_state(reinterpret_cast<FPTR>(ref), value);
|
||||
}
|
||||
|
||||
@ -3191,28 +3133,17 @@ void device_debug::set_state(void *globalref, void *ref, UINT64 value)
|
||||
// breakpoint - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_debug::breakpoint::breakpoint(int index, offs_t address, parsed_expression *condition, const char *action)
|
||||
device_debug::breakpoint::breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition, const char *action)
|
||||
: m_next(NULL),
|
||||
m_index(index),
|
||||
m_enabled(true),
|
||||
m_address(address),
|
||||
m_condition(condition),
|
||||
m_condition(&symbols, (condition != NULL) ? condition : "1"),
|
||||
m_action((action != NULL) ? action : "")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~breakpoint - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_debug::breakpoint::~breakpoint()
|
||||
{
|
||||
if (m_condition != NULL)
|
||||
expression_free(m_condition);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// hit - detect a hit
|
||||
//-------------------------------------------------
|
||||
@ -3228,9 +3159,17 @@ bool device_debug::breakpoint::hit(offs_t pc)
|
||||
return false;
|
||||
|
||||
// must satisfy the condition
|
||||
UINT64 result;
|
||||
if (m_condition != NULL && expression_execute(m_condition, &result) == EXPRERR_NONE && result == 0)
|
||||
return false;
|
||||
if (!m_condition.is_empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
return (m_condition.execute() != 0);
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3245,7 +3184,7 @@ bool device_debug::breakpoint::hit(offs_t pc)
|
||||
// watchpoint - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_debug::watchpoint::watchpoint(int index, address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition, const char *action)
|
||||
device_debug::watchpoint::watchpoint(symbol_table &symbols, int index, address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action)
|
||||
: m_next(NULL),
|
||||
m_space(space),
|
||||
m_index(index),
|
||||
@ -3253,23 +3192,12 @@ device_debug::watchpoint::watchpoint(int index, address_space &space, int type,
|
||||
m_type(type),
|
||||
m_address(space.address_to_byte(address) & space.bytemask()),
|
||||
m_length(space.address_to_byte(length)),
|
||||
m_condition(condition),
|
||||
m_condition(&symbols, (condition != NULL) ? condition : "1"),
|
||||
m_action((action != NULL) ? action : "")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~watchpoint - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_debug::watchpoint::~watchpoint()
|
||||
{
|
||||
if (m_condition != NULL)
|
||||
expression_free(m_condition);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// hit - detect a hit
|
||||
//-------------------------------------------------
|
||||
@ -3289,10 +3217,17 @@ bool device_debug::watchpoint::hit(int type, offs_t address, int size)
|
||||
return false;
|
||||
|
||||
// must satisfy the condition
|
||||
UINT64 result;
|
||||
if (m_condition != NULL && expression_execute(m_condition, &result) == EXPRERR_NONE && result == 0)
|
||||
return false;
|
||||
|
||||
if (!m_condition.is_empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
return (m_condition.execute() != 0);
|
||||
}
|
||||
catch (expression_error &err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -79,15 +79,14 @@ public:
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
breakpoint(int index, offs_t address, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~breakpoint();
|
||||
breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition = NULL, const char *action = NULL);
|
||||
|
||||
// getters
|
||||
breakpoint *next() const { return m_next; }
|
||||
int index() const { return m_index; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *condition() const { return m_condition.original_string(); }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
@ -98,7 +97,7 @@ public:
|
||||
int m_index; // user reported index
|
||||
UINT8 m_enabled; // enabled?
|
||||
offs_t m_address; // execution address
|
||||
parsed_expression * m_condition; // condition
|
||||
parsed_expression m_condition; // condition
|
||||
astring m_action; // action
|
||||
};
|
||||
|
||||
@ -109,8 +108,7 @@ public:
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
watchpoint(int index, address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~watchpoint();
|
||||
watchpoint(symbol_table &symbols, int index, address_space &space, int type, offs_t address, offs_t length, const char *condition = NULL, const char *action = NULL);
|
||||
|
||||
// getters
|
||||
watchpoint *next() const { return m_next; }
|
||||
@ -120,7 +118,7 @@ public:
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
offs_t length() const { return m_length; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *condition() const { return m_condition.original_string(); }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
@ -134,7 +132,7 @@ public:
|
||||
UINT8 m_type; // type (read/write)
|
||||
offs_t m_address; // start address
|
||||
offs_t m_length; // length of watch area
|
||||
parsed_expression * m_condition; // condition
|
||||
parsed_expression m_condition; // condition
|
||||
astring m_action; // action
|
||||
};
|
||||
|
||||
@ -144,7 +142,7 @@ public:
|
||||
~device_debug();
|
||||
|
||||
// getters
|
||||
symbol_table *symtable() const { return m_symtable; }
|
||||
symbol_table &symtable() { return m_symtable; }
|
||||
|
||||
// commonly-used pass-throughs
|
||||
offs_t pc() const { return (m_state != NULL) ? m_state->pc() : 0; }
|
||||
@ -188,7 +186,7 @@ public:
|
||||
|
||||
// breakpoints
|
||||
breakpoint *breakpoint_first() const { return m_bplist; }
|
||||
int breakpoint_set(offs_t address, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
int breakpoint_set(offs_t address, const char *condition = NULL, const char *action = NULL);
|
||||
bool breakpoint_clear(int index);
|
||||
void breakpoint_clear_all();
|
||||
bool breakpoint_enable(int index, bool enable = true);
|
||||
@ -196,7 +194,7 @@ public:
|
||||
|
||||
// watchpoints
|
||||
watchpoint *watchpoint_first(int spacenum) const { return m_wplist[spacenum]; }
|
||||
int watchpoint_set(address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition, const char *action);
|
||||
int watchpoint_set(address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action);
|
||||
bool watchpoint_clear(int wpnum);
|
||||
void watchpoint_clear_all();
|
||||
bool watchpoint_enable(int index, bool enable = true);
|
||||
@ -243,12 +241,12 @@ private:
|
||||
void hotspot_check(address_space &space, offs_t address);
|
||||
|
||||
// symbol get/set callbacks
|
||||
static UINT64 get_current_pc(void *globalref, void *ref);
|
||||
static UINT64 get_cycles(void *globalref, void *ref);
|
||||
static UINT64 get_logunmap(void *globalref, void *ref);
|
||||
static void set_logunmap(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 get_cpu_reg(void *globalref, void *ref);
|
||||
static void set_state(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 get_current_pc(symbol_table &table, void *ref);
|
||||
static UINT64 get_cycles(symbol_table &table, void *ref);
|
||||
static UINT64 get_logunmap(symbol_table &table, void *ref);
|
||||
static void set_logunmap(symbol_table &table, void *ref, UINT64 value);
|
||||
static UINT64 get_state(symbol_table &table, void *ref);
|
||||
static void set_state(symbol_table &table, void *ref, UINT64 value);
|
||||
|
||||
// basic device information
|
||||
device_t & m_device; // device we are attached to
|
||||
@ -259,7 +257,7 @@ private:
|
||||
|
||||
// global state
|
||||
UINT32 m_flags; // debugging flags for this CPU
|
||||
symbol_table * m_symtable; // symbol table for expression evaluation
|
||||
symbol_table m_symtable; // symbol table for expression evaluation
|
||||
debug_instruction_hook_func m_instrhook; // per-instruction callback hook
|
||||
|
||||
// disassembly
|
||||
@ -366,14 +364,6 @@ private:
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
extern const express_callbacks debug_expression_callbacks;
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// FUNCTION PROTOTYPES
|
||||
//**************************************************************************
|
||||
@ -382,6 +372,7 @@ extern const express_callbacks debug_expression_callbacks;
|
||||
|
||||
/* initialize the CPU tracking for the debugger */
|
||||
void debug_cpu_init(running_machine *machine);
|
||||
void debug_cpu_configure_memory(running_machine &machine, symbol_table &table);
|
||||
|
||||
/* flushes all traces; this is useful if a trace is going on when we fatalerror */
|
||||
void debug_cpu_flush_traces(running_machine *machine);
|
||||
|
@ -38,6 +38,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "express.h"
|
||||
#include "debugvw.h"
|
||||
#include "dvtext.h"
|
||||
#include "dvstate.h"
|
||||
@ -46,7 +47,6 @@
|
||||
#include "debugcmd.h"
|
||||
#include "debugcpu.h"
|
||||
#include "debugcon.h"
|
||||
#include "express.h"
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
@ -559,9 +559,8 @@ debug_view_expression::debug_view_expression(running_machine &machine)
|
||||
: m_machine(machine),
|
||||
m_dirty(true),
|
||||
m_result(0),
|
||||
m_parsed(NULL),
|
||||
m_string("0"),
|
||||
m_context(debug_cpu_get_global_symtable(&machine))
|
||||
m_parsed(debug_cpu_get_global_symtable(&machine)),
|
||||
m_string("0")
|
||||
{
|
||||
}
|
||||
|
||||
@ -572,20 +571,6 @@ debug_view_expression::debug_view_expression(running_machine &machine)
|
||||
|
||||
debug_view_expression::~debug_view_expression()
|
||||
{
|
||||
// free our parsed expression
|
||||
if (m_parsed != NULL)
|
||||
expression_free(m_parsed);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_string - set the expression string
|
||||
//-------------------------------------------------
|
||||
|
||||
void debug_view_expression::set_string(const char *string)
|
||||
{
|
||||
m_string = string;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
|
||||
@ -596,7 +581,7 @@ void debug_view_expression::set_string(const char *string)
|
||||
|
||||
void debug_view_expression::set_context(symbol_table *context)
|
||||
{
|
||||
m_context = (context != NULL) ? context : debug_cpu_get_global_symtable(&m_machine);
|
||||
m_parsed.set_symbols((context != NULL) ? context : debug_cpu_get_global_symtable(&m_machine));
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -613,28 +598,33 @@ bool debug_view_expression::recompute()
|
||||
// if dirty, re-evaluate
|
||||
if (m_dirty)
|
||||
{
|
||||
// parse the new expression
|
||||
parsed_expression *expr;
|
||||
EXPRERR exprerr = expression_parse(m_string, m_context, &debug_expression_callbacks, &m_machine, &expr);
|
||||
|
||||
// if it worked, update the expression
|
||||
if (exprerr == EXPRERR_NONE)
|
||||
astring oldstring(m_parsed.original_string());
|
||||
try
|
||||
{
|
||||
if (m_parsed != NULL)
|
||||
expression_free(m_parsed);
|
||||
m_parsed = expr;
|
||||
m_parsed.parse(m_string);
|
||||
}
|
||||
catch (expression_error &)
|
||||
{
|
||||
m_parsed.parse(oldstring);
|
||||
}
|
||||
}
|
||||
|
||||
// if we have a parsed expression, evalute it
|
||||
if (m_parsed != NULL)
|
||||
if (!m_parsed.is_empty())
|
||||
{
|
||||
UINT64 oldresult = m_result;
|
||||
|
||||
// recompute the value of the expression
|
||||
expression_execute(m_parsed, &m_result);
|
||||
if (m_result != oldresult)
|
||||
changed = true;
|
||||
try
|
||||
{
|
||||
UINT64 newresult = m_parsed.execute();
|
||||
if (newresult != m_result)
|
||||
{
|
||||
m_result = newresult;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
catch (expression_error &)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// expression no longer dirty by definition
|
||||
|
@ -40,6 +40,8 @@
|
||||
#ifndef __DEBUGVIEW_H__
|
||||
#define __DEBUGVIEW_H__
|
||||
|
||||
#include "express.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
@ -102,8 +104,6 @@ const int DCH_CTRLLEFT = 12; // ctrl+left
|
||||
|
||||
// forward references
|
||||
class debug_view;
|
||||
typedef struct _symbol_table symbol_table;
|
||||
typedef struct _parsed_expression parsed_expression;
|
||||
|
||||
|
||||
// OSD callback function for a view
|
||||
@ -305,11 +305,11 @@ public:
|
||||
UINT64 last_value() const { return m_result; }
|
||||
UINT64 value() { recompute(); return m_result; }
|
||||
const char *string() const { return m_string; }
|
||||
symbol_table *context() const { return m_context; }
|
||||
symbol_table *context() const { return m_parsed.symbols(); }
|
||||
|
||||
// setters
|
||||
void mark_dirty() { m_dirty = true; }
|
||||
void set_string(const char *string);
|
||||
void set_string(const char *string) { m_string.cpy(string); m_dirty = true; }
|
||||
void set_context(symbol_table *context);
|
||||
|
||||
private:
|
||||
@ -320,9 +320,8 @@ private:
|
||||
running_machine & m_machine; // reference to the machine
|
||||
bool m_dirty; // true if the expression needs to be re-evaluated
|
||||
UINT64 m_result; // last result from the expression
|
||||
parsed_expression * m_parsed; // parsed expression data
|
||||
parsed_expression m_parsed; // parsed expression data
|
||||
astring m_string; // copy of the expression string
|
||||
symbol_table * m_context; // context we are using
|
||||
};
|
||||
|
||||
|
||||
|
@ -156,7 +156,7 @@ void debug_view_disasm::view_notify(debug_view_notification type)
|
||||
adjust_visible_y_for_cursor();
|
||||
|
||||
else if (type == VIEW_NOTIFY_SOURCE_CHANGED)
|
||||
m_expression.set_context(downcast<const debug_view_disasm_source *>(m_source)->device().debug()->symtable());
|
||||
m_expression.set_context(&downcast<const debug_view_disasm_source *>(m_source)->device().debug()->symtable());
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +213,7 @@ void debug_view_memory::view_notify(debug_view_notification type)
|
||||
m_chunks_per_row = m_bytes_per_chunk * m_chunks_per_row / source.m_prefsize;
|
||||
m_bytes_per_chunk = source.m_prefsize;
|
||||
if (source.m_space != NULL)
|
||||
m_expression.set_context(source.m_space->cpu->debug()->symtable());
|
||||
m_expression.set_context(&source.m_space->cpu->debug()->symtable());
|
||||
else
|
||||
m_expression.set_context(NULL);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,193 +1,412 @@
|
||||
/***************************************************************************
|
||||
|
||||
express.h
|
||||
|
||||
Generic expressions engine.
|
||||
Written by Aaron Giles
|
||||
|
||||
****************************************************************************
|
||||
|
||||
Copyright Aaron Giles
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EXPRESS_H__
|
||||
#define __EXPRESS_H__
|
||||
|
||||
#include "osdcore.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
/* maximum number of parameters in a function call */
|
||||
#define MAX_FUNCTION_PARAMS (16)
|
||||
|
||||
/* values for symbol_entry.type */
|
||||
#define SMT_REGISTER (0)
|
||||
#define SMT_FUNCTION (1)
|
||||
#define SMT_VALUE (2)
|
||||
|
||||
/* values for the error code in an expression error */
|
||||
#define EXPRERR_NONE (0)
|
||||
#define EXPRERR_NOT_LVAL (1)
|
||||
#define EXPRERR_NOT_RVAL (2)
|
||||
#define EXPRERR_SYNTAX (3)
|
||||
#define EXPRERR_UNKNOWN_SYMBOL (4)
|
||||
#define EXPRERR_INVALID_NUMBER (5)
|
||||
#define EXPRERR_INVALID_TOKEN (6)
|
||||
#define EXPRERR_STACK_OVERFLOW (7)
|
||||
#define EXPRERR_STACK_UNDERFLOW (8)
|
||||
#define EXPRERR_UNBALANCED_PARENS (9)
|
||||
#define EXPRERR_DIVIDE_BY_ZERO (10)
|
||||
#define EXPRERR_OUT_OF_MEMORY (11)
|
||||
#define EXPRERR_INVALID_PARAM_COUNT (12)
|
||||
#define EXPRERR_UNBALANCED_QUOTES (13)
|
||||
#define EXPRERR_TOO_MANY_STRINGS (14)
|
||||
#define EXPRERR_INVALID_MEMORY_SIZE (15)
|
||||
#define EXPRERR_INVALID_MEMORY_SPACE (16)
|
||||
#define EXPRERR_NO_SUCH_MEMORY_SPACE (17)
|
||||
#define EXPRERR_INVALID_MEMORY_NAME (18)
|
||||
#define EXPRERR_MISSING_MEMORY_NAME (19)
|
||||
|
||||
/* values for the address space passed to external_read/write_memory */
|
||||
#define EXPSPACE_PROGRAM_LOGICAL (0)
|
||||
#define EXPSPACE_DATA_LOGICAL (1)
|
||||
#define EXPSPACE_IO_LOGICAL (2)
|
||||
#define EXPSPACE_SPACE3_LOGICAL (3)
|
||||
#define EXPSPACE_PROGRAM_PHYSICAL (4)
|
||||
#define EXPSPACE_DATA_PHYSICAL (5)
|
||||
#define EXPSPACE_IO_PHYSICAL (6)
|
||||
#define EXPSPACE_SPACE3_PHYSICAL (7)
|
||||
#define EXPSPACE_OPCODE (8)
|
||||
#define EXPSPACE_RAMWRITE (9)
|
||||
#define EXPSPACE_REGION (10)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
/* expression error assembly/disassembly macros */
|
||||
#define EXPRERR_ERROR_CLASS(x) ((x) >> 16)
|
||||
#define EXPRERR_ERROR_OFFSET(x) ((x) & 0xffff)
|
||||
#define MAKE_EXPRERR(a,b) (((a) << 16) | ((b) & 0xffff))
|
||||
|
||||
/* macros to assemble specific error conditions */
|
||||
#define MAKE_EXPRERR_NOT_LVAL(x) MAKE_EXPRERR(EXPRERR_NOT_LVAL, (x))
|
||||
#define MAKE_EXPRERR_NOT_RVAL(x) MAKE_EXPRERR(EXPRERR_NOT_RVAL, (x))
|
||||
#define MAKE_EXPRERR_SYNTAX(x) MAKE_EXPRERR(EXPRERR_SYNTAX, (x))
|
||||
#define MAKE_EXPRERR_UNKNOWN_SYMBOL(x) MAKE_EXPRERR(EXPRERR_UNKNOWN_SYMBOL, (x))
|
||||
#define MAKE_EXPRERR_INVALID_NUMBER(x) MAKE_EXPRERR(EXPRERR_INVALID_NUMBER, (x))
|
||||
#define MAKE_EXPRERR_INVALID_TOKEN(x) MAKE_EXPRERR(EXPRERR_INVALID_TOKEN, (x))
|
||||
#define MAKE_EXPRERR_STACK_OVERFLOW(x) MAKE_EXPRERR(EXPRERR_STACK_OVERFLOW, (x))
|
||||
#define MAKE_EXPRERR_STACK_UNDERFLOW(x) MAKE_EXPRERR(EXPRERR_STACK_UNDERFLOW, (x))
|
||||
#define MAKE_EXPRERR_UNBALANCED_PARENS(x) MAKE_EXPRERR(EXPRERR_UNBALANCED_PARENS, (x))
|
||||
#define MAKE_EXPRERR_DIVIDE_BY_ZERO(x) MAKE_EXPRERR(EXPRERR_DIVIDE_BY_ZERO, (x))
|
||||
#define MAKE_EXPRERR_OUT_OF_MEMORY(x) MAKE_EXPRERR(EXPRERR_OUT_OF_MEMORY, (x))
|
||||
#define MAKE_EXPRERR_INVALID_PARAM_COUNT(x) MAKE_EXPRERR(EXPRERR_INVALID_PARAM_COUNT, (x))
|
||||
#define MAKE_EXPRERR_UNBALANCED_QUOTES(x) MAKE_EXPRERR(EXPRERR_UNBALANCED_QUOTES, (x))
|
||||
#define MAKE_EXPRERR_TOO_MANY_STRINGS(x) MAKE_EXPRERR(EXPRERR_TOO_MANY_STRINGS, (x))
|
||||
#define MAKE_EXPRERR_INVALID_MEMORY_SIZE(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_SIZE, (x))
|
||||
#define MAKE_EXPRERR_NO_SUCH_MEMORY_SPACE(x) MAKE_EXPRERR(EXPRERR_NO_SUCH_MEMORY_SPACE, (x))
|
||||
#define MAKE_EXPRERR_INVALID_MEMORY_SPACE(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_SPACE, (x))
|
||||
#define MAKE_EXPRERR_INVALID_MEMORY_NAME(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_NAME, (x))
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* EXPRERR is an error code for expression evaluation */
|
||||
typedef UINT32 EXPRERR;
|
||||
|
||||
|
||||
/* callback functions for getting/setting a symbol value */
|
||||
typedef UINT64 (*symbol_getter_func)(void *globalref, void *symref);
|
||||
typedef void (*symbol_setter_func)(void *globalref, void *symref, UINT64 value);
|
||||
|
||||
/* callback function for execution a function */
|
||||
typedef UINT64 (*function_execute_func)(void *globalref, void *symref, UINT32 numparams, const UINT64 *paramlist);
|
||||
|
||||
/* callback function for memory reads/writes */
|
||||
typedef UINT64 (*express_read_func)(void *cbparam, const char *name, int space, UINT32 offset, int size);
|
||||
typedef void (*express_write_func)(void *cbparam, const char *name, int space, UINT32 offset, int size, UINT64 value);
|
||||
typedef EXPRERR (*express_valid_func)(void *cbparam, const char *name, int space);
|
||||
|
||||
|
||||
/* callback parameter for executing expressions */
|
||||
typedef struct _express_callbacks express_callbacks;
|
||||
struct _express_callbacks
|
||||
// values for the address space passed to external_read/write_memory
|
||||
enum expression_space
|
||||
{
|
||||
express_read_func read; /* read callback */
|
||||
express_write_func write; /* write callback */
|
||||
express_valid_func valid; /* validation callback */
|
||||
EXPSPACE_INVALID,
|
||||
EXPSPACE_PROGRAM_LOGICAL,
|
||||
EXPSPACE_DATA_LOGICAL,
|
||||
EXPSPACE_IO_LOGICAL,
|
||||
EXPSPACE_SPACE3_LOGICAL,
|
||||
EXPSPACE_PROGRAM_PHYSICAL,
|
||||
EXPSPACE_DATA_PHYSICAL,
|
||||
EXPSPACE_IO_PHYSICAL,
|
||||
EXPSPACE_SPACE3_PHYSICAL,
|
||||
EXPSPACE_OPCODE,
|
||||
EXPSPACE_RAMWRITE,
|
||||
EXPSPACE_REGION
|
||||
};
|
||||
|
||||
|
||||
/* symbol_table is an opaque structure for holding a collection of symbols */
|
||||
typedef struct _symbol_table symbol_table;
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// forward references
|
||||
class symbol_table;
|
||||
|
||||
|
||||
/* symbol_entry describes a symbol in a symbol table */
|
||||
typedef struct _symbol_entry symbol_entry;
|
||||
struct _symbol_entry
|
||||
// ======================> expression_error
|
||||
|
||||
// an expression_error holds an error code and a string offset
|
||||
class expression_error
|
||||
{
|
||||
void * ref; /* internal reference */
|
||||
symbol_table * table; /* pointer back to the owning table */
|
||||
UINT32 type; /* type of symbol */
|
||||
union
|
||||
public:
|
||||
// codes
|
||||
enum error_code
|
||||
{
|
||||
/* register info */
|
||||
struct
|
||||
{
|
||||
symbol_getter_func getter; /* value getter */
|
||||
symbol_setter_func setter; /* value setter */
|
||||
} reg;
|
||||
NONE,
|
||||
NOT_LVAL,
|
||||
NOT_RVAL,
|
||||
SYNTAX,
|
||||
UNKNOWN_SYMBOL,
|
||||
INVALID_NUMBER,
|
||||
INVALID_TOKEN,
|
||||
STACK_OVERFLOW,
|
||||
STACK_UNDERFLOW,
|
||||
UNBALANCED_PARENS,
|
||||
DIVIDE_BY_ZERO,
|
||||
OUT_OF_MEMORY,
|
||||
INVALID_PARAM_COUNT,
|
||||
UNBALANCED_QUOTES,
|
||||
TOO_MANY_STRINGS,
|
||||
INVALID_MEMORY_SIZE,
|
||||
INVALID_MEMORY_SPACE,
|
||||
NO_SUCH_MEMORY_SPACE,
|
||||
INVALID_MEMORY_NAME,
|
||||
MISSING_MEMORY_NAME
|
||||
};
|
||||
|
||||
/* function info */
|
||||
struct
|
||||
{
|
||||
UINT16 minparams; /* minimum expected parameters */
|
||||
UINT16 maxparams; /* maximum expected parameters */
|
||||
function_execute_func execute; /* execute callback */
|
||||
} func;
|
||||
// construction/destruction
|
||||
expression_error(error_code code, int offset = 0)
|
||||
: m_code(code),
|
||||
m_offset(offset) { }
|
||||
|
||||
/* generic info */
|
||||
struct generic_info
|
||||
{
|
||||
void * ptr; /* generic pointer */
|
||||
UINT64 value; /* generic value */
|
||||
} gen;
|
||||
} info;
|
||||
// operators
|
||||
operator error_code() const { return m_code; }
|
||||
|
||||
// getters
|
||||
error_code code() const { return m_code; }
|
||||
int offset() const { return m_offset; }
|
||||
const char *code_string() const;
|
||||
|
||||
private:
|
||||
// internal state
|
||||
error_code m_code;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
|
||||
/* parsed_expression is an opaque structure for holding a pre-parsed expression */
|
||||
typedef struct _parsed_expression parsed_expression;
|
||||
// ======================> symbol_entry
|
||||
|
||||
// symbol_entry describes a symbol in a symbol table
|
||||
class symbol_entry
|
||||
{
|
||||
friend class tagged_list<symbol_entry>;
|
||||
|
||||
protected:
|
||||
// symbol types
|
||||
enum symbol_type
|
||||
{
|
||||
SMT_INTEGER,
|
||||
SMT_FUNCTION
|
||||
};
|
||||
|
||||
// construction/destruction
|
||||
symbol_entry(symbol_table &table, symbol_type type, const char *name, void *ref);
|
||||
virtual ~symbol_entry();
|
||||
|
||||
public:
|
||||
// getters
|
||||
symbol_entry *next() const { return m_next; }
|
||||
const char *name() const { return m_name; }
|
||||
|
||||
// type checking
|
||||
bool is_function() const { return (m_type == SMT_FUNCTION); }
|
||||
|
||||
// symbol access
|
||||
virtual bool is_lval() const = 0;
|
||||
virtual UINT64 value() const = 0;
|
||||
virtual void set_value(UINT64 newvalue) = 0;
|
||||
|
||||
protected:
|
||||
// internal state
|
||||
symbol_entry * m_next; // link to next entry
|
||||
symbol_table & m_table; // pointer back to the owning table
|
||||
symbol_type m_type; // type of symbol
|
||||
astring m_name; // name of the symbol
|
||||
void * m_ref; // internal reference
|
||||
};
|
||||
|
||||
|
||||
// ======================> symbol_table
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
// a symbol_table holds symbols of various types which the expression engine
|
||||
// queries to look up symbols
|
||||
class symbol_table
|
||||
{
|
||||
public:
|
||||
// callback functions for getting/setting a symbol value
|
||||
typedef UINT64 (*getter_func)(symbol_table &table, void *symref);
|
||||
typedef void (*setter_func)(symbol_table &table, void *symref, UINT64 value);
|
||||
|
||||
// callback functions for function execution
|
||||
typedef UINT64 (*execute_func)(symbol_table &table, void *symref, int numparams, const UINT64 *paramlist);
|
||||
|
||||
/* expression evaluation */
|
||||
EXPRERR expression_evaluate(const char *expression, const symbol_table *table, const express_callbacks *callbacks, void *cbparam, UINT64 *result);
|
||||
EXPRERR expression_parse(const char *expression, const symbol_table *table, const express_callbacks *callbacks, void *cbparam, parsed_expression **result);
|
||||
EXPRERR expression_execute(parsed_expression *expr, UINT64 *result);
|
||||
void expression_free(parsed_expression *expr);
|
||||
const char * expression_original_string(parsed_expression *expr);
|
||||
const char * exprerr_to_string(EXPRERR error);
|
||||
// callback functions for memory reads/writes
|
||||
typedef expression_error::error_code (*valid_func)(void *cbparam, const char *name, int space);
|
||||
typedef UINT64 (*read_func)(void *cbparam, const char *name, int space, UINT32 offset, int size);
|
||||
typedef void (*write_func)(void *cbparam, const char *name, int space, UINT32 offset, int size, UINT64 value);
|
||||
|
||||
enum read_write
|
||||
{
|
||||
READ_ONLY = 0,
|
||||
READ_WRITE
|
||||
};
|
||||
|
||||
// construction/destruction
|
||||
symbol_table(void *globalref, symbol_table *parent = NULL);
|
||||
|
||||
// getters
|
||||
symbol_entry *first() const { return m_symlist.first(); }
|
||||
symbol_table *parent() const { return m_parent; }
|
||||
void *globalref() const { return m_globalref; }
|
||||
|
||||
// setters
|
||||
void configure_memory(void *param, valid_func valid, read_func read, write_func write);
|
||||
|
||||
// symbol access
|
||||
void add(const char *name, read_write rw, UINT64 *ptr = NULL);
|
||||
void add(const char *name, UINT64 constvalue);
|
||||
void add(const char *name, void *ref, getter_func getter, setter_func setter = NULL);
|
||||
void add(const char *name, void *ref, int minparams, int maxparams, execute_func execute);
|
||||
symbol_entry *find(const char *name) { return m_symlist.find(name); }
|
||||
|
||||
// value getter/setter
|
||||
UINT64 value(const char *symbol);
|
||||
void set_value(const char *symbol, UINT64 value);
|
||||
|
||||
// memory accessors
|
||||
expression_error::error_code memory_valid(const char *name, int space);
|
||||
UINT64 memory_value(const char *name, int space, UINT32 offset, int size);
|
||||
void set_memory_value(const char *name, int space, UINT32 offset, int size, UINT64 value);
|
||||
|
||||
private:
|
||||
// internal state
|
||||
symbol_table * m_parent; // pointer to the parent symbol table
|
||||
void * m_globalref; // global reference parameter
|
||||
tagged_list<symbol_entry> m_symlist; // list of symbols
|
||||
void * m_memory_param; // callback parameter for memory
|
||||
valid_func m_memory_valid; // validation callback
|
||||
read_func m_memory_read; // read callback
|
||||
write_func m_memory_write; // write callback
|
||||
};
|
||||
|
||||
|
||||
// ======================> parsed_expression
|
||||
|
||||
// a parsed_expression holds a pre-parsed expression that can be
|
||||
// efficiently executed at a later time
|
||||
class parsed_expression
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
parsed_expression(const parsed_expression &src) { copy(src); }
|
||||
parsed_expression(symbol_table *symtable = NULL, const char *expression = NULL, UINT64 *result = NULL);
|
||||
|
||||
// operators
|
||||
parsed_expression &operator=(const parsed_expression &src) { copy(src); return *this; }
|
||||
|
||||
// getters
|
||||
bool is_empty() const { return (m_tokenlist.count() == 0); }
|
||||
const char *original_string() const { return m_original_string; }
|
||||
symbol_table *symbols() const { return m_symtable; }
|
||||
|
||||
// setters
|
||||
void set_symbols(symbol_table *symtable) { m_symtable = symtable; }
|
||||
|
||||
// execution
|
||||
void parse(const char *string);
|
||||
UINT64 execute() { return execute_tokens(); }
|
||||
|
||||
private:
|
||||
// a single token
|
||||
class parse_token
|
||||
{
|
||||
friend class simple_list<parse_token>;
|
||||
|
||||
// operator flags
|
||||
enum
|
||||
{
|
||||
TIN_OPTYPE_SHIFT = 0, // 8 bits (0-7)
|
||||
TIN_OPTYPE_MASK = 0xff << TIN_OPTYPE_SHIFT,
|
||||
TIN_RIGHT_TO_LEFT_SHIFT = 16, // 1 bit (16)
|
||||
TIN_RIGHT_TO_LEFT_MASK = 1 << TIN_RIGHT_TO_LEFT_SHIFT,
|
||||
TIN_FUNCTION_SHIFT = 17, // 1 bit (17)
|
||||
TIN_FUNCTION_MASK = 1 << TIN_FUNCTION_SHIFT,
|
||||
TIN_MEMORY_SIZE_SHIFT = 18, // 2 bits (18-19)
|
||||
TIN_MEMORY_SIZE_MASK = 3 << TIN_MEMORY_SIZE_SHIFT,
|
||||
TIN_MEMORY_SPACE_SHIFT = 20, // 4 bits (20-23)
|
||||
TIN_MEMORY_SPACE_MASK = 0xf << TIN_MEMORY_SPACE_SHIFT,
|
||||
TIN_PRECEDENCE_SHIFT = 24, // 8 bits (24-31)
|
||||
TIN_PRECEDENCE_MASK = 0xff << TIN_PRECEDENCE_SHIFT
|
||||
};
|
||||
|
||||
// types of tokens
|
||||
enum token_type
|
||||
{
|
||||
INVALID = 0,
|
||||
NUMBER,
|
||||
STRING,
|
||||
MEMORY,
|
||||
SYMBOL,
|
||||
OPERATOR
|
||||
};
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
parse_token(int offset = 0);
|
||||
|
||||
// getters
|
||||
parse_token *next() const { return m_next; }
|
||||
int offset() const { return m_offset; }
|
||||
bool is_number() const { return (m_type == NUMBER); }
|
||||
bool is_string() const { return (m_type == STRING); }
|
||||
bool is_memory() const { return (m_type == MEMORY); }
|
||||
bool is_symbol() const { return (m_type == SYMBOL); }
|
||||
bool is_operator() const { return (m_type == OPERATOR); }
|
||||
bool is_operator(UINT8 type) const { return (m_type == OPERATOR && optype() == type); }
|
||||
bool is_lval() const { return ((m_type == SYMBOL && m_symbol->is_lval()) || m_type == MEMORY); }
|
||||
|
||||
UINT64 value() const { assert(m_type == NUMBER); return m_value; }
|
||||
UINT32 address() const { assert(m_type == MEMORY); return m_value; }
|
||||
symbol_entry *symbol() const { assert(m_type == SYMBOL); return m_symbol; }
|
||||
|
||||
UINT8 optype() const { assert(m_type == OPERATOR); return (m_flags & TIN_OPTYPE_MASK) >> TIN_OPTYPE_SHIFT; }
|
||||
UINT8 precedence() const { assert(m_type == OPERATOR); return (m_flags & TIN_PRECEDENCE_MASK) >> TIN_PRECEDENCE_SHIFT; }
|
||||
bool is_function_separator() const { assert(m_type == OPERATOR); return ((m_flags & TIN_FUNCTION_MASK) != 0); }
|
||||
bool right_to_left() const { assert(m_type == OPERATOR); return ((m_flags & TIN_RIGHT_TO_LEFT_MASK) != 0); }
|
||||
expression_space memory_space() const { assert(m_type == OPERATOR || m_type == MEMORY); return expression_space((m_flags & TIN_MEMORY_SPACE_MASK) >> TIN_MEMORY_SPACE_SHIFT); }
|
||||
int memory_size() const { assert(m_type == OPERATOR || m_type == MEMORY); return (m_flags & TIN_MEMORY_SIZE_MASK) >> TIN_MEMORY_SIZE_SHIFT; }
|
||||
|
||||
// setters
|
||||
parse_token &set_offset(int offset) { m_offset = offset; return *this; }
|
||||
parse_token &set_offset(const parse_token &src) { m_offset = src.m_offset; return *this; }
|
||||
parse_token &set_offset(const parse_token &src1, const parse_token &src2) { m_offset = MIN(src1.m_offset, src2.m_offset); return *this; }
|
||||
parse_token &configure_number(UINT64 value) { m_type = NUMBER; m_value = value; return *this; }
|
||||
parse_token &configure_string(const char *string) { m_type = STRING; m_string = string; return *this; }
|
||||
parse_token &configure_memory(UINT32 address, parse_token &memoryat) { m_type = MEMORY; m_value = address; m_flags = memoryat.m_flags; m_string = memoryat.m_string; return *this; }
|
||||
parse_token &configure_symbol(symbol_entry &symbol) { m_type = SYMBOL; m_symbol = &symbol; return *this; }
|
||||
parse_token &configure_operator(UINT8 optype, UINT8 precedence)
|
||||
{ m_type = OPERATOR; m_flags = ((optype << TIN_OPTYPE_SHIFT) & TIN_OPTYPE_MASK) | ((precedence << TIN_PRECEDENCE_SHIFT) & TIN_PRECEDENCE_MASK); return *this; }
|
||||
|
||||
parse_token &set_function_separator() { assert(m_type == OPERATOR); m_flags |= TIN_FUNCTION_MASK; return *this; }
|
||||
parse_token &set_right_to_left() { assert(m_type == OPERATOR); m_flags |= TIN_RIGHT_TO_LEFT_MASK; return *this; }
|
||||
parse_token &set_memory_space(expression_space space) { assert(m_type == OPERATOR || m_type == MEMORY); m_flags = (m_flags & ~TIN_MEMORY_SPACE_MASK) | ((space << TIN_MEMORY_SPACE_SHIFT) & TIN_MEMORY_SPACE_MASK); return *this; }
|
||||
parse_token &set_memory_size(int log2ofbits) { assert(m_type == OPERATOR || m_type == MEMORY); m_flags = (m_flags & ~TIN_MEMORY_SIZE_MASK) | ((log2ofbits << TIN_MEMORY_SIZE_SHIFT) & TIN_MEMORY_SIZE_MASK); return *this; }
|
||||
parse_token &set_memory_source(const char *string) { assert(m_type == OPERATOR || m_type == MEMORY); m_string = string; return *this; }
|
||||
|
||||
// access
|
||||
UINT64 get_lval_value(symbol_table *symtable);
|
||||
void set_lval_value(symbol_table *symtable, UINT64 value);
|
||||
|
||||
private:
|
||||
// internal state
|
||||
parse_token * m_next; // next token in list
|
||||
token_type m_type; // type of token
|
||||
int m_offset; // offset within the string
|
||||
UINT64 m_value; // integral value
|
||||
UINT32 m_flags; // additional flags/info
|
||||
const char * m_string; // associated string
|
||||
symbol_entry * m_symbol; // symbol pointer
|
||||
};
|
||||
|
||||
// an expression_string holds an indexed string parsed from the expression
|
||||
class expression_string
|
||||
{
|
||||
friend class simple_list<expression_string>;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
expression_string(const char *string, int length = 0)
|
||||
: m_next(NULL),
|
||||
m_string(string, (length == 0) ? strlen(string) : length) { }
|
||||
|
||||
// operators
|
||||
operator const char *() { return m_string; }
|
||||
operator const char *() const { return m_string; }
|
||||
|
||||
private:
|
||||
// internal state
|
||||
expression_string * m_next; // next string in list
|
||||
astring m_string; // copy of the string
|
||||
};
|
||||
|
||||
// internal helpers
|
||||
void copy(const parsed_expression &src);
|
||||
void print_tokens(FILE *out);
|
||||
|
||||
// parsing helpers
|
||||
void parse_string_into_tokens();
|
||||
void parse_symbol_or_number(parse_token &token, const char *&string);
|
||||
void parse_number(parse_token &token, const char *string, int base, expression_error::error_code errcode);
|
||||
void parse_quoted_char(parse_token &token, const char *&string);
|
||||
void parse_quoted_string(parse_token &token, const char *&string);
|
||||
void parse_memory_operator(parse_token &token, const char *string);
|
||||
void normalize_operator(parse_token *prevtoken, parse_token &thistoken);
|
||||
void infix_to_postfix();
|
||||
|
||||
// execution helpers
|
||||
void push_token(parse_token &token);
|
||||
void pop_token(parse_token &token);
|
||||
parse_token *peek_token(int count);
|
||||
void pop_token_lval(parse_token &token);
|
||||
void pop_token_rval(parse_token &token);
|
||||
UINT64 execute_tokens();
|
||||
void execute_function(parse_token &token);
|
||||
|
||||
// constants
|
||||
static const int MAX_FUNCTION_PARAMS = 16;
|
||||
static const int MAX_STACK_DEPTH = 16;
|
||||
|
||||
// internal state
|
||||
symbol_table * m_symtable; // symbol table
|
||||
astring m_original_string; // original string (prior to parsing)
|
||||
simple_list<parse_token> m_tokenlist; // token list
|
||||
simple_list<expression_string> m_stringlist; // string list
|
||||
int m_token_stack_ptr; // stack pointer (used during execution)
|
||||
parse_token m_token_stack[MAX_STACK_DEPTH]; // token stack (used during execution)
|
||||
};
|
||||
|
||||
/* symbol table manipulation */
|
||||
symbol_table * symtable_alloc(symbol_table *parent, void *globalref);
|
||||
void * symtable_get_globalref(symbol_table *table);
|
||||
int symtable_add(symbol_table *table, const char *name, const symbol_entry *entry);
|
||||
int symtable_add_register(symbol_table *table, const char *name, void *symref, symbol_getter_func getter, symbol_setter_func setter);
|
||||
int symtable_add_function(symbol_table *table, const char *name, void *symref, UINT16 minparams, UINT16 maxparams, function_execute_func execute);
|
||||
int symtable_add_value(symbol_table *table, const char *name, UINT64 value);
|
||||
const symbol_entry * symtable_find(const symbol_table *table, const char *name);
|
||||
const char * symtable_find_indexed(const symbol_table *table, int index, const symbol_entry **entry);
|
||||
void symtable_free(symbol_table *table);
|
||||
|
||||
#endif
|
||||
|
@ -308,6 +308,7 @@ public:
|
||||
~astring();
|
||||
|
||||
astring(const char *string) { init().cpy(string); }
|
||||
astring(const char *string, int length) { init().cpy(string, length); }
|
||||
astring(const char *str1, const char *str2) { init().cpy(str1).cat(str2); }
|
||||
astring(const char *str1, const char *str2, const char *str3) { init().cpy(str1).cat(str2).cat(str3); }
|
||||
astring(const char *str1, const char *str2, const char *str3, const char *str4) { init().cpy(str1).cat(str2).cat(str3).cat(str4); }
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "dview.h"
|
||||
#include "osdsdl.h"
|
||||
#include "debugger.h"
|
||||
#include "debug/dvdisasm.h"
|
||||
#include "debug/dvmemory.h"
|
||||
#include "debug/dvstate.h"
|
||||
|
@ -51,6 +51,7 @@
|
||||
// MAME headers
|
||||
#include "emu.h"
|
||||
#include "uiinput.h"
|
||||
#include "debugger.h"
|
||||
#include "debug/debugvw.h"
|
||||
#include "debug/dvdisasm.h"
|
||||
#include "debug/dvmemory.h"
|
||||
@ -58,7 +59,6 @@
|
||||
#include "debug/debugvw.h"
|
||||
#include "debug/debugcon.h"
|
||||
#include "debug/debugcpu.h"
|
||||
#include "debugger.h"
|
||||
|
||||
// MAMEOS headers
|
||||
#include "debugwin.h"
|
||||
|
Loading…
Reference in New Issue
Block a user