Refactor remaining tokensplitters
Also fixes some bugs with memory search.
This commit is contained in:
parent
4cf07bd298
commit
b1c2441da4
4 changed files with 39 additions and 117 deletions
|
@ -71,44 +71,6 @@ private:
|
|||
std::string commandname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Splits string to fields on ' ' and '\t', with multiple whitespace collapsed into one.
|
||||
*/
|
||||
class tokensplitter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a new splitter.
|
||||
*
|
||||
* parameter _line: The line to start splitting.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
tokensplitter(const std::string& _line) throw(std::bad_alloc);
|
||||
/**
|
||||
* Are there more tokens coming?
|
||||
*
|
||||
* returns: True if there is at least one token coming, false otherwise.
|
||||
*/
|
||||
operator bool() throw();
|
||||
/**
|
||||
* Get the next token.
|
||||
*
|
||||
* returns: The next token from line. If there are no more tokens, returns "".
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
operator std::string() throw(std::bad_alloc);
|
||||
/**
|
||||
* Get all remaining line in one go.
|
||||
*
|
||||
* returns: All remaining parts of line as-is.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
std::string tail() throw(std::bad_alloc);
|
||||
private:
|
||||
std::string line;
|
||||
size_t position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mandatory filename
|
||||
*/
|
||||
|
|
|
@ -39,30 +39,25 @@ namespace
|
|||
messages << "alias " << i.first << " " << j << std::endl;
|
||||
});
|
||||
|
||||
function_ptr_command<tokensplitter&> unalias_command("unalias-command", "unalias a command",
|
||||
function_ptr_command<const std::string&> unalias_command("unalias-command", "unalias a command",
|
||||
"Syntax: unalias-command <aliasname>\nClear expansion of alias <aliasname>\n",
|
||||
[](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
|
||||
std::string aliasname = t;
|
||||
if(t)
|
||||
throw std::runtime_error("This command only takes one argument");
|
||||
if(!command::valid_alias_name(aliasname))
|
||||
[](const std::string& t) throw(std::bad_alloc, std::runtime_error) {
|
||||
auto r = regex("([^ \t]+)[ \t]*", t, "This command only takes one argument");
|
||||
if(!command::valid_alias_name(r[1]))
|
||||
throw std::runtime_error("Illegal alias name");
|
||||
aliases[aliasname].clear();
|
||||
messages << "Command '" << aliasname << "' unaliased" << std::endl;
|
||||
aliases[r[1]].clear();
|
||||
messages << "Command '" << r[1] << "' unaliased" << std::endl;
|
||||
});
|
||||
|
||||
function_ptr_command<tokensplitter&> alias_command("alias-command", "alias a command",
|
||||
function_ptr_command<const std::string&> alias_command("alias-command", "alias a command",
|
||||
"Syntax: alias-command <aliasname> <command>\nAppend <command> to expansion of alias <aliasname>\n"
|
||||
"Valid alias names can't be empty nor start with '*' or '?'\n",
|
||||
[](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
|
||||
std::string aliasname = t;
|
||||
std::string command = t.tail();
|
||||
if(command == "")
|
||||
throw std::runtime_error("Alias name and command needed");
|
||||
if(!command::valid_alias_name(aliasname))
|
||||
[](const std::string& t) throw(std::bad_alloc, std::runtime_error) {
|
||||
auto r = regex("([^ \t]+)[ \t]+([^ \t].*)", t, "Alias name and command needed");
|
||||
if(!command::valid_alias_name(r[1]))
|
||||
throw std::runtime_error("Illegal alias name");
|
||||
aliases[aliasname].push_back(command);
|
||||
messages << "Command '" << aliasname << "' aliased to '" << command << "'" << std::endl;
|
||||
aliases[r[1]].push_back(r[2]);
|
||||
messages << "Command '" << r[1] << "' aliased to '" << r[2] << "'" << std::endl;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -206,37 +201,6 @@ bool command::valid_alias_name(const std::string& aliasname) throw(std::bad_allo
|
|||
return true;
|
||||
}
|
||||
|
||||
tokensplitter::tokensplitter(const std::string& _line) throw(std::bad_alloc)
|
||||
{
|
||||
line = _line;
|
||||
position = 0;
|
||||
}
|
||||
|
||||
tokensplitter::operator bool() throw()
|
||||
{
|
||||
return (position < line.length());
|
||||
}
|
||||
|
||||
tokensplitter::operator std::string() throw(std::bad_alloc)
|
||||
{
|
||||
size_t nextp, oldp = position;
|
||||
nextp = line.find_first_of(" \t", position);
|
||||
if(nextp > line.length()) {
|
||||
position = line.length();
|
||||
return line.substr(oldp);
|
||||
} else {
|
||||
position = nextp;
|
||||
while(position < line.length() && (line[position] == ' ' || line[position] == '\t'))
|
||||
position++;
|
||||
return line.substr(oldp, nextp - oldp);
|
||||
}
|
||||
}
|
||||
|
||||
std::string tokensplitter::tail() throw(std::bad_alloc)
|
||||
{
|
||||
return line.substr(position);
|
||||
}
|
||||
|
||||
template<>
|
||||
void invoke_command_fn(void (*fn)(const std::string& args), const std::string& args)
|
||||
{
|
||||
|
@ -260,10 +224,3 @@ void invoke_command_fn(void (*fn)(struct arg_filename a), const std::string& arg
|
|||
b.v = args;
|
||||
fn(b);
|
||||
}
|
||||
|
||||
template<>
|
||||
void invoke_command_fn(void (*fn)(tokensplitter& a), const std::string& args)
|
||||
{
|
||||
tokensplitter t(args);
|
||||
fn(t);
|
||||
}
|
||||
|
|
|
@ -67,15 +67,16 @@ namespace
|
|||
controls.analog(pcid, x / 2 , y / 2);
|
||||
}
|
||||
|
||||
function_ptr_command<tokensplitter&> autofire("autofire", "Set autofire pattern",
|
||||
function_ptr_command<const std::string&> autofire("autofire", "Set autofire pattern",
|
||||
"Syntax: autofire <buttons|->...\nSet autofire pattern\n",
|
||||
[](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
|
||||
if(!t)
|
||||
throw std::runtime_error("Need at least one frame for autofire");
|
||||
[](const std::string& a) throw(std::bad_alloc, std::runtime_error) {
|
||||
auto r = regex(".*[^ \t].*", a, "Need at least one frame for autofire");
|
||||
std::vector<controller_frame> new_autofire_pattern;
|
||||
init_buttonmap();
|
||||
while(t) {
|
||||
std::string fpattern = t;
|
||||
std::string pattern = a;
|
||||
while(pattern != "") {
|
||||
std::string fpattern;
|
||||
extract_token(pattern, fpattern, " \t", true);
|
||||
if(fpattern == "-")
|
||||
new_autofire_pattern.push_back(controls.get_blank());
|
||||
else {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "core/memorymanip.hpp"
|
||||
#include "core/misc.hpp"
|
||||
#include "core/rom.hpp"
|
||||
#include "library/string.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
@ -791,20 +792,20 @@ namespace
|
|||
~memorymanip_command() throw() {}
|
||||
void invoke(const std::string& args) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
tokensplitter t(args);
|
||||
firstword = static_cast<std::string>(t);
|
||||
secondword = static_cast<std::string>(t);
|
||||
has_tail = t;
|
||||
regex_results t = regex("(([^ \t]+)([ \t]+([^ \t]+)([ \t]+([^ \t].*)?)?)?)?", args);
|
||||
firstword = t[2];
|
||||
secondword = t[4];
|
||||
has_tail = (t[6] != "");
|
||||
address_bad = true;
|
||||
value_bad = true;
|
||||
has_value = (secondword != "");
|
||||
try {
|
||||
if(firstword.length() >= 2 && firstword.substr(0, 2) == "0x") {
|
||||
if(firstword.length() > 10)
|
||||
if(t = regex("0x(.+)", firstword)) {
|
||||
if(t[1].length() > 8)
|
||||
throw 42;
|
||||
address = 0;
|
||||
for(unsigned i = 2; i < firstword.length(); i++)
|
||||
address = 16 * address + hex(firstword[i]);
|
||||
for(unsigned i = 0; i < t[1].length(); i++)
|
||||
address = 16 * address + hex(t[1][i]);
|
||||
} else {
|
||||
address = parse_value<uint32_t>(firstword);
|
||||
}
|
||||
|
@ -812,13 +813,13 @@ namespace
|
|||
} catch(...) {
|
||||
}
|
||||
try {
|
||||
if(secondword.length() >= 2 && secondword.substr(0, 2) == "0x") {
|
||||
if(secondword.length() > 18)
|
||||
if(t = regex("0x(.+)", secondword)) {
|
||||
if(t[1].length() > 16)
|
||||
throw 42;
|
||||
value = 0;
|
||||
for(unsigned i = 2; i < secondword.length(); i++)
|
||||
value = 16 * value + hex(secondword[i]);
|
||||
} else if(secondword.length() > 0 && secondword[0] == '-') {
|
||||
for(unsigned i = 0; i < t[1].length(); i++)
|
||||
value = 16 * value + hex(t[1][i]);
|
||||
} else if(regex("-.*", secondword)) {
|
||||
value = static_cast<uint64_t>(parse_value<int64_t>(secondword));
|
||||
} else {
|
||||
value = parse_value<uint64_t>(secondword);
|
||||
|
@ -885,7 +886,8 @@ namespace
|
|||
{
|
||||
if(address_bad || value_bad || has_tail)
|
||||
throw std::runtime_error("Syntax: " + _command + " <address> <value>");
|
||||
if(static_cast<int64_t>(value) < low || value > high)
|
||||
int64_t value2 = static_cast<int64_t>(value);
|
||||
if(value2 < low || (value > high && value2 >= 0))
|
||||
throw std::runtime_error("Value to write out of range");
|
||||
wfn(address, value & high);
|
||||
}
|
||||
|
@ -911,7 +913,7 @@ namespace
|
|||
else if(firstword == "sble" && !has_value)
|
||||
isrch->byte_sle();
|
||||
else if(firstword == "sbeq" && !has_value)
|
||||
isrch->byte_seq();
|
||||
isrch->byte_seq();
|
||||
else if(firstword == "sbne" && !has_value)
|
||||
isrch->byte_sne();
|
||||
else if(firstword == "sbge" && !has_value)
|
||||
|
@ -961,7 +963,7 @@ namespace
|
|||
else if(firstword == "w" && has_value) {
|
||||
if(static_cast<int64_t>(value) < -32768 || value > 65535)
|
||||
throw std::runtime_error("Value to compare out of range");
|
||||
isrch->word_value(value & 0xFF);
|
||||
isrch->word_value(value & 0xFFFF);
|
||||
} else if(firstword == "sdlt" && !has_value)
|
||||
isrch->dword_slt();
|
||||
else if(firstword == "sdle" && !has_value)
|
||||
|
@ -989,7 +991,7 @@ namespace
|
|||
else if(firstword == "d" && has_value) {
|
||||
if(static_cast<int64_t>(value) < -2147483648LL || value > 4294967295ULL)
|
||||
throw std::runtime_error("Value to compare out of range");
|
||||
isrch->dword_value(value & 0xFF);
|
||||
isrch->dword_value(value & 0xFFFFFFFFULL);
|
||||
} else if(firstword == "sqlt" && !has_value)
|
||||
isrch->qword_slt();
|
||||
else if(firstword == "sqle" && !has_value)
|
||||
|
@ -1015,7 +1017,7 @@ namespace
|
|||
else if(firstword == "uqgt" && !has_value)
|
||||
isrch->qword_ugt();
|
||||
else if(firstword == "q" && has_value)
|
||||
isrch->qword_value(value & 0xFF);
|
||||
isrch->qword_value(value);
|
||||
else if(firstword == "update" && !has_value)
|
||||
isrch->update();
|
||||
else if(firstword == "reset" && !has_value)
|
||||
|
|
Loading…
Add table
Reference in a new issue