Converted the expression engine to C++, did the usual cleanup.

This commit is contained in:
Aaron Giles 2010-11-01 07:48:02 +00:00
parent c956d18f78
commit a2ce61ac6c
16 changed files with 2053 additions and 2361 deletions

View File

@ -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;

View File

@ -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__ */

View File

@ -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);
}
/*************************************************************************/

View File

@ -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");
}

View File

@ -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
{

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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
};

View File

@ -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());
}

View File

@ -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

View File

@ -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

View File

@ -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); }

View File

@ -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"

View File

@ -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"