summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/express.c
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
commit7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch)
treef310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/emu/debug/express.c
parenta57b46ae933badd7441ce1644711dbb851e2b504 (diff)
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/emu/debug/express.c')
-rw-r--r--src/emu/debug/express.c1753
1 files changed, 0 insertions, 1753 deletions
diff --git a/src/emu/debug/express.c b/src/emu/debug/express.c
deleted file mode 100644
index a37a7796f5f..00000000000
--- a/src/emu/debug/express.c
+++ /dev/null
@@ -1,1753 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- express.c
-
- Generic expressions engine.
-
-****************************************************************************
-
- Operator precedence
- ===================
- 0x0000 ( )
- 0x0001 ++ (postfix), -- (postfix)
- 0x0002 ++ (prefix), -- (prefix), ~, !, - (unary), + (unary), b@, w@, d@, q@
- 0x0003 *, /, %
- 0x0004 + -
- 0x0005 << >>
- 0x0006 < <= > >=
- 0x0007 == !=
- 0x0008 &
- 0x0009 ^
- 0x000a |
- 0x000b &&
- 0x000c ||
- 0x000d = *= /= %= += -= <<= >>= &= |= ^=
- 0x000e ,
- 0x000f func()
-
-***************************************************************************/
-
-#include "emu.h"
-#include "express.h"
-#include <ctype.h>
-
-
-
-/***************************************************************************
- DEBUGGING
-***************************************************************************/
-
-#define DEBUG_TOKENS 0
-
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#ifndef DEFAULT_BASE
-#define DEFAULT_BASE 16 // hex unless otherwise specified
-#endif
-
-
-// token.value values if token.is_operator()
-enum
-{
- TVL_LPAREN,
- TVL_RPAREN,
- TVL_PLUSPLUS,
- TVL_MINUSMINUS,
- TVL_PREINCREMENT,
- TVL_PREDECREMENT,
- TVL_POSTINCREMENT,
- TVL_POSTDECREMENT,
- TVL_COMPLEMENT,
- TVL_NOT,
- TVL_UPLUS,
- TVL_UMINUS,
- TVL_MULTIPLY,
- TVL_DIVIDE,
- TVL_MODULO,
- TVL_ADD,
- TVL_SUBTRACT,
- TVL_LSHIFT,
- TVL_RSHIFT,
- TVL_LESS,
- TVL_LESSOREQUAL,
- TVL_GREATER,
- TVL_GREATEROREQUAL,
- TVL_EQUAL,
- TVL_NOTEQUAL,
- TVL_BAND,
- TVL_BXOR,
- TVL_BOR,
- TVL_LAND,
- TVL_LOR,
- TVL_ASSIGN,
- TVL_ASSIGNMULTIPLY,
- TVL_ASSIGNDIVIDE,
- TVL_ASSIGNMODULO,
- TVL_ASSIGNADD,
- TVL_ASSIGNSUBTRACT,
- TVL_ASSIGNLSHIFT,
- TVL_ASSIGNRSHIFT,
- TVL_ASSIGNBAND,
- TVL_ASSIGNBXOR,
- TVL_ASSIGNBOR,
- TVL_COMMA,
- TVL_MEMORYAT,
- TVL_EXECUTEFUNC
-};
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// a symbol entry representing a register, with read/write callbacks
-class integer_symbol_entry : public symbol_entry
-{
-public:
- // construction/destruction
- integer_symbol_entry(symbol_table &table, const char *name, symbol_table::read_write rw, UINT64 *ptr = NULL);
- integer_symbol_entry(symbol_table &table, const char *name, UINT64 constval);
- integer_symbol_entry(symbol_table &table, const char *name, void *ref, symbol_table::getter_func getter, symbol_table::setter_func setter);
-
- // symbol access
- virtual bool is_lval() const;
- virtual UINT64 value() const;
- virtual void set_value(UINT64 newvalue);
-
-private:
- // internal helpers
- static UINT64 internal_getter(symbol_table &table, void *symref);
- static void internal_setter(symbol_table &table, void *symref, UINT64 value);
-
- // internal state
- symbol_table::getter_func m_getter;
- symbol_table::setter_func m_setter;
- UINT64 m_value;
-};
-
-
-// a symbol entry representing a function
-class function_symbol_entry : public symbol_entry
-{
-public:
- // construction/destruction
- function_symbol_entry(symbol_table &table, const char *name, void *ref, int minparams, int maxparams, symbol_table::execute_func execute);
-
- // symbol access
- virtual bool is_lval() const;
- virtual UINT64 value() const;
- virtual void set_value(UINT64 newvalue);
-
- // execution helper
- virtual UINT64 execute(int numparams, const UINT64 *paramlist);
-
-private:
- // internal state
- UINT16 m_minparams;
- UINT16 m_maxparams;
- symbol_table::execute_func m_execute;
-};
-
-
-
-//**************************************************************************
-// EXPRESSION ERROR
-//**************************************************************************
-
-//-------------------------------------------------
-// code_string - return a friendly string for a
-// given expression error
-//-------------------------------------------------
-
-const char *expression_error::code_string() const
-{
- switch (m_code)
- {
- case NOT_LVAL: return "not an lvalue";
- case NOT_RVAL: return "not an rvalue";
- case SYNTAX: return "syntax error";
- case UNKNOWN_SYMBOL: return "unknown symbol";
- case INVALID_NUMBER: return "invalid number";
- case INVALID_TOKEN: return "invalid token";
- case STACK_OVERFLOW: return "stack overflow";
- case STACK_UNDERFLOW: return "stack underflow";
- case UNBALANCED_PARENS: return "unbalanced parentheses";
- case DIVIDE_BY_ZERO: return "divide by zero";
- case OUT_OF_MEMORY: return "out of memory";
- case INVALID_PARAM_COUNT: return "invalid number of parameters";
- case UNBALANCED_QUOTES: return "unbalanced quotes";
- case TOO_MANY_STRINGS: return "too many strings";
- case INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)";
- case NO_SUCH_MEMORY_SPACE: return "non-existent memory space";
- case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)";
- case INVALID_MEMORY_NAME: return "invalid memory name";
- case MISSING_MEMORY_NAME: return "missing memory name";
- default: return "unknown error";
- }
-}
-
-
-
-//**************************************************************************
-// SYMBOL ENTRY
-//**************************************************************************
-
-//-------------------------------------------------
-// symbol_entry - constructor
-//-------------------------------------------------
-
-symbol_entry::symbol_entry(symbol_table &table, symbol_type type, const char *name, void *ref)
- : m_next(NULL),
- m_table(table),
- m_type(type),
- m_name(name),
- m_ref(ref)
-{
-}
-
-
-//-------------------------------------------------
-// ~symbol_entry - destructor
-//-------------------------------------------------
-
-symbol_entry::~symbol_entry()
-{
-}
-
-
-
-//**************************************************************************
-// REGISTER SYMBOL ENTRY
-//**************************************************************************
-
-//-------------------------------------------------
-// integer_symbol_entry - constructor
-//-------------------------------------------------
-
-integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, symbol_table::read_write rw, UINT64 *ptr)
- : symbol_entry(table, SMT_INTEGER, name, (ptr == NULL) ? &m_value : ptr),
- m_getter(internal_getter),
- m_setter((rw == symbol_table::READ_ONLY) ? NULL : internal_setter),
- m_value(0)
-{
-}
-
-
-integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, UINT64 constval)
- : symbol_entry(table, SMT_INTEGER, name, &m_value),
- m_getter(internal_getter),
- m_setter(NULL),
- m_value(constval)
-{
-}
-
-
-integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, void *ref, symbol_table::getter_func getter, symbol_table::setter_func setter)
- : symbol_entry(table, SMT_INTEGER, name, ref),
- m_getter(getter),
- m_setter(setter),
- m_value(0)
-{
-}
-
-
-//-------------------------------------------------
-// is_lval - is this symbol allowable as an lval?
-//-------------------------------------------------
-
-bool integer_symbol_entry::is_lval() const
-{
- return (m_setter != NULL);
-}
-
-
-//-------------------------------------------------
-// value - return the value of this symbol
-//-------------------------------------------------
-
-UINT64 integer_symbol_entry::value() const
-{
- return (*m_getter)(m_table, m_ref);
-}
-
-
-//-------------------------------------------------
-// set_value - set the value of this symbol
-//-------------------------------------------------
-
-void integer_symbol_entry::set_value(UINT64 newvalue)
-{
- if (m_setter != NULL)
- (*m_setter)(m_table, m_ref, newvalue);
- else
- throw emu_fatalerror("Symbol '%s' is read-only", m_name.c_str());
-}
-
-
-//-------------------------------------------------
-// internal_getter - internal helper for
-// returning the value of a variable
-//-------------------------------------------------
-
-UINT64 integer_symbol_entry::internal_getter(symbol_table &table, void *symref)
-{
- return *(UINT64 *)symref;
-}
-
-
-//-------------------------------------------------
-// internal_setter - internal helper for setting
-// the value of a variable
-//-------------------------------------------------
-
-void integer_symbol_entry::internal_setter(symbol_table &table, void *symref, UINT64 value)
-{
- *(UINT64 *)symref = value;
-}
-
-
-
-//**************************************************************************
-// FUNCTION SYMBOL ENTRY
-//**************************************************************************
-
-//-------------------------------------------------
-// function_symbol_entry - constructor
-//-------------------------------------------------
-
-function_symbol_entry::function_symbol_entry(symbol_table &table, const char *name, void *ref, int minparams, int maxparams, symbol_table::execute_func execute)
- : symbol_entry(table, SMT_FUNCTION, name, ref),
- m_minparams(minparams),
- m_maxparams(maxparams),
- m_execute(execute)
-{
-}
-
-
-//-------------------------------------------------
-// is_lval - is this symbol allowable as an lval?
-//-------------------------------------------------
-
-bool function_symbol_entry::is_lval() const
-{
- return false;
-}
-
-
-//-------------------------------------------------
-// value - return the value of this symbol
-//-------------------------------------------------
-
-UINT64 function_symbol_entry::value() const
-{
- throw emu_fatalerror("Symbol '%s' is a function and cannot be used in this context", m_name.c_str());
-}
-
-
-//-------------------------------------------------
-// set_value - set the value of this symbol
-//-------------------------------------------------
-
-void function_symbol_entry::set_value(UINT64 newvalue)
-{
- throw emu_fatalerror("Symbol '%s' is a function and cannot be written", m_name.c_str());
-}
-
-
-//-------------------------------------------------
-// execute - execute the function
-//-------------------------------------------------
-
-UINT64 function_symbol_entry::execute(int numparams, const UINT64 *paramlist)
-{
- if (numparams < m_minparams)
- throw emu_fatalerror("Function '%s' requires at least %d parameters", m_name.c_str(), m_minparams);
- if (numparams > m_maxparams)
- throw emu_fatalerror("Function '%s' accepts no more than %d parameters", m_name.c_str(), m_maxparams);
- return (*m_execute)(m_table, m_ref, numparams, paramlist);
-}
-
-
-
-//**************************************************************************
-// SYMBOL TABLE
-//**************************************************************************
-
-//-------------------------------------------------
-// symbol_table - constructor
-//-------------------------------------------------
-
-symbol_table::symbol_table(void *globalref, symbol_table *parent)
- : m_parent(parent),
- m_globalref(globalref),
- m_memory_param(NULL),
- m_memory_valid(NULL),
- m_memory_read(NULL),
- m_memory_write(NULL)
-{
-}
-
-
-//-------------------------------------------------
-// add - add a new UINT64 pointer symbol
-//-------------------------------------------------
-
-void symbol_table::configure_memory(void *param, valid_func valid, read_func read, write_func write)
-{
- m_memory_param = param;
- m_memory_valid = valid;
- m_memory_read = read;
- m_memory_write = write;
-}
-
-
-//-------------------------------------------------
-// add - add a new UINT64 pointer symbol
-//-------------------------------------------------
-
-void symbol_table::add(const char *name, read_write rw, UINT64 *ptr)
-{
- m_symlist.remove(name);
- m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, rw, ptr)));
-}
-
-
-//-------------------------------------------------
-// add - add a new value symbol
-//-------------------------------------------------
-
-void symbol_table::add(const char *name, UINT64 value)
-{
- m_symlist.remove(name);
- m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, value)));
-}
-
-
-//-------------------------------------------------
-// add - add a new register symbol
-//-------------------------------------------------
-
-void symbol_table::add(const char *name, void *ref, getter_func getter, setter_func setter)
-{
- m_symlist.remove(name);
- m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, ref, getter, setter)));
-}
-
-
-//-------------------------------------------------
-// add - add a new function symbol
-//-------------------------------------------------
-
-void symbol_table::add(const char *name, void *ref, int minparams, int maxparams, execute_func execute)
-{
- m_symlist.remove(name);
- m_symlist.append(name, *global_alloc(function_symbol_entry(*this, name, ref, minparams, maxparams, execute)));
-}
-
-
-//-------------------------------------------------
-// find_deep - do a deep search for a symbol,
-// looking in the parent if needed
-//-------------------------------------------------
-
-symbol_entry *symbol_table::find_deep(const char *symbol)
-{
- // walk up the table hierarchy to find the owner
- for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
- {
- symbol_entry *entry = symtable->find(symbol);
- if (entry != NULL)
- return entry;
- }
- return NULL;
-}
-
-
-//-------------------------------------------------
-// value - return the value of a symbol
-//-------------------------------------------------
-
-UINT64 symbol_table::value(const char *symbol)
-{
- symbol_entry *entry = find_deep(symbol);
- return (entry != NULL) ? entry->value() : 0;
-}
-
-
-//-------------------------------------------------
-// set_value - set the value of a symbol
-//-------------------------------------------------
-
-void symbol_table::set_value(const char *symbol, UINT64 value)
-{
- symbol_entry *entry = find_deep(symbol);
- if (entry != NULL)
- entry->set_value(value);
-}
-
-
-//-------------------------------------------------
-// memory_valid - return true if the given
-// memory name/space/offset combination is valid
-//-------------------------------------------------
-
-expression_error::error_code symbol_table::memory_valid(const char *name, expression_space space)
-{
- // walk up the table hierarchy to find the owner
- for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
- if (symtable->m_memory_valid != NULL)
- {
- expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
- if (err != expression_error::NO_SUCH_MEMORY_SPACE)
- return err;
- }
- return expression_error::NO_SUCH_MEMORY_SPACE;
-}
-
-
-//-------------------------------------------------
-// memory_value - return a value read from memory
-//-------------------------------------------------
-
-UINT64 symbol_table::memory_value(const char *name, expression_space space, UINT32 offset, int size)
-{
- // walk up the table hierarchy to find the owner
- for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
- if (symtable->m_memory_valid != NULL)
- {
- expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
- if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_read != NULL)
- return (*symtable->m_memory_read)(symtable->m_memory_param, name, space, offset, size);
- return 0;
- }
- return 0;
-}
-
-
-//-------------------------------------------------
-// set_memory_value - write a value to memory
-//-------------------------------------------------
-
-void symbol_table::set_memory_value(const char *name, expression_space space, UINT32 offset, int size, UINT64 value)
-{
- // walk up the table hierarchy to find the owner
- for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
- if (symtable->m_memory_valid != NULL)
- {
- expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
- if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_write != NULL)
- (*symtable->m_memory_write)(symtable->m_memory_param, name, space, offset, size, value);
- return;
- }
-}
-
-
-
-//**************************************************************************
-// PARSED EXPRESSION
-//**************************************************************************
-
-//-------------------------------------------------
-// parsed_expression - constructor
-//-------------------------------------------------
-
-parsed_expression::parsed_expression(symbol_table *symtable, const char *expression, UINT64 *result)
- : m_symtable(symtable),
- m_token_stack_ptr(0)
-{
- // if we got an expression parse it
- if (expression != NULL)
- parse(expression);
-
- // if we get a result pointer, execute it
- if (result != NULL)
- *result = execute();
-}
-
-
-//-------------------------------------------------
-// parse - parse an expression into tokens
-//-------------------------------------------------
-
-void parsed_expression::parse(const char *expression)
-{
- // copy the string and reset our parsing state
- m_original_string.assign(expression);
- m_tokenlist.reset();
- m_stringlist.reset();
-
- // first parse the tokens into the token array in order
- parse_string_into_tokens();
-
- // convert the infix order to postfix order
- infix_to_postfix();
-}
-
-
-//-------------------------------------------------
-// copy - copy an expression from another source
-//-------------------------------------------------
-
-void parsed_expression::copy(const parsed_expression &src)
-{
- m_symtable = src.m_symtable;
- m_original_string.assign(src.m_original_string);
- if (!m_original_string.empty())
- parse_string_into_tokens();
-}
-
-
-//-------------------------------------------------
-// print_tokens - debugging took to print a
-// human readable token representation
-//-------------------------------------------------
-
-void parsed_expression::print_tokens(FILE *out)
-{
-#if DEBUG_TOKENS
- osd_printf_debug("----\n");
- for (parse_token *token = m_tokens.first(); token != NULL; token = token->next())
- {
- switch (token->type)
- {
- default:
- case parse_token::INVALID:
- fprintf(out, "INVALID\n");
- break;
-
- case parse_token::END:
- fprintf(out, "END\n");
- break;
-
- case parse_token::NUMBER:
- fprintf(out, "NUMBER: %08X%08X\n", (UINT32)(token->value.i >> 32), (UINT32)token->value.i);
- break;
-
- case parse_token::STRING:
- fprintf(out, "STRING: ""%s""\n", token->string);
- break;
-
- case parse_token::SYMBOL:
- fprintf(out, "SYMBOL: %08X%08X\n", (UINT32)(token->value.i >> 32), (UINT32)token->value.i);
- break;
-
- case parse_token::OPERATOR:
- switch (token->value.i)
- {
- case TVL_LPAREN: fprintf(out, "(\n"); break;
- case TVL_RPAREN: fprintf(out, ")\n"); break;
- case TVL_PLUSPLUS: fprintf(out, "++ (unspecified)\n"); break;
- case TVL_MINUSMINUS: fprintf(out, "-- (unspecified)\n"); break;
- case TVL_PREINCREMENT: fprintf(out, "++ (prefix)\n"); break;
- case TVL_PREDECREMENT: fprintf(out, "-- (prefix)\n"); break;
- case TVL_POSTINCREMENT: fprintf(out, "++ (postfix)\n"); break;
- case TVL_POSTDECREMENT: fprintf(out, "-- (postfix)\n"); break;
- case TVL_COMPLEMENT: fprintf(out, "!\n"); break;
- case TVL_NOT: fprintf(out, "~\n"); break;
- case TVL_UPLUS: fprintf(out, "+ (unary)\n"); break;
- case TVL_UMINUS: fprintf(out, "- (unary)\n"); break;
- case TVL_MULTIPLY: fprintf(out, "*\n"); break;
- case TVL_DIVIDE: fprintf(out, "/\n"); break;
- case TVL_MODULO: fprintf(out, "%%\n"); break;
- case TVL_ADD: fprintf(out, "+\n"); break;
- case TVL_SUBTRACT: fprintf(out, "-\n"); break;
- case TVL_LSHIFT: fprintf(out, "<<\n"); break;
- case TVL_RSHIFT: fprintf(out, ">>\n"); break;
- case TVL_LESS: fprintf(out, "<\n"); break;
- case TVL_LESSOREQUAL: fprintf(out, "<=\n"); break;
- case TVL_GREATER: fprintf(out, ">\n"); break;
- case TVL_GREATEROREQUAL:fprintf(out, ">=\n"); break;
- case TVL_EQUAL: fprintf(out, "==\n"); break;
- case TVL_NOTEQUAL: fprintf(out, "!=\n"); break;
- case TVL_BAND: fprintf(out, "&\n"); break;
- case TVL_BXOR: fprintf(out, "^\n"); break;
- case TVL_BOR: fprintf(out, "|\n"); break;
- case TVL_LAND: fprintf(out, "&&\n"); break;
- case TVL_LOR: fprintf(out, "||\n"); break;
- case TVL_ASSIGN: fprintf(out, "=\n"); break;
- case TVL_ASSIGNMULTIPLY:fprintf(out, "*=\n"); break;
- case TVL_ASSIGNDIVIDE: fprintf(out, "/=\n"); break;
- case TVL_ASSIGNMODULO: fprintf(out, "%%=\n"); break;
- case TVL_ASSIGNADD: fprintf(out, "+=\n"); break;
- case TVL_ASSIGNSUBTRACT:fprintf(out, "-=\n"); break;
- case TVL_ASSIGNLSHIFT: fprintf(out, "<<=\n"); break;
- case TVL_ASSIGNRSHIFT: fprintf(out, ">>=\n"); break;
- case TVL_ASSIGNBAND: fprintf(out, "&=\n"); break;
- case TVL_ASSIGNBXOR: fprintf(out, "^=\n"); break;
- case TVL_ASSIGNBOR: fprintf(out, "|=\n"); break;
- case TVL_COMMA: fprintf(out, ",\n"); break;
- case TVL_MEMORYAT: fprintf(out, "mem@\n"); break;
- case TVL_EXECUTEFUNC: fprintf(out, "execute\n"); break;
- default: fprintf(out, "INVALID OPERATOR\n"); break;
- }
- break;
- }
- }
- osd_printf_debug("----\n");
-#endif
-}
-
-
-//-------------------------------------------------
-// parse_string_into_tokens - take an expression
-// string and break it into a sequence of tokens
-//-------------------------------------------------
-
-void parsed_expression::parse_string_into_tokens()
-{
- // loop until done
- const char *stringstart = m_original_string.c_str();
- const char *string = stringstart;
- while (string[0] != 0)
- {
- // ignore any whitespace
- while (string[0] != 0 && isspace((UINT8)string[0]))
- string++;
- if (string[0] == 0)
- break;
-
- // initialize the current token object
- parse_token &token = m_tokenlist.append(*global_alloc(parse_token(string - stringstart)));
-
- // switch off the first character
- switch (tolower((UINT8)string[0]))
- {
- case '(':
- string += 1, token.configure_operator(TVL_LPAREN, 0);
- break;
-
- case ')':
- string += 1, token.configure_operator(TVL_RPAREN, 0);
- break;
-
- case '~':
- string += 1, token.configure_operator(TVL_NOT, 2);
- break;
-
- case ',':
- string += 1, token.configure_operator(TVL_COMMA, 14);
- break;
-
- case '+':
- if (string[1] == '+')
- string += 2, token.configure_operator(TVL_PLUSPLUS, 1);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNADD, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_ADD, 4);
- break;
-
- case '-':
- if (string[1] == '-')
- string += 2, token.configure_operator(TVL_MINUSMINUS, 1);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNSUBTRACT, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_SUBTRACT, 4);
- break;
-
- case '*':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNMULTIPLY, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_MULTIPLY, 3);
- break;
-
- case '/':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNDIVIDE, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_DIVIDE, 3);
- break;
-
- case '%':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNMODULO, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_MODULO, 3);
- break;
-
- case '<':
- if (string[1] == '<' && string[2] == '=')
- string += 3, token.configure_operator(TVL_ASSIGNLSHIFT, 13).set_right_to_left();
- else if (string[1] == '<')
- string += 2, token.configure_operator(TVL_LSHIFT, 5);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_LESSOREQUAL, 6);
- else
- string += 1, token.configure_operator(TVL_LESS, 6);
- break;
-
- case '>':
- if (string[1] == '>' && string[2] == '=')
- string += 3, token.configure_operator(TVL_ASSIGNRSHIFT, 13).set_right_to_left();
- else if (string[1] == '>')
- string += 2, token.configure_operator(TVL_RSHIFT, 5);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_GREATEROREQUAL, 6);
- else
- string += 1, token.configure_operator(TVL_GREATER, 6);
- break;
-
- case '=':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_EQUAL, 7);
- else
- string += 1, token.configure_operator(TVL_ASSIGN, 13).set_right_to_left();
- break;
-
- case '!':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_NOTEQUAL, 7);
- else
- string += 2, token.configure_operator(TVL_COMPLEMENT, 2);
- break;
-
- case '&':
- if (string[1] == '&')
- string += 2, token.configure_operator(TVL_LAND, 11);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNBAND, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_BAND, 8);
- break;
-
- case '|':
- if (string[1] == '|')
- string += 2, token.configure_operator(TVL_LOR, 12);
- else if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNBOR, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_BOR, 10);
- break;
-
- case '^':
- if (string[1] == '=')
- string += 2, token.configure_operator(TVL_ASSIGNBXOR, 13).set_right_to_left();
- else
- string += 1, token.configure_operator(TVL_BXOR, 9);
- break;
-
- case '"':
- parse_quoted_string(token, string);
- break;
-
- case '\'':
- parse_quoted_char(token, string);
- break;
-
- default:
- parse_symbol_or_number(token, string);
- break;
- }
- }
-}
-
-
-//-------------------------------------------------
-// parse_symbol_or_number - parse a substring
-// into either a symbol or a number or an
-// expanded operator
-//-------------------------------------------------
-
-void parsed_expression::parse_symbol_or_number(parse_token &token, const char *&string)
-{
- // accumulate a lower-case version of the symbol
- const char *stringstart = string;
- std::string buffer;
- while (1)
- {
- static const char valid[] = "abcdefghijklmnopqrstuvwxyz0123456789_$#.:";
- char val = tolower((UINT8)string[0]);
- if (val == 0 || strchr(valid, val) == NULL)
- break;
- buffer.append(&val, 1);
- string++;
- }
-
- // check for memory @ operators
- if (string[0] == '@')
- {
- string += 1;
- return parse_memory_operator(token, buffer.c_str());
- }
-
- // empty string is automatically invalid
- if (buffer.empty())
- throw expression_error(expression_error::INVALID_TOKEN, token.offset());
-
- // check for wordy variants on standard operators
- if (buffer.compare("bnot")==0)
- { token.configure_operator(TVL_NOT, 2); return; }
- if (buffer.compare("plus") == 0)
- { token.configure_operator(TVL_ADD, 4); return; }
- if (buffer.compare("minus") == 0)
- { token.configure_operator(TVL_SUBTRACT, 4); return; }
- if (buffer.compare("times") == 0 || buffer.compare("mul") == 0)
- { token.configure_operator(TVL_MULTIPLY, 3); return; }
- if (buffer.compare("div") == 0)
- { token.configure_operator(TVL_DIVIDE, 3); return; }
- if (buffer.compare("mod") == 0)
- { token.configure_operator(TVL_MODULO, 3); return; }
- if (buffer.compare("lt") == 0)
- { token.configure_operator(TVL_LESS, 6); return; }
- if (buffer.compare("le") == 0)
- { token.configure_operator(TVL_LESSOREQUAL, 6); return; }
- if (buffer.compare("gt") == 0)
- { token.configure_operator(TVL_GREATER, 6); return; }
- if (buffer.compare("ge") == 0)
- { token.configure_operator(TVL_GREATEROREQUAL, 6); return; }
- if (buffer.compare("eq") == 0)
- { token.configure_operator(TVL_EQUAL, 7); return; }
- if (buffer.compare("ne") == 0)
- { token.configure_operator(TVL_NOTEQUAL, 7); return; }
- if (buffer.compare("not") == 0)
- { token.configure_operator(TVL_COMPLEMENT, 2); return; }
- if (buffer.compare("and") == 0)
- { token.configure_operator(TVL_LAND, 8); return; }
- if (buffer.compare("band") == 0)
- { token.configure_operator(TVL_BAND, 8); return; }
- if (buffer.compare("or") == 0)
- { token.configure_operator(TVL_LOR, 12); return; }
- if (buffer.compare("bor") == 0)
- { token.configure_operator(TVL_BOR, 10); return; }
- if (buffer.compare("bxor") == 0)
- { token.configure_operator(TVL_BXOR, 9); return; }
- if (buffer.compare("lshift") == 0)
- { token.configure_operator(TVL_LSHIFT, 5); return; }
- if (buffer.compare("rshift") == 0)
- { token.configure_operator(TVL_RSHIFT, 5); return; }
-
- // if we have an 0x prefix, we must be a hex value
- if (buffer[0] == '0' && buffer[1] == 'x')
- return parse_number(token, buffer.c_str() + 2, 16, expression_error::INVALID_NUMBER);
-
- // if we have a # prefix, we must be a decimal value
- if (buffer[0] == '#')
- return parse_number(token, buffer.c_str() + 1, 10, expression_error::INVALID_NUMBER);
-
- // if we have a $ prefix, we are a hex value
- if (buffer[0] == '$')
- return parse_number(token, buffer.c_str() + 1, 16, expression_error::INVALID_NUMBER);
-
- // check for a symbol match
- symbol_entry *symbol = m_symtable->find_deep(buffer.c_str());
- if (symbol != NULL)
- {
- token.configure_symbol(*symbol);
-
- // if this is a function symbol, synthesize an execute function operator
- if (symbol->is_function())
- {
- parse_token &newtoken = m_tokenlist.append(*global_alloc(parse_token(string - stringstart)));
- newtoken.configure_operator(TVL_EXECUTEFUNC, 0);
- }
- return;
- }
-
- // attempt to parse as a number in the default base
- parse_number(token, buffer.c_str(), DEFAULT_BASE, expression_error::UNKNOWN_SYMBOL);
-}
-
-
-//-------------------------------------------------
-// parse_number - parse a number using the
-// given base
-//-------------------------------------------------
-
-void parsed_expression::parse_number(parse_token &token, const char *string, int base, expression_error::error_code errcode)
-{
- // parse the actual value
- UINT64 value = 0;
- while (*string != 0)
- {
- // look up the number's value, stopping if not valid
- static const char numbers[] = "0123456789abcdef";
- const char *ptr = strchr(numbers, tolower((UINT8)*string));
- if (ptr == NULL)
- break;
-
- // if outside of the base, we also stop
- int digit = ptr - numbers;
- if (digit >= base)
- break;
-
- // shift previous digits up and add in new digit
- value = (value * (UINT64)base) + digit;
- string++;
- }
-
- // if we succeeded as a number, make it so
- if (*string == 0)
- token.configure_number(value);
- else
- throw expression_error(errcode, token.offset());
-}
-
-
-//-------------------------------------------------
-// parse_quoted_char - parse a single-quoted
-// character constant
-//-------------------------------------------------
-
-void parsed_expression::parse_quoted_char(parse_token &token, const char *&string)
-{
- // accumulate the value of the character token
- string++;
- UINT64 value = 0;
- while (string[0] != 0)
- {
- // allow '' to mean a nested single quote
- if (string[0] == '\'')
- {
- if (string[1] != '\'')
- break;
- string++;
- }
- value = (value << 8) | (UINT8)*string++;
- }
-
- // if we didn't find the ending quote, report an error
- if (string[0] != '\'')
- throw expression_error(expression_error::UNBALANCED_QUOTES, token.offset());
- string++;
-
- // make it a number token
- token.configure_number(value);
-}
-
-
-//-------------------------------------------------
-// parse_quoted_string - parse a double-quoted
-// string constant
-//-------------------------------------------------
-
-void parsed_expression::parse_quoted_string(parse_token &token, const char *&string)
-{
- // accumulate a copy of the quoted string
- string++;
- std::string buffer;
- while (string[0] != 0)
- {
- // allow "" to mean a nested double-quote
- if (string[0] == '"')
- {
- if (string[1] != '"')
- break;
- string++;
- }
- buffer.append(string++, 1);
- }
-
- // if we didn't find the ending quote, report an error
- if (string[0] != '"')
- throw expression_error(expression_error::UNBALANCED_QUOTES, token.offset());
- string++;
-
- // make the token
- token.configure_string(m_stringlist.append(*global_alloc(expression_string(buffer.c_str()))));
-}
-
-
-//-------------------------------------------------
-// parse_memory_operator - parse the several
-// forms of memory operators
-//-------------------------------------------------
-
-void parsed_expression::parse_memory_operator(parse_token &token, const char *string)
-{
- // if there is a '.', it means we have a name
- const char *startstring = string;
- const char *namestring = NULL;
- const char *dot = strrchr(string, '.');
- if (dot != NULL)
- {
- namestring = m_stringlist.append(*global_alloc(expression_string(string, dot - string)));
- string = dot + 1;
- }
-
- // length 3 means logical/physical, then space, then size
- int length = (int)strlen(string);
- bool physical = false;
- int space = 'p';
- int size;
- if (length == 3)
- {
- if (string[0] != 'l' && string[0] != 'p')
- throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
- if (string[1] != 'p' && string[1] != 'd' && string[1] != 'i' && string[1] != '3')
- throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
- physical = (string[0] == 'p');
- space = string[1];
- size = string[2];
- }
-
- // length 2 means space then size
- else if (length == 2)
- {
- space = string[0];
- size = string[1];
- }
-
- // length 1 means size
- else if (length == 1)
- size = string[0];
-
- // anything else is invalid
- else
- throw expression_error(expression_error::INVALID_TOKEN, token.offset());
-
- // convert the space to flags
- expression_space memspace = EXPSPACE_INVALID;
- switch (space)
- {
- case 'p': memspace = physical ? EXPSPACE_PROGRAM_PHYSICAL : EXPSPACE_PROGRAM_LOGICAL; break;
- case 'd': memspace = physical ? EXPSPACE_DATA_PHYSICAL : EXPSPACE_DATA_LOGICAL; break;
- case 'i': memspace = physical ? EXPSPACE_IO_PHYSICAL : EXPSPACE_IO_LOGICAL; break;
- case '3': memspace = physical ? EXPSPACE_SPACE3_PHYSICAL : EXPSPACE_SPACE3_LOGICAL; break;
- case 'o': memspace = EXPSPACE_OPCODE; break;
- case 'r': memspace = EXPSPACE_RAMWRITE; break;
- case 'm': memspace = EXPSPACE_REGION; break;
- default: throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
- }
-
- // convert the size to flags
- int memsize;
- switch (size)
- {
- case 'b': memsize = 0; break;
- case 'w': memsize = 1; break;
- case 'd': memsize = 2; break;
- case 'q': memsize = 3; break;
- default: throw expression_error(expression_error::INVALID_MEMORY_SIZE, token.offset() + (string - startstring) + length - 1);
- }
-
- // validate the name
- if (m_symtable != NULL)
- {
- expression_error::error_code err = m_symtable->memory_valid(namestring, memspace);
- if (err != expression_error::NONE)
- throw expression_error(err, token.offset() + (string - startstring));
- }
-
- // configure the token
- token.configure_operator(TVL_MEMORYAT, 2).set_memory_size(memsize).set_memory_space(memspace).set_memory_source(namestring);
-}
-
-
-//-------------------------------------------------
-// normalize_operator - resolve operator
-// ambiguities based on neighboring tokens
-//-------------------------------------------------
-
-void parsed_expression::normalize_operator(parse_token *prevtoken, parse_token &thistoken)
-{
- parse_token *nexttoken = thistoken.next();
- switch (thistoken.optype())
- {
- // Determine if an open paren is part of a function or not
- case TVL_LPAREN:
- if (prevtoken != NULL && prevtoken->is_operator(TVL_EXECUTEFUNC))
- thistoken.set_function_separator();
- break;
-
- // Determine if ++ is a pre or post increment
- case TVL_PLUSPLUS:
- if (nexttoken != NULL && (nexttoken->is_symbol() || (nexttoken->is_operator(TVL_MEMORYAT))))
- thistoken.configure_operator(TVL_PREINCREMENT, 2);
- else if (prevtoken != NULL && (prevtoken->is_symbol() || (prevtoken->is_operator(TVL_MEMORYAT))))
- thistoken.configure_operator(TVL_POSTINCREMENT, 1);
- else
- throw expression_error(expression_error::SYNTAX, thistoken.offset());
- break;
-
- // Determine if -- is a pre or post decrement
- case TVL_MINUSMINUS:
- if (nexttoken != NULL && (nexttoken->is_symbol() || (nexttoken->is_operator(TVL_MEMORYAT))))
- thistoken.configure_operator(TVL_PREDECREMENT, 2);
- else if (prevtoken != NULL && (prevtoken->is_symbol() || (prevtoken->is_operator(TVL_MEMORYAT))))
- thistoken.configure_operator(TVL_POSTDECREMENT, 1);
- else
- throw expression_error(expression_error::SYNTAX, thistoken.offset());
- break;
-
- // Determine if +/- is a unary or binary
- case TVL_ADD:
- case TVL_SUBTRACT:
- // Assume we're unary if we are the first token, or if the previous token is not
- // a symbol, a number, or a right parenthesis
- if (prevtoken == NULL || (!prevtoken->is_symbol() && !prevtoken->is_number() && !prevtoken->is_operator(TVL_RPAREN)))
- thistoken.configure_operator(thistoken.is_operator(TVL_ADD) ? TVL_UPLUS : TVL_UMINUS, 2);
- break;
-
- // Determine if , refers to a function parameter
- case TVL_COMMA:
- for (int lookback = 0; lookback < MAX_STACK_DEPTH; lookback++)
- {
- parse_token *peek = peek_token(lookback);
- if (peek == NULL)
- break;
-
- // if we hit an execute function operator, or else a left parenthesis that is
- // already tagged, then tag us as well
- if (peek->is_operator(TVL_EXECUTEFUNC) || (peek->is_operator(TVL_LPAREN) && peek->is_function_separator()))
- {
- thistoken.set_function_separator();
- break;
- }
- }
- break;
- }
-}
-
-
-//-------------------------------------------------
-// infix_to_postfix - convert an infix sequence
-// of tokens to a postfix sequence for processing
-//-------------------------------------------------
-
-void parsed_expression::infix_to_postfix()
-{
- simple_list<parse_token> stack;
-
- // loop over all the original tokens
- parse_token *prev = NULL;
- parse_token *next = NULL;
- for (parse_token *token = m_tokenlist.detach_all(); token != NULL; prev = token, token = next)
- {
- // pre-determine our next token
- next = token->next();
-
- // if the character is an operand, append it to the result string
- if (token->is_number() || token->is_symbol() || token->is_string())
- m_tokenlist.append(*token);
-
- // if this is an operator, process it
- else if (token->is_operator())
- {
- // normalize the operator based on neighbors
- normalize_operator(prev, *token);
-
- // if the token is an opening parenthesis, push it onto the stack.
- if (token->is_operator(TVL_LPAREN))
- stack.prepend(*token);
-
- // if the token is a closing parenthesis, pop all operators until we
- // reach an opening parenthesis and append them to the result string,
- // discaring the open parenthesis
- else if (token->is_operator(TVL_RPAREN))
- {
- // loop until we find our matching opener
- parse_token *popped;
- while ((popped = stack.detach_head()) != NULL)
- {
- if (popped->is_operator(TVL_LPAREN))
- break;
- m_tokenlist.append(*popped);
- }
-
- // if we didn't find an open paren, it's an error
- if (popped == NULL)
- throw expression_error(expression_error::UNBALANCED_PARENS, token->offset());
-
- // free ourself and our matching opening parenthesis
- global_free(token);
- global_free(popped);
- }
-
- // if the token is an operator, pop operators until we reach an opening parenthesis,
- // an operator of lower precedence, or a right associative symbol of equal precedence.
- // Push the operator onto the stack.
- else
- {
- int our_precedence = token->precedence();
-
- // loop until we can't peek at the stack anymore
- parse_token *peek;
- while ((peek = stack.first()) != NULL)
- {
- // break if any of the above conditions are true
- if (peek->is_operator(TVL_LPAREN))
- break;
- int stack_precedence = peek->precedence();
- if (stack_precedence > our_precedence || (stack_precedence == our_precedence && peek->right_to_left()))
- break;
-
- // pop this token
- m_tokenlist.append(*stack.detach_head());
- }
-
- // push the new operator
- stack.prepend(*token);
- }
- }
- }
-
- // finish popping the stack
- parse_token *popped;
- while ((popped = stack.detach_head()) != NULL)
- {
- // it is an error to have a left parenthesis still on the stack
- if (popped->is_operator(TVL_LPAREN))
- throw expression_error(expression_error::UNBALANCED_PARENS, popped->offset());
-
- // pop this token
- m_tokenlist.append(*popped);
- }
-}
-
-
-//-------------------------------------------------
-// push_token - push a token onto the stack
-//-------------------------------------------------
-
-inline void parsed_expression::push_token(parse_token &token)
-{
- // check for overflow
- if (m_token_stack_ptr >= MAX_STACK_DEPTH)
- throw expression_error(expression_error::STACK_OVERFLOW, token.offset());
-
- // push
- m_token_stack[m_token_stack_ptr++] = token;
-}
-
-
-//-------------------------------------------------
-// pop_token - pop a token off the stack
-//-------------------------------------------------
-
-inline void parsed_expression::pop_token(parse_token &token)
-{
- // check for underflow
- if (m_token_stack_ptr == 0)
- throw expression_error(expression_error::STACK_UNDERFLOW, token.offset());
-
- // pop
- token = m_token_stack[--m_token_stack_ptr];
-}
-
-
-//-------------------------------------------------
-// peek_token - look at a token some number of
-// entries up the stack
-//-------------------------------------------------
-
-inline parsed_expression::parse_token *parsed_expression::peek_token(int count)
-{
- if (m_token_stack_ptr <= count)
- return NULL;
- return &m_token_stack[m_token_stack_ptr - count - 1];
-}
-
-
-//-------------------------------------------------
-// pop_token_lval - pop a token off the stack
-// and ensure that it is a proper lval
-//-------------------------------------------------
-
-inline void parsed_expression::pop_token_lval(parse_token &token)
-{
- // start with normal pop
- pop_token(token);
-
- // if we're not an lval, throw an error
- if (!token.is_lval())
- throw expression_error(expression_error::NOT_LVAL, token.offset());
-}
-
-
-//-------------------------------------------------
-// pop_token_rval - pop a token off the stack
-// and ensure that it is a proper rval
-//-------------------------------------------------
-
-inline void parsed_expression::pop_token_rval(parse_token &token)
-{
- // start with normal pop
- pop_token(token);
-
- // symbol and memory tokens get resolved down to number tokens
- if (token.is_symbol() || token.is_memory())
- token.configure_number(token.get_lval_value(m_symtable));
-
- // to be an rval, the final token must be a number
- if (!token.is_number())
- throw expression_error(expression_error::NOT_RVAL, token.offset());
-}
-
-
-//-------------------------------------------------
-// execute_tokens - execute a postfix sequence
-// of tokens
-//-------------------------------------------------
-
-UINT64 parsed_expression::execute_tokens()
-{
- // reset the token stack
- m_token_stack_ptr = 0;
-
- // loop over the entire sequence
- parse_token t1, t2, result;
- for (parse_token *token = m_tokenlist.first(); token != NULL; token = token->next())
- {
- // symbols/numbers/strings just get pushed
- if (!token->is_operator())
- {
- push_token(*token);
- continue;
- }
-
- // otherwise, switch off the operator
- switch (token->optype())
- {
- case TVL_PREINCREMENT:
- pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) + 1).set_offset(t1));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_PREDECREMENT:
- pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) - 1).set_offset(t1));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_POSTINCREMENT:
- pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable)).set_offset(t1));
- t1.set_lval_value(m_symtable, result.value() + 1);
- break;
-
- case TVL_POSTDECREMENT:
- pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable)).set_offset(t1));
- t1.set_lval_value(m_symtable, result.value() - 1);
- break;
-
- case TVL_COMPLEMENT:
- pop_token_rval(t1);
- push_token(result.configure_number(!t1.value()).set_offset(t1));
- break;
-
- case TVL_NOT:
- pop_token_rval(t1);
- push_token(result.configure_number(~t1.value()).set_offset(t1));
- break;
-
- case TVL_UPLUS:
- pop_token_rval(t1);
- push_token(result.configure_number(t1.value()).set_offset(t1));
- break;
-
- case TVL_UMINUS:
- pop_token_rval(t1);
- push_token(result.configure_number(-t1.value()).set_offset(t1));
- break;
-
- case TVL_MULTIPLY:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() * t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_DIVIDE:
- pop_token_rval(t2); pop_token_rval(t1);
- if (t2.value() == 0)
- throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
- push_token(result.configure_number(t1.value() / t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_MODULO:
- pop_token_rval(t2); pop_token_rval(t1);
- if (t2.value() == 0)
- throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
- push_token(result.configure_number(t1.value() % t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_ADD:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() + t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_SUBTRACT:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() - t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_LSHIFT:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() << t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_RSHIFT:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() >> t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_LESS:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() < t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_LESSOREQUAL:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() <= t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_GREATER:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() > t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_GREATEROREQUAL:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() >= t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_EQUAL:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() == t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_NOTEQUAL:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() != t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_BAND:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() & t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_BXOR:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() ^ t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_BOR:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() | t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_LAND:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() && t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_LOR:
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(result.configure_number(t1.value() || t2.value()).set_offset(t1, t2));
- break;
-
- case TVL_ASSIGN:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t2.value()).set_offset(t2));
- t1.set_lval_value(m_symtable, t2.value());
- break;
-
- case TVL_ASSIGNMULTIPLY:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) * t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNDIVIDE:
- pop_token_rval(t2); pop_token_lval(t1);
- if (t2.value() == 0)
- throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
- push_token(result.configure_number(t1.get_lval_value(m_symtable) / t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNMODULO:
- pop_token_rval(t2); pop_token_lval(t1);
- if (t2.value() == 0)
- throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
- push_token(result.configure_number(t1.get_lval_value(m_symtable) % t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNADD:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) + t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNSUBTRACT:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) - t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNLSHIFT:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) << t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNRSHIFT:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) >> t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNBAND:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) & t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNBXOR:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) ^ t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_ASSIGNBOR:
- pop_token_rval(t2); pop_token_lval(t1);
- push_token(result.configure_number(t1.get_lval_value(m_symtable) | t2.value()).set_offset(t1, t2));
- t1.set_lval_value(m_symtable, result.value());
- break;
-
- case TVL_COMMA:
- if (!token->is_function_separator())
- {
- pop_token_rval(t2); pop_token_rval(t1);
- push_token(t2);
- }
- break;
-
- case TVL_MEMORYAT:
- pop_token_rval(t1);
- push_token(result.configure_memory(t1.value(), *token));
- break;
-
- case TVL_EXECUTEFUNC:
- execute_function(*token);
- break;
-
- default:
- throw expression_error(expression_error::SYNTAX, token->offset());
- }
- }
-
- // pop the final result
- pop_token_rval(result);
-
- // error if our stack isn't empty
- if (peek_token(0) != NULL)
- throw expression_error(expression_error::SYNTAX, 0);
-
- return result.value();
-}
-
-
-
-//**************************************************************************
-// PARSE TOKEN
-//**************************************************************************
-
-//-------------------------------------------------
-// parse_token - constructor
-//-------------------------------------------------
-
-parsed_expression::parse_token::parse_token(int offset)
- : m_next(NULL),
- m_type(INVALID),
- m_offset(offset),
- m_value(0),
- m_flags(0),
- m_string(NULL),
- m_symbol(NULL)
-{
-}
-
-
-//-------------------------------------------------
-// get_lval_value - call the getter function
-// for a SYMBOL token
-//-------------------------------------------------
-
-UINT64 parsed_expression::parse_token::get_lval_value(symbol_table *table)
-{
- // get the value of a symbol
- if (is_symbol())
- return m_symbol->value();
-
- // or get the value from the memory callbacks
- else if (is_memory() && table != NULL)
- return table->memory_value(m_string, memory_space(), address(), 1 << memory_size());
-
- return 0;
-}
-
-
-//-------------------------------------------------
-// set_lval_value - call the setter function
-// for a SYMBOL token
-//-------------------------------------------------
-
-inline void parsed_expression::parse_token::set_lval_value(symbol_table *table, UINT64 value)
-{
- // set the value of a symbol
- if (is_symbol())
- m_symbol->set_value(value);
-
- // or set the value via the memory callbacks
- else if (is_memory() && table != NULL)
- table->set_memory_value(m_string, memory_space(), address(), 1 << memory_size(), value);
-}
-
-
-//-------------------------------------------------
-// execute_function - handle an execute function
-// operator
-//-------------------------------------------------
-
-void parsed_expression::execute_function(parse_token &token)
-{
- // pop off all pushed parameters
- UINT64 funcparams[MAX_FUNCTION_PARAMS];
- symbol_entry *symbol = NULL;
- int paramcount = 0;
- while (paramcount < MAX_FUNCTION_PARAMS)
- {
- // peek at the next token on the stack
- parse_token *peek = peek_token(0);
- if (peek == NULL)
- throw expression_error(expression_error::INVALID_PARAM_COUNT, token.offset());
-
- // if it is a function symbol, break out of the loop
- if (peek->is_symbol())
- {
- symbol = peek->symbol();
- if (symbol->is_function())
- {
- parse_token t1;
- pop_token(t1);
- break;
- }
- }
-
- // otherwise, pop as a standard rval
- parse_token t1;
- pop_token_rval(t1);
- funcparams[MAX_FUNCTION_PARAMS - (++paramcount)] = t1.value();
- }
-
- // if we didn't find the symbol, fail
- if (paramcount == MAX_FUNCTION_PARAMS)
- throw expression_error(expression_error::INVALID_PARAM_COUNT, token.offset());
-
- // execute the function and push the result
- function_symbol_entry *function = downcast<function_symbol_entry *>(symbol);
- parse_token result(token.offset());
- result.configure_number(function->execute(paramcount, &funcparams[MAX_FUNCTION_PARAMS - paramcount]));
- push_token(result);
-}