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:
parent
48d4e97515
commit
437a3091e4
6 changed files with 159 additions and 77 deletions
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue