Made EquateList use a couple of STL maps to store address => label and

label => address mappings. It should be faster than the linear search,
and it's a damn sight cleaner. Still TODO is to restore the case-insensitive
string matching from the original version.

Changed a few EquateList methods that used to return char*, so they now
return string or string&. Changed other classes that call them so they
work with the new return types.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@633 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-07-12 02:27:07 +00:00
parent 9bce69cd2b
commit 5702496cdc
8 changed files with 100 additions and 145 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.cxx,v 1.59 2005-07-10 02:15:55 stephena Exp $ // $Id: Debugger.cxx,v 1.60 2005-07-12 02:27:04 urchlay Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -607,12 +607,13 @@ int Debugger::cycles() {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Debugger::disassemble(int start, int lines) { const string& Debugger::disassemble(int start, int lines) {
char buf[255], bbuf[255]; char buf[255], bbuf[255];
string result; static string result;
result = "";
do { do {
char *label = equateList->getFormatted(start, 4); const char *label = equateList->getFormatted(start, 4);
result += label; result += label;
result += ": "; result += ": ";

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.hxx,v 1.47 2005-07-10 02:15:57 stephena Exp $ // $Id: Debugger.hxx,v 1.48 2005-07-12 02:27:05 urchlay Exp $
//============================================================================ //============================================================================
#ifndef DEBUGGER_HXX #ifndef DEBUGGER_HXX
@ -52,7 +52,7 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc). for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony @author Stephen Anthony
@version $Id: Debugger.hxx,v 1.47 2005-07-10 02:15:57 stephena Exp $ @version $Id: Debugger.hxx,v 1.48 2005-07-12 02:27:05 urchlay Exp $
*/ */
class Debugger : public DialogContainer class Debugger : public DialogContainer
{ {
@ -149,7 +149,7 @@ class Debugger : public DialogContainer
Disassemble from the starting address the specified number of lines Disassemble from the starting address the specified number of lines
and place result in a string. and place result in a string.
*/ */
string disassemble(int start, int lines); const string& disassemble(int start, int lines);
int step(); int step();
int trace(); int trace();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: DebuggerParser.cxx,v 1.50 2005-07-11 18:56:26 urchlay Exp $ // $Id: DebuggerParser.cxx,v 1.51 2005-07-12 02:27:06 urchlay Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -451,7 +451,7 @@ int DebuggerParser::conv_hex_digit(char d) {
int DebuggerParser::decipher_arg(const string &str) { int DebuggerParser::decipher_arg(const string &str) {
bool derefByte=false, derefWord=false, lobyte=false, hibyte=false, bin=false, dec=false; bool derefByte=false, derefWord=false, lobyte=false, hibyte=false, bin=false, dec=false;
int result; int result;
string arg = str; string arg = str;
if(defaultBase == kBASE_2) { if(defaultBase == kBASE_2) {
bin=true; dec=false; bin=true; dec=false;
@ -506,7 +506,7 @@ int DebuggerParser::decipher_arg(const string &str) {
else if(arg == "pc" || arg == ".") result = state.PC; else if(arg == "pc" || arg == ".") result = state.PC;
else { // Not a special, must be a regular arg: check for label first else { // Not a special, must be a regular arg: check for label first
const char *a = arg.c_str(); const char *a = arg.c_str();
result = debugger->equateList->getAddress(a); result = debugger->equateList->getAddress(arg);
if(result < 0) { // if not label, must be a number if(result < 0) { // if not label, must be a number
if(bin) { // treat as binary if(bin) { // treat as binary
@ -697,8 +697,8 @@ string DebuggerParser::eval() {
char buf[50]; char buf[50];
string ret; string ret;
for(int i=0; i<argCount; i++) { for(int i=0; i<argCount; i++) {
char *label = debugger->equates()->getLabel(args[i]); string label = debugger->equates()->getLabel(args[i]);
if(label != NULL) { if(label != "") {
ret += label; ret += label;
ret += ": "; ret += ": ";
} }
@ -783,8 +783,8 @@ string DebuggerParser::trapStatus(int addr) {
else else
result += " none "; result += " none ";
char *l = debugger->equateList->getLabel(addr); string l = debugger->equateList->getLabel(addr);
if(l != NULL) { if(l != "") {
result += " ("; result += " (";
result += l; result += l;
result += ")"; result += ")";

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EquateList.cxx,v 1.16 2005-06-25 01:13:00 urchlay Exp $ // $Id: EquateList.cxx,v 1.17 2005-07-12 02:27:06 urchlay Exp $
//============================================================================ //============================================================================
#include <string> #include <string>
@ -99,44 +99,44 @@ static Equate hardCodedEquates[] = {
}; };
EquateList::EquateList() { EquateList::EquateList() {
// cerr << sizeof(hardCodedEquates)/sizeof(struct Equate) << endl;
int size = sizeof(hardCodedEquates)/sizeof(struct Equate); int size = sizeof(hardCodedEquates)/sizeof(struct Equate);
for(int i=0; i<size; i++) for(int i=0; i<size; i++) {
ourVcsEquates.push_back(hardCodedEquates[i]); string l = hardCodedEquates[i].label;
int a = hardCodedEquates[i].address;
myFwdMap.insert(make_pair(l, a));
myRevMap.insert(make_pair(a, l));
}
calcSize(); calcSize();
} }
EquateList::~EquateList() { EquateList::~EquateList() {
ourVcsEquates.clear(); myFwdMap.clear();
myRevMap.clear();
} }
int EquateList::calcSize() { int EquateList::calcSize() {
currentSize = ourVcsEquates.size(); currentSize = myFwdMap.size();
return currentSize; return currentSize;
} }
// FIXME: use something smarter than a linear search in the future. const string& EquateList::getLabel(int addr) {
char *EquateList::getLabel(int addr) { static string nothing = "";
// cerr << "getLabel(" << addr << ")" << endl; addrToLabel::const_iterator iter = myRevMap.find(addr);
for(int i=0; i<currentSize; i++) { if(iter == myRevMap.end())
// cerr << "Checking ourVcsEquates[" << i << "] (" << ourVcsEquates[i].label << ")" << endl; return nothing;
if(ourVcsEquates[i].address == addr) { else
// cerr << "Found label " << ourVcsEquates[i].label << endl; return iter->second;
return ourVcsEquates[i].label;
}
}
return NULL;
} }
// returns either the label, or a formatted hex string // returns either the label, or a formatted hex string
// if no label found. // if no label found.
char *EquateList::getFormatted(int addr, int places) { const char *EquateList::getFormatted(int addr, int places) {
static char fmt[10], buf[255]; static char fmt[10], buf[255];
char *res = getLabel(addr); string res = getLabel(addr);
if(res != NULL) if(res != "")
return res; return res.c_str();
sprintf(fmt, "$%%0%dx", places); sprintf(fmt, "$%%0%dx", places);
//cerr << addr << ", " << fmt << ", " << places << endl; //cerr << addr << ", " << fmt << ", " << places << endl;
@ -144,33 +144,25 @@ char *EquateList::getFormatted(int addr, int places) {
return buf; return buf;
} }
int EquateList::getAddress(const char *lbl) { int EquateList::getAddress(const string& label) {
// cerr << "getAddress(" << lbl << ")" << endl; labelToAddr::const_iterator iter = myFwdMap.find(label);
// cerr << ourVcsEquates[0].label << endl; if(iter == myFwdMap.end())
// cerr << "shit" << endl; return -1;
for(int i=0; i<currentSize; i++) { else
// cerr << "Looking at " << ourVcsEquates[i].label << endl; return iter->second;
if( STR_CASE_CMP(ourVcsEquates[i].label, lbl) == 0 )
if(ourVcsEquates[i].address >= 0)
return ourVcsEquates[i].address;
}
return -1;
} }
bool EquateList::undefine(string& label) { bool EquateList::undefine(string& label) {
return undefine(label.c_str());
}
bool EquateList::undefine(const char *lbl) {
for(int i=0; i<currentSize; i++) {
if( STR_CASE_CMP(ourVcsEquates[i].label, lbl) == 0 ) {
ourVcsEquates[i].address = -1;
return true;
}
}
return false; return false;
labelToAddr::iterator iter = myFwdMap.find(label);
if(iter == myFwdMap.end()) {
return false;
} else {
myRevMap.erase( myRevMap.find(iter->second) ); // FIXME: error check?
myFwdMap.erase(iter);
return true;
}
} }
bool EquateList::saveFile(string file) { bool EquateList::saveFile(string file) {
@ -182,16 +174,10 @@ bool EquateList::saveFile(string file) {
out << "--- Symbol List (sorted by symbol)" << endl; out << "--- Symbol List (sorted by symbol)" << endl;
// we don't have these pre-loaded any more. labelToAddr::iterator iter;
// int hardSize = sizeof(hardCodedEquates)/sizeof(struct Equate); for(iter = myFwdMap.begin(); iter != myFwdMap.end(); iter++) {
// for(int i=hardSize; i<currentSize; i++) sprintf(buf, "%-24s %04x \n", iter->first.c_str(), iter->second);
out << buf;
for(int i=0; i<currentSize; i++) {
int a = ourVcsEquates[i].address;
if(a >= 0) {
sprintf(buf, "%-24s %04x \n", ourVcsEquates[i].label, a);
out << buf;
}
} }
out << "--- End of Symbol List." << endl; out << "--- End of Symbol List." << endl;
@ -202,28 +188,14 @@ string EquateList::loadFile(string file) {
int lines = 0; int lines = 0;
string curLabel; string curLabel;
int curVal; int curVal;
// string::size_type p;
char buffer[256]; // FIXME: static buffers suck char buffer[256]; // FIXME: static buffers suck
// cerr << "loading file " << file << endl;
ifstream in(file.c_str()); ifstream in(file.c_str());
if(!in.is_open()) if(!in.is_open())
return "Unable to read symbols from " + file; return "Unable to read symbols from " + file;
myFwdMap.clear();
// Make sure the hard-coded equates show up first myRevMap.clear();
ourVcsEquates.clear();
/*
// Don't preload these: they cause more trouble than they're worth
// Besides which, any sane symfile will already have them all.
int hardSize = sizeof(hardCodedEquates)/sizeof(struct Equate);
for(int i=0; i<hardSize; i++) {
ourVcsEquates.push_back(hardCodedEquates[i]);
}
*/
while( !in.eof() ) { while( !in.eof() ) {
curVal = 0; curVal = 0;
@ -239,8 +211,6 @@ string EquateList::loadFile(string file) {
addEquate(curLabel, curVal); addEquate(curLabel, curVal);
// cerr << "label: " << curLabel << ", address: " << curVal << endl;
// cerr << buffer;
lines++; lines++;
} }
} }
@ -248,22 +218,15 @@ string EquateList::loadFile(string file) {
calcSize(); calcSize();
// dumpAll();
return "loaded " + file + " OK"; return "loaded " + file + " OK";
} }
void EquateList::addEquate(string label, int address) { void EquateList::addEquate(string label, int address) {
// FIXME - this is a memleak and *must* be fixed myFwdMap.insert(make_pair(label, address));
// ideally, the Equate class should hold a string, not a char* myRevMap.insert(make_pair(address, label));
Equate e;
e.label = strdup(label.c_str());
e.address = address;
ourVcsEquates.push_back(e);
calcSize();
} }
int EquateList::parse4hex(char *c) { int EquateList::parse4hex(char *c) {
//cerr << c << endl;
int ret = 0; int ret = 0;
for(int i=0; i<4; i++) { for(int i=0; i<4; i++) {
if(*c >= '0' && *c <= '9') if(*c >= '0' && *c <= '9')
@ -302,49 +265,31 @@ string EquateList::extractLabel(char *c) {
return l; return l;
} }
string EquateList::dumpAll() {
string ret;
for(int i=0; i<currentSize; i++) {
if(ourVcsEquates[i].address != -1) {
ret += ourVcsEquates[i].label;
ret += ": ";
ret += Debugger::to_hex_16(ourVcsEquates[i].address);
if(i != currentSize - 1) ret += "\n";
}
}
return ret;
}
int EquateList::countCompletions(const char *in) { int EquateList::countCompletions(const char *in) {
int count = 0; int count = 0;
completions = compPrefix = ""; completions = compPrefix = "";
// cerr << "Attempting to complete \"" << in << "\"" << endl; labelToAddr::iterator iter;
for(int i=0; i<currentSize; i++) { for(iter = myFwdMap.begin(); iter != myFwdMap.end(); iter++) {
if(ourVcsEquates[i].address != -1) { const char *l = iter->first.c_str();
const char *l = ourVcsEquates[i].label;
if(STR_N_CASE_CMP(l, in, strlen(in)) == 0) { if(STR_N_CASE_CMP(l, in, strlen(in)) == 0) {
if(compPrefix == "") if(compPrefix == "")
compPrefix += l; compPrefix += l;
else { else {
int nonMatch = 0; int nonMatch = 0;
const char *c = compPrefix.c_str(); const char *c = compPrefix.c_str();
while(*c != '\0' && tolower(*c) == tolower(l[nonMatch])) { while(*c != '\0' && tolower(*c) == tolower(l[nonMatch])) {
c++; c++;
nonMatch++; nonMatch++;
}
compPrefix.erase(nonMatch, compPrefix.length());
// cerr << "compPrefix==" << compPrefix << endl;
} }
compPrefix.erase(nonMatch, compPrefix.length());
if(count++) completions += " ";
completions += l;
} }
if(count++) completions += " ";
completions += l;
} }
} }
// cerr << "Found " << count << " label(s):" << endl << completions << endl;
return count; return count;
} }

View File

@ -13,31 +13,38 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EquateList.hxx,v 1.10 2005-06-25 01:13:00 urchlay Exp $ // $Id: EquateList.hxx,v 1.11 2005-07-12 02:27:06 urchlay Exp $
//============================================================================ //============================================================================
#ifndef EQUATELIST_HXX #ifndef EQUATELIST_HXX
#define EQUATELIST_HXX #define EQUATELIST_HXX
#include <map>
#include "bspf.hxx" #include "bspf.hxx"
#include "Equate.hxx" #include "Equate.hxx"
#include "Array.hxx" #include "Array.hxx"
using namespace std;
typedef map<int, string> addrToLabel;
typedef map<string, int> labelToAddr;
typedef GUI::Array<Equate> Equates; typedef GUI::Array<Equate> Equates;
class EquateList { class EquateList {
public: public:
EquateList(); EquateList();
~EquateList(); ~EquateList();
char *getLabel(int addr); const string& getLabel(int addr);
char *getFormatted(int addr, int places); const char *getFormatted(int addr, int places);
int getAddress(const char *label); int getAddress(const string& label);
void addEquate(string label, int address); void addEquate(string label, int address);
bool saveFile(string file); bool saveFile(string file);
string loadFile(string file); string loadFile(string file);
bool undefine(string& label); bool undefine(string& label);
bool undefine(const char *lbl); bool undefine(const char *lbl);
string dumpAll(); //string dumpAll();
int countCompletions(const char *in); int countCompletions(const char *in);
const char *getCompletions(); const char *getCompletions();
const char *getCompletionPrefix(); const char *getCompletionPrefix();
@ -51,8 +58,10 @@ class EquateList {
string compPrefix; string compPrefix;
private: private:
Equates ourVcsEquates; //Equates ourVcsEquates;
int currentSize; int currentSize;
labelToAddr myFwdMap;
addrToLabel myRevMap;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: CpuWidget.cxx,v 1.14 2005-07-08 14:36:18 stephena Exp $ // $Id: CpuWidget.cxx,v 1.15 2005-07-12 02:27:07 urchlay Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -264,8 +264,8 @@ void CpuWidget::fillGrid()
const char* buf; const char* buf;
Debugger& dbg = instance()->debugger(); Debugger& dbg = instance()->debugger();
buf = dbg.equates()->getLabel(pc); buf = dbg.equates()->getLabel(pc).c_str();
if(buf) if(*buf)
myPCLabel->setEditString(buf); myPCLabel->setEditString(buf);
else else
myPCLabel->setEditString(""); myPCLabel->setEditString("");

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: RamWidget.cxx,v 1.18 2005-07-07 20:51:10 stephena Exp $ // $Id: RamWidget.cxx,v 1.19 2005-07-12 02:27:07 urchlay Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -174,8 +174,8 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
addr = myRamGrid->getSelectedAddr(); addr = myRamGrid->getSelectedAddr();
value = myRamGrid->getSelectedValue(); value = myRamGrid->getSelectedValue();
buf = instance()->debugger().equates()->getLabel(addr+kRamStart); buf = instance()->debugger().equates()->getLabel(addr+kRamStart).c_str();
if(buf) myLabel->setEditString(buf); if(*buf) myLabel->setEditString(buf);
else myLabel->setEditString(""); else myLabel->setEditString("");
myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10)); myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10));

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: TiaWidget.cxx,v 1.8 2005-07-10 02:16:01 stephena Exp $ // $Id: TiaWidget.cxx,v 1.9 2005-07-12 02:27:07 urchlay Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -201,8 +201,8 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
addr = myRamGrid->getSelectedAddr(); addr = myRamGrid->getSelectedAddr();
value = myRamGrid->getSelectedValue(); value = myRamGrid->getSelectedValue();
buf = instance()->debugger().equates()->getLabel(addr); buf = instance()->debugger().equates()->getLabel(addr).c_str();
if(buf) myLabel->setEditString(buf); if(*buf) myLabel->setEditString(buf);
else myLabel->setEditString(""); else myLabel->setEditString("");
myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10)); myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10));