Fix qcc bug with removed continues/breaks editing other statements after removal.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5429 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-03-05 14:39:47 +00:00
parent b9fd3c01be
commit d6d8d4c695
2 changed files with 100 additions and 7 deletions

View file

@ -4269,6 +4269,70 @@ QCC_statement_t *QCC_PR_SimpleStatement ( QCC_opcode_t *op, QCC_sref_t var_a, QC
return statement;
}
/*
Removes trailing statements, rewinding back to a known-safe position.
*/
void QCC_UngenerateStatements(int newstatementcount)
{
int i;
//forget any indexes to statements if those statements are going to go away...
for (i = 0; i < num_gotos; )
{
if (pr_gotos[i].statementno >= newstatementcount)
{
memmove(&pr_gotos[i], &pr_gotos[i+1], sizeof(*pr_gotos)*(num_gotos-(i+1)));
num_gotos--;
}
else
i++;
}
for (i = 0; i < num_labels; )
{ //FIXME: stripping a label? erk?
if (pr_labels[i].statementno >= newstatementcount)
{
memmove(&pr_labels[i], &pr_labels[i+1], sizeof(*pr_labels)*(num_labels-(i+1)));
num_labels--;
}
else
i++;
}
for (i = 0; i < num_breaks; )
{
if (pr_breaks[i] >= newstatementcount)
{
memmove(&pr_breaks[i], &pr_breaks[i+1], sizeof(*pr_breaks)*(num_breaks-(i+1)));
num_breaks--;
}
else
i++;
}
for (i = 0; i < num_continues; )
{
if (pr_continues[i] >= newstatementcount)
{
memmove(&pr_continues[i], &pr_continues[i+1], sizeof(*pr_continues)*(num_continues-(i+1)));
num_continues--;
}
else
i++;
}
for (i = 0; i < num_cases; )
{
if (pr_cases[i] >= newstatementcount)
{
memmove(&pr_cases[i], &pr_cases[i+1], sizeof(*pr_cases)*(num_cases-(i+1)));
memmove(&pr_casesref[i], &pr_casesref[i+1], sizeof(*pr_casesref)*(num_cases-(i+1)));
memmove(&pr_casesref2[i], &pr_casesref2[i+1], sizeof(*pr_casesref2)*(num_cases-(i+1)));
num_cases--;
}
else
i++;
}
numstatements = newstatementcount;
}
/*
============
PR_ParseImmediate
@ -5363,7 +5427,7 @@ static QCC_sref_t QCC_PR_Inline(QCC_sref_t fdef, QCC_ref_t **arglist, unsigned i
}
if (!ctx.result.cast)
numstatements = statements; //on failure, remove the extra statements
QCC_UngenerateStatements(statements);
else
{ //on success, make sure the args were freed
while (argcount-->0)
@ -11071,7 +11135,7 @@ void QCC_PR_ParseStatement (void)
QCC_PR_ParseStatement ();
if (striptruth && oldlab == num_labels)
{
numstatements = oldnumst;
QCC_UngenerateStatements(oldnumst);
patch1 = NULL;
}
else
@ -11096,7 +11160,7 @@ void QCC_PR_ParseStatement (void)
if (stripfalse && oldlab == num_labels)
{
patch2 = NULL;
numstatements = oldnumst;
QCC_UngenerateStatements(oldnumst);
if (patch1)
patch1->b.ofs = &statements[numstatements] - patch1;
@ -11118,7 +11182,7 @@ void QCC_PR_ParseStatement (void)
if (stripfalse && oldlab == num_labels)
{
patch2 = NULL;
numstatements = oldnumst;
QCC_UngenerateStatements(oldnumst);
if (patch1)
patch1->b.ofs = &statements[numstatements] - patch1;
@ -13231,7 +13295,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
{ //FIXME: should probably always take this path, but kinda pointless until we have relocs for defs
QCC_RemapLockedTemps(f->code, numstatements);
QCC_Marshal_Locals(f->code, numstatements);
QCC_WriteAsmFunction(f, f->code, f->firstlocal); //FIXME: this will print the entire function, not just the part that we added. and we'll print it all again later, too. should probably make it a function attribute that we check at the end.
// QCC_WriteAsmFunction(f, f->code, f->firstlocal); //FIXME: this will print the entire function, not just the part that we added. and we'll print it all again later, too. should probably make it a function attribute that we check at the end.
f->numstatements = numstatements - f->code;
f->statements = qccHunkAlloc(sizeof(*statements)*f->numstatements);

View file

@ -395,6 +395,7 @@ public:
if (c)
return; //already in there.
beginResetModel();
c = new filenode_s();
c->name = strdup(filename);
c->parent = p;
@ -402,6 +403,7 @@ public:
p->children = cpprealloc(p->children, sizeof(*p->children)*(p->numchildren+1));
p->children[p->numchildren] = c;
p->numchildren++;
endResetModel();
}
};
@ -925,6 +927,29 @@ public:
return ret;
}
bool annotate(const char *line)
{
auto filename = line+6;
auto filenameend = strchr(filename, ':');
if (!filenameend) return false;
auto linenum = atoi(filenameend+1);
line = strchr(filenameend+1, ':')+1;
if (!line) return false;
if (strncmp(curdoc->fname, filename, filenameend-filename) || curdoc->fname[filenameend-filename])
{
auto d = FindFile(filename);
if (d)
{
curdoc = d;
s->setDocument(d->doc);
}
else
return false; //some other file that we're not interested in
}
s->annotate(linenum-1, s->annotation(linenum) + line + "\n", 0);
return true;
}
bool saveDocument(document_s *d)
{
@ -1848,7 +1873,12 @@ int GUIprintf(const char *msg, ...)
QString s = l.mid(0, idx);
l = l.mid(idx+1);
if (s.contains(": error") || s.contains(": werror") || !s.mid(0,5).compare("error", Qt::CaseInsensitive))
if (!s.mid(0, 6).compare("code: "))
{
mainwnd->docs.annotate(s.toUtf8().data());
continue;
}
else if (s.contains(": error") || s.contains(": werror") || !s.mid(0,5).compare("error", Qt::CaseInsensitive))
mainwnd->log.setTextColor(QColor(255, 0, 0));
else if (s.contains(": warning"))
mainwnd->log.setTextColor(QColor(128, 128, 0));
@ -1892,7 +1922,6 @@ void documentlist::EditFile(document_s *c, const char *filename, int linenum, bo
if (!CreateDocument(c))
{
delete(c);
numdocuments--;
return;
}