Fixes to variable list in CBot debugger
* fixed stack overflow with circular references (closes #434) * fixed displaying boolean variables * fixed buffer overflows with entries longer than 100 characters * removed hard-limit to 100 entries with at most 100 characters in CList (this also allows you to have more than 100 programs in a robot, up to 999)dev-time-step
parent
4479a196f9
commit
fef8a8e355
|
@ -490,79 +490,71 @@ bool CScript::GetCursor(int &cursor1, int &cursor2)
|
|||
|
||||
// Put of the variables in a list.
|
||||
|
||||
void PutList(const char *baseName, bool bArray, CBot::CBotVar *var, Ui::CList *list, int &rankList)
|
||||
void PutList(const std::string& baseName, bool bArray, CBot::CBotVar *var, Ui::CList *list, int &rankList, std::set<CBot::CBotVar*>& previous)
|
||||
{
|
||||
CBot::CBotVar *svar, *pStatic;
|
||||
char varName[100];
|
||||
char buffer[100];
|
||||
std::string p;
|
||||
int index, type;
|
||||
|
||||
if ( var == nullptr && baseName[0] != 0 )
|
||||
if ( var == nullptr && !baseName.empty() )
|
||||
{
|
||||
sprintf(buffer, "%s = null;", baseName);
|
||||
list->SetItemName(rankList++, buffer);
|
||||
list->SetItemName(rankList++, StrUtils::Format("%s = null;", baseName.c_str()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while ( var != nullptr )
|
||||
int index = 0;
|
||||
while (var != nullptr)
|
||||
{
|
||||
var->Update(nullptr);
|
||||
pStatic = var->GetStaticVar(); // finds the static element
|
||||
CBot::CBotVar* pStatic = var->GetStaticVar(); // finds the static element
|
||||
|
||||
p = pStatic->GetName(); // variable name
|
||||
//? if ( strcmp(p, "this") == 0 )
|
||||
//? {
|
||||
//? var = var->GetNext();
|
||||
//? continue;
|
||||
//? }
|
||||
|
||||
if ( baseName[0] == 0 )
|
||||
std::string varName;
|
||||
if (baseName.empty())
|
||||
{
|
||||
sprintf(varName, "%s", p.c_str());
|
||||
varName = StrUtils::Format("%s", pStatic->GetName().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bArray )
|
||||
if (bArray)
|
||||
{
|
||||
sprintf(varName, "%s[%d]", baseName, index);
|
||||
varName = StrUtils::Format("%s[%d]", baseName.c_str(), index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(varName, "%s.%s", baseName, p.c_str());
|
||||
varName = StrUtils::Format("%s.%s", baseName.c_str(), pStatic->GetName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
type = pStatic->GetType();
|
||||
|
||||
if ( type < CBot::CBotTypBoolean )
|
||||
if (previous.find(pStatic) != previous.end())
|
||||
{
|
||||
p = pStatic->GetValString();
|
||||
sprintf(buffer, "%s = %s;", varName, p.c_str());
|
||||
list->SetItemName(rankList++, buffer);
|
||||
}
|
||||
else if ( type == CBot::CBotTypString )
|
||||
{
|
||||
p = pStatic->GetValString();
|
||||
sprintf(buffer, "%s = \"%s\";", varName, p.c_str());
|
||||
list->SetItemName(rankList++, buffer);
|
||||
}
|
||||
else if ( type == CBot::CBotTypArrayPointer )
|
||||
{
|
||||
svar = pStatic->GetItemList();
|
||||
PutList(varName, true, svar, list, rankList);
|
||||
}
|
||||
else if ( type == CBot::CBotTypClass ||
|
||||
type == CBot::CBotTypPointer )
|
||||
{
|
||||
svar = pStatic->GetItemList();
|
||||
PutList(varName, false, svar, list, rankList);
|
||||
list->SetItemName(rankList++, StrUtils::Format("%s = [circular reference]", varName.c_str()).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "%s = ?;", varName);
|
||||
list->SetItemName(rankList++, buffer);
|
||||
int type = pStatic->GetType();
|
||||
|
||||
if (type <= CBot::CBotTypBoolean)
|
||||
{
|
||||
list->SetItemName(rankList++, StrUtils::Format("%s = %s;", varName.c_str(), pStatic->GetValString().c_str()).c_str());
|
||||
}
|
||||
else if (type == CBot::CBotTypString)
|
||||
{
|
||||
list->SetItemName(rankList++, StrUtils::Format("%s = \"%s\";", varName.c_str(), pStatic->GetValString().c_str()).c_str());
|
||||
}
|
||||
else if (type == CBot::CBotTypArrayPointer)
|
||||
{
|
||||
previous.insert(pStatic);
|
||||
PutList(varName, true, pStatic->GetItemList(), list, rankList, previous);
|
||||
previous.erase(pStatic);
|
||||
}
|
||||
else if (type == CBot::CBotTypClass ||
|
||||
type == CBot::CBotTypPointer)
|
||||
{
|
||||
previous.insert(pStatic);
|
||||
PutList(varName, false, pStatic->GetItemList(), list, rankList, previous);
|
||||
previous.erase(pStatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
//list->SetItemName(rankList++, StrUtils::Format("%s = ?;", varName.c_str()).c_str());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
index ++;
|
||||
|
@ -589,13 +581,15 @@ void CScript::UpdateList(Ui::CList* list)
|
|||
|
||||
level = 0;
|
||||
rank = 0;
|
||||
std::set<CBot::CBotVar*> previous;
|
||||
while ( true )
|
||||
{
|
||||
var = m_botProg->GetStackVars(funcName, level--);
|
||||
if ( funcName != progName ) break;
|
||||
|
||||
PutList("", false, var, list, rank);
|
||||
PutList("", false, var, list, rank, previous);
|
||||
}
|
||||
assert(previous.empty());
|
||||
|
||||
if ( total == list->GetTotal() ) // same total?
|
||||
{
|
||||
|
|
|
@ -354,7 +354,7 @@ void CList::Draw()
|
|||
float dp;
|
||||
int i;
|
||||
char text[100];
|
||||
char *pb, *pe;
|
||||
const char *pb, *pe;
|
||||
|
||||
if ((m_state & STATE_VISIBLE) == 0)
|
||||
return;
|
||||
|
@ -451,14 +451,14 @@ void CList::Draw()
|
|||
ppos.y = pos.y + dim.y * 0.5f;
|
||||
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
|
||||
ddim.x = dim.x-dim.y;
|
||||
DrawCase(m_items[i + m_firstLine].text, ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
|
||||
DrawCase(m_items[i + m_firstLine].text.c_str(), ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppos.x = pos.x + dim.y * 0.5f;
|
||||
ppos.y = pos.y + dim.y * 0.5f;
|
||||
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
|
||||
pb = m_items[i + m_firstLine].text;
|
||||
pb = m_items[i + m_firstLine].text.c_str();
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
pe = strchr(pb, '\t');
|
||||
|
@ -548,7 +548,7 @@ void CList::Draw()
|
|||
|
||||
// Displays text in a box.
|
||||
|
||||
void CList::DrawCase(char *text, Math::Point pos, float width, Gfx::TextAlign justif)
|
||||
void CList::DrawCase(const char* text, Math::Point pos, float width, Gfx::TextAlign justif)
|
||||
{
|
||||
if (justif == Gfx::TEXT_ALIGN_CENTER)
|
||||
pos.x += width / 2.0f;
|
||||
|
@ -651,18 +651,19 @@ bool CList::GetBlink()
|
|||
|
||||
// Specifies the text of a line.
|
||||
|
||||
void CList::SetItemName(int i, const char* name)
|
||||
void CList::SetItemName(int i, const std::string& name)
|
||||
{
|
||||
if ( i < 0 || i >= LISTMAXTOTAL )
|
||||
if ( i < 0 )
|
||||
return;
|
||||
|
||||
if ( i >= m_totalLine )
|
||||
m_totalLine = i+1; // expands the list
|
||||
|
||||
if ( name[0] == 0 )
|
||||
strcpy(m_items[i].text, " ");
|
||||
m_items.resize(m_totalLine);
|
||||
if ( name.empty() )
|
||||
m_items[i].text = " ";
|
||||
else
|
||||
strcpy(m_items[i].text, name);
|
||||
m_items[i].text = name;
|
||||
|
||||
UpdateButton();
|
||||
UpdateScroll();
|
||||
|
@ -670,10 +671,10 @@ void CList::SetItemName(int i, const char* name)
|
|||
|
||||
// Returns the text of a line.
|
||||
|
||||
char* CList::GetItemName(int i)
|
||||
const std::string& CList::GetItemName(int i)
|
||||
{
|
||||
if ( i < 0 || i >= m_totalLine )
|
||||
return nullptr;
|
||||
assert(false);
|
||||
|
||||
return m_items[i].text;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace Ui
|
|||
{
|
||||
|
||||
const int LISTMAXDISPLAY = 20; // maximum number of visible lines
|
||||
const int LISTMAXTOTAL = 100; // maximum total number of lines
|
||||
|
||||
|
||||
|
||||
|
@ -71,8 +70,8 @@ public:
|
|||
void SetBlink(bool bEnable);
|
||||
bool GetBlink();
|
||||
|
||||
void SetItemName(int i, const char* name);
|
||||
char* GetItemName(int i);
|
||||
void SetItemName(int i, const std::string& name);
|
||||
const std::string& GetItemName(int i);
|
||||
|
||||
void SetCheck(int i, bool bMode);
|
||||
bool GetCheck(int i);
|
||||
|
@ -93,7 +92,7 @@ protected:
|
|||
void UpdateButton();
|
||||
void UpdateScroll();
|
||||
void MoveScroll();
|
||||
void DrawCase(char *text, Math::Point pos, float width, Gfx::TextAlign justif);
|
||||
void DrawCase(const char* text, Math::Point pos, float width, Gfx::TextAlign justif);
|
||||
|
||||
private:
|
||||
// Overridden to avoid warning about hiding the virtual function
|
||||
|
@ -116,11 +115,11 @@ protected:
|
|||
|
||||
struct Item
|
||||
{
|
||||
char text[100] = {};
|
||||
std::string text = "";
|
||||
bool check = false;
|
||||
bool enable = true;
|
||||
};
|
||||
std::array<Item, LISTMAXTOTAL> m_items;
|
||||
std::vector<Item> m_items;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ bool CScreenPlayerSelect::EventProcess(const Event &event)
|
|||
CWindow* pw;
|
||||
CList* pl;
|
||||
std::string name;
|
||||
char* gamer;
|
||||
std::string gamer;
|
||||
|
||||
switch( event.type )
|
||||
{
|
||||
|
@ -289,7 +289,7 @@ void CScreenPlayerSelect::UpdateNameList()
|
|||
for ( i=0 ; i<total ; i++ )
|
||||
{
|
||||
// TODO: stricmp?
|
||||
if ( strcmp(name, pl->GetItemName(i)) == 0 )
|
||||
if ( name == pl->GetItemName(i) )
|
||||
{
|
||||
pl->SetSelect(i);
|
||||
pl->ShowSelect(false);
|
||||
|
@ -307,7 +307,7 @@ void CScreenPlayerSelect::UpdateNameEdit()
|
|||
CWindow* pw;
|
||||
CList* pl;
|
||||
CEdit* pe;
|
||||
char* name;
|
||||
std::string name;
|
||||
int sel;
|
||||
|
||||
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
|
||||
|
@ -326,8 +326,8 @@ void CScreenPlayerSelect::UpdateNameEdit()
|
|||
else
|
||||
{
|
||||
name = pl->GetItemName(sel);
|
||||
pe->SetText(name);
|
||||
pe->SetCursor(strlen(name), 0);
|
||||
pe->SetText(name.c_str());
|
||||
pe->SetCursor(name.length(), 0);
|
||||
}
|
||||
|
||||
UpdateNameControl();
|
||||
|
@ -434,7 +434,7 @@ void CScreenPlayerSelect::NameDelete()
|
|||
return;
|
||||
}
|
||||
|
||||
char* gamer = pl->GetItemName(sel);
|
||||
std::string gamer = pl->GetItemName(sel);
|
||||
|
||||
m_main->SelectPlayer(gamer);
|
||||
if (!m_main->GetPlayerProfile()->Delete())
|
||||
|
|
Loading…
Reference in New Issue