1
0
Fork 0
forked from fte/fteqw

Fix some recent bugs in fteqcc.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5740 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-08-03 10:34:44 +00:00
parent 48d4e97515
commit 437a3091e4
6 changed files with 159 additions and 77 deletions

View file

@ -1104,7 +1104,7 @@ reeval:
break;
case OP_MULSTOREP_VF:
i = OPB->_int;
errorif (QCPOINTERWRITEFAIL(i, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(i, sizeof(pvec3_t)))
{
prinst.pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, (unsigned)prinst.addressableused);
@ -1148,7 +1148,7 @@ reeval:
break;
case OP_ADDSTOREP_V:
i = OPB->_int;
errorif (QCPOINTERWRITEFAIL(i, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(i, sizeof(pvec3_t)))
{
prinst.pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, (unsigned)prinst.addressableused);
@ -1178,7 +1178,7 @@ reeval:
break;
case OP_SUBSTOREP_V:
i = OPB->_int;
errorif (QCPOINTERWRITEFAIL(i, sizeof(float)))
errorif (QCPOINTERWRITEFAIL(i, sizeof(pvec3_t)))
{
prinst.pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, (unsigned)prinst.addressableused);
@ -1256,6 +1256,15 @@ reeval:
RUNAWAYCHECK();
st += (sofs)st->b - 1; // offset the s++
break;
case OP_SWITCH_I:
//the case opcodes depend upon the preceding switch.
//otherwise the switch itself is much like a goto
//don't embed the case/caserange checks directly into the switch so that custom caseranges can be potentially be implemented with hybrid emulation.
switchcomparison = OP_SWITCH_E - OP_SWITCH_F;
switchref = OPA;
RUNAWAYCHECK();
st += (sofs)st->b - 1; // offset the s++
break;
case OP_CASE:
//if the comparison is true, jump (back up) to the relevent code block
if (casecmp[switchcomparison](progfuncs, switchref, OPA))

View file

@ -1477,7 +1477,7 @@ static struct {
{QCF_STANDARD, "quakec"},
{QCF_STANDARD, "qs"},
// {QCF_QSS, "qss"},
{QCF_QSS, "qss"},
{QCF_HEXEN2, "hexen2"},
{QCF_HEXEN2, "h2"},
@ -5648,7 +5648,7 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
if (!QCC_PR_InlinePushResult(ctx, st->b, c))
return "too many temps";
}
else
else if (OpAssignsToC(st->op))
{
//a+b->c
if (st->a.cast)
@ -5697,6 +5697,10 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
QCC_PR_SimpleStatement(&pr_opcodes[st->op], a, b, c, false);
}
}
else
{
return "nonstandard opcode form";
}
break;
}
st++;
@ -15686,6 +15690,7 @@ QCC_sref_t QCC_PR_ParseInitializerType_Internal(int arraysize, QCC_def_t *basede
else
{
//FIXME: inheritance makes stuff weird
int i;
isunion = ((type)->type == ev_union);
for (partnum = 0; partnum < (type)->num_parms; partnum++)
{
@ -15693,12 +15698,19 @@ QCC_sref_t QCC_PR_ParseInitializerType_Internal(int arraysize, QCC_def_t *basede
break;
if ((type)->params[partnum].isvirtual)
continue; //these are pre-initialised....
if ((type)->params[partnum].optional)
continue; //float parts of a vector.
// if ((type)->params[partnum].optional)
// continue; //float parts of a vector.
def.cast = (type)->params[partnum].type;
def.ofs = (type)->params[partnum].ofs;
isinited[def.ofs] = true;
if (isinited[def.ofs])
continue;
i = (type)->params[partnum].arraysize;
if (!i)
i = 1;
i *= (type)->params[partnum].type->size;
while(i --> 0)
isinited[def.ofs+i] = true;
def.ofs += offset;
ret &= QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, basedef, def, flags);

View file

@ -17,7 +17,7 @@ void QCC_FreeDef(QCC_def_t *def);
extern pbool destfile_explicit;
extern char destfile[1024];
static const QCC_sref_t nullsref = {0};
//static const QCC_sref_t nullsref = {0};
#define MAXINCLUDEDIRS 8
char qccincludedir[MAXINCLUDEDIRS][256]; //the -src path, for #includes
@ -6044,7 +6044,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
parms[numparms].defltvalue = defaultval;
numparms++;
if (type->type == ev_vector && arraysize == 0)
/*if (type->type == ev_vector && arraysize == 0)
{ //add in vec_x/y/z members too.
int c;
for (c = 0; c < 3; c++)
@ -6054,13 +6054,13 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
parms[numparms].out = false;
parms[numparms].optional = true;
parms[numparms].isvirtual = isvirt;
parms[numparms].paramname = qccHunkAlloc(strlen(pr_token)+3);
parms[numparms].paramname = qccHunkAlloc(strlen(parmname)+3);
sprintf(parms[numparms].paramname, "%s_%c", parmname, 'x'+c);
parms[numparms].type = type_float;
parms[numparms].defltvalue = nullsref;
numparms++;
}
}
}*/
}
if (!numparms)
QCC_PR_ParseError(ERR_NOTANAME, "%s %s has no members", structtype==ev_union?"union":"struct", newt->name);

View file

@ -521,6 +521,16 @@ protected:
class documentlist : public QAbstractListModel
{
public: enum endings_e
{
NONE = 0, //no endings at all yet
UNIX = 1,
MAC = 2,
MIXED = 3,
WINDOWS = 4,
};
private:
WrappedQsciScintilla *s; //this is the widget that we load our documents into
int numdocuments;
@ -531,6 +541,7 @@ class documentlist : public QAbstractListModel
time_t filemodifiedtime;
bool modified;
int cursorline;
enum endings_e endings; //line endings for this file.
int savefmt; //encoding to save as
QsciDocument doc;
QsciLexer *l;
@ -919,6 +930,60 @@ public:
}
*/ }
void SwitchToDocument_Internal(document_s *ed)
{
curdoc = ed;
s->setDocument(ed->doc);
switch(ed->endings)
{
#ifdef _WIN32
case endings_e::NONE: //new file with no endings, default to windows on windows.
#endif
case endings_e::WINDOWS: //windows
s->setEolMode(QsciScintilla::EolMode::EolWindows);
s->setEolVisibility(false);
break;
#ifndef _WIN32
case endings_e::NONE: //new file with no endings, default to unix on non-windows.
#endif
case endings_e::UNIX: //unix
s->setEolMode(QsciScintilla::EolMode::EolUnix);
s->setEolVisibility(false);
break;
case endings_e::MAC: //mac. traditionally qccs have never supported this. one of the mission packs has a \r in the middle of some single-line comment.
s->setEolMode(QsciScintilla::EolMode::EolMac);
s->setEolVisibility(false);
break;
default: //panic! everyone panic!
s->setEolMode(QsciScintilla::EolMode::EolUnix);
s->setEolVisibility(true);
break;
}
s->setUtf8(ed->savefmt != UTF_ANSI);
}
void ConvertEndings(endings_e newendings)
{
curdoc->endings = newendings;
switch(newendings)
{
case endings_e::WINDOWS: //windows
s->convertEols(QsciScintilla::EolWindows);
break;
case endings_e::UNIX: //unix
s->convertEols(QsciScintilla::EolUnix);
break;
case endings_e::MAC: //mac. traditionally qccs have never supported this. one of the mission packs has a \r in the middle of some single-line comment.
s->convertEols(QsciScintilla::EolMac);
break;
default:
break; //not real endings.
}
SwitchToDocument_Internal(curdoc);
}
bool CreateDocument(document_s *ed)
{
size_t flensz;
@ -932,7 +997,7 @@ public:
QCC_StatFile(ed->fname, &sbuf);
ed->filemodifiedtime = sbuf.st_mtime;
int endings = 0;
endings_e endings = endings_e::NONE;
char *e, *stop;
for (e = file, stop=file+flen; e < stop; )
{
@ -942,43 +1007,27 @@ public:
if (*e == '\n')
{
e++;
endings |= 4;
if (endings != endings_e::WINDOWS)
endings = endings?(endings_e::MIXED):endings_e::WINDOWS;
}
else
endings |= 2;
{
if (endings != endings_e::MAC)
endings = endings?(endings_e::MIXED):endings_e::MAC;
}
}
else if (*e == '\n')
{
e++;
endings |= 1;
if (endings != endings_e::UNIX)
endings = endings?(endings_e::MIXED):endings_e::UNIX;
}
else
e++;
}
ed->endings = endings;
curdoc = ed;
s->setDocument(ed->doc);
switch(endings)
{
case 0: //new file with no endings, default to windows on windows.
case 4: //windows
s->setEolMode(QsciScintilla::EolMode::EolWindows);
s->setEolVisibility(false);
break;
case 1: //unix
s->setEolMode(QsciScintilla::EolMode::EolUnix);
s->setEolVisibility(false);
break;
case 2: //mac. traditionally qccs have never supported this. one of the mission packs has a \r in the middle of some single-line comment.
s->setEolMode(QsciScintilla::EolMode::EolMac);
s->setEolVisibility(false);
break;
default: //panic! everyone panic!
s->setEolMode(QsciScintilla::EolMode::EolUnix);
s->setEolVisibility(true);
break;
}
SwitchToDocument_Internal(ed);
connect(s, &QsciScintillaBase::SCN_CHARADDED, [=](int charadded)
{
@ -992,7 +1041,6 @@ public:
}
});
s->setUtf8(ed->savefmt != UTF_ANSI);
s->setText(QString(file));
SetupScintilla(ed);
@ -1012,8 +1060,7 @@ public:
return;
}
curdoc = ed;
s->setDocument(ed->doc);
SwitchToDocument_Internal(ed);
}
document_s *FindFile(const char *filename)
@ -1798,15 +1845,13 @@ private:
editMenu->addAction(convertunix);
connect(convertunix, &QAction::triggered, [=]()
{
s.convertEols(QsciScintilla::EolUnix);
s.setEolVisibility(false);
docs.ConvertEndings(documentlist::endings_e::UNIX);
});
auto convertdos = new QAction(tr("Convert to DOS Endings"), this);
editMenu->addAction(convertdos);
connect(convertdos, &QAction::triggered, [=]()
{
s.convertEols(QsciScintilla::EolWindows);
s.setEolVisibility(false);
docs.ConvertEndings(documentlist::endings_e::WINDOWS);
});
//convert to utf-8 chars

View file

@ -358,7 +358,10 @@ static char *GUI_ParseInPlace(char **state)
for (end = str, fmt = str; *end; )
{
if (*end == '\"')
{
end++;
break;
}
else if (*end == '\'' && end[1] == '\\')
*fmt = '\\';
else if (*end == '\'' && end[1] == '\"')
@ -379,10 +382,21 @@ static char *GUI_ParseInPlace(char **state)
}
}
else
for (end = str; *end&&*end!=' '&&*end !='\t' && *end != '#'; end++)
;
{
for (end = str; *end; end++)
{
if (*end == '#')
{
while (*end && *end != '\n')
end++;
break;
}
if (*end==' ' || *end =='\t' || *end == '\n')
break;
}
}
*end = 0;
*state = end+1;
*state = end;
return str;
}
static int GUI_ParseIntInPlace(char **state, int defaultval)
@ -492,7 +506,7 @@ void GUI_LoadConfig(void)
fl_ftetarg = GUI_ParseBooleanInPlace(&str, false);
else if (*token)
{
puts("Unknown setting: "); puts(token); puts("\n");
puts("Unknown setting: \""); puts(token); puts("\"\n");
}
}
fclose(file);

View file

@ -1005,7 +1005,6 @@ static void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
}
}
const QCC_eval_t *QCC_SRef_EvalConst(QCC_sref_t ref);
//allocates final space for the def, making it a true def
static void QCC_FinaliseDef(QCC_def_t *def)
{
@ -1172,7 +1171,7 @@ static void QCC_FinaliseDef(QCC_def_t *def)
sr.sym = def;
sr.ofs = 0;
sr.cast = def->type;
v = QCC_SRef_EvalConst(sr);
v = &sr.sym->symboldata[sr.ofs];
if (v && def->type->type == ev_float)
externs->Printf("Finalise %s(%f) @ %i+%i\n", def->name, v->_float, def->ofs, ssize);
else if (v && def->type->type == ev_vector)
@ -1184,9 +1183,9 @@ static void QCC_FinaliseDef(QCC_def_t *def)
else if (v && def->type->type == ev_field)
externs->Printf("Finalise %s(.%i) @ %i+%i\n", def->name, v->_int, def->ofs, ssize);
else if (v && def->type->type == ev_string)
externs->Printf("Finalise %s(%s) @ %i+%i\n", def->name, strings+v->_int, def->ofs, ssize);
externs->Printf("Finalise %s(\"%s\") @ %i+%i\n", def->name, strings+v->_int, def->ofs, ssize);
else
externs->Printf("Finalise %s @ %i+%i\n", def->name, def->ofs, ssize);
externs->Printf("Finalise %s(?) @ %i+%i\n", def->name, def->ofs, ssize);
#endif
}
@ -2510,34 +2509,37 @@ strofs = (strofs+3)&~3;
progs.crc = crc;
def = QCC_PR_GetDef(NULL, "progs", NULL, false, 0, 0); //this is for qccx support
if (def && (def->type->type == ev_entity || (def->type->type == ev_accessor && def->type->parentclass->type == ev_entity)))
if (flag_qccx)
{
int size = SafeSeek (h, 0, SEEK_CUR);
size += 1; //the engine will add a null terminator
size = (size+15)&(~15); //and will allocate it on the hunk with 16-byte alignment
//this global receives the offset from world to the start of the progs def _IN VANILLA QUAKE_.
//this is a negative index due to allocation ordering with the assumption that the progs.dat was loaded on the heap directly followed by the entities.
//this will NOT work in FTE, DP, QuakeForge due to entity indexes. Various other engines will likely mess up too, if they change the allocation order or sizes etc. 64bit is screwed.
if (progs.blockscompressed&32)
externs->Printf("unable to write value for 'entity progs'\n"); //would not work anyway
else
def = QCC_PR_GetDef(NULL, "progs", NULL, false, 0, 0); //this is for qccx support
if (def && (def->type->type == ev_entity || (def->type->type == ev_accessor && def->type->parentclass->type == ev_entity)))
{
QCC_PR_Warning(WARN_DENORMAL, def->filen, def->s_line, "'entity progs' is non-portable and will not work across engines nor cpus.");
int size = SafeSeek (h, 0, SEEK_CUR);
size += 1; //the engine will add a null terminator
size = (size+15)&(~15); //and will allocate it on the hunk with 16-byte alignment
if (def->initialized)
i = PRLittleLong(qcc_pr_globals[def->ofs]._int);
//this global receives the offset from world to the start of the progs def _IN VANILLA QUAKE_.
//this is a negative index due to allocation ordering with the assumption that the progs.dat was loaded on the heap directly followed by the entities.
//this will NOT work in FTE, DP, QuakeForge due to entity indexes. Various other engines will likely mess up too, if they change the allocation order or sizes etc. 64bit is screwed.
if (progs.blockscompressed&32)
externs->Printf("unable to write value for 'entity progs'\n"); //would not work anyway
else
{ //entsize(=96)+hunk header size(=32)
if (verbose)
externs->Printf("qccx hack - 'entity progs' uninitialised. Assuming 112.\n");
i = 112; //match qccx.
{
QCC_PR_Warning(WARN_DENORMAL, def->filen, def->s_line, "'entity progs' is non-portable and will not work across engines nor cpus.");
if (def->initialized)
i = PRLittleLong(qcc_pr_globals[def->ofs]._int);
else
{ //entsize(=96)+hunk header size(=32)
if (verbose)
externs->Printf("qccx hack - 'entity progs' uninitialised. Assuming 112.\n");
i = 112; //match qccx.
}
i = -(size + i);
i = PRLittleLong(i);
SafeSeek (h, progs.ofs_globals + 4 * def->ofs, SEEK_SET);
SafeWrite (h, &i, 4);
}
i = -(size + i);
i = PRLittleLong(i);
SafeSeek (h, progs.ofs_globals + 4 * def->ofs, SEEK_SET);
SafeWrite (h, &i, 4);
}
}