mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-23 04:11:53 +00:00
I feel that '#pragma warning disable Q302' will shortly be overused...
Added -Kno-ifstring parameter to break correction of if(string) to testing for null instead of empty string. Added a couple of fixes for stacked function calls. The reference and dereference (& and *) operators are now working with -Tfte! Woot. Function calls to functions taking integer arguments with a floating point parameter have been tweeked to supply an implicit conversion rather than erroring all of a sudden. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@407 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
ed24206d93
commit
7e7582b734
6 changed files with 351 additions and 68 deletions
|
@ -461,6 +461,7 @@ extern pbool keyword_class;
|
||||||
extern pbool keywords_coexist;
|
extern pbool keywords_coexist;
|
||||||
extern pbool output_parms;
|
extern pbool output_parms;
|
||||||
extern pbool autoprototype;
|
extern pbool autoprototype;
|
||||||
|
extern pbool flag_ifstring;
|
||||||
|
|
||||||
extern pbool opt_overlaptemps;
|
extern pbool opt_overlaptemps;
|
||||||
extern pbool opt_shortenifnots;
|
extern pbool opt_shortenifnots;
|
||||||
|
@ -574,6 +575,7 @@ enum {
|
||||||
WARN_DUPLICATEPRECOMPILER,
|
WARN_DUPLICATEPRECOMPILER,
|
||||||
WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about.
|
WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about.
|
||||||
WARN_EXTENSION_USED, //extension that frikqcc also understands
|
WARN_EXTENSION_USED, //extension that frikqcc also understands
|
||||||
|
WARN_IFSTRING_USED,
|
||||||
|
|
||||||
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
|
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,115 @@ skipwhite:
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//more C tokens...
|
||||||
|
char *QCC_COM_Parse2 (char *data)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
qcc_token[0] = 0;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// skip whitespace
|
||||||
|
skipwhite:
|
||||||
|
while ( (c = *data) <= ' ')
|
||||||
|
{
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
qcc_eof = true;
|
||||||
|
return NULL; // end of file;
|
||||||
|
}
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip // comments
|
||||||
|
if (c=='/' && data[1] == '/')
|
||||||
|
{
|
||||||
|
while (*data && *data != '\n')
|
||||||
|
data++;
|
||||||
|
goto skipwhite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// handle quoted strings specially
|
||||||
|
if (c == '\"')
|
||||||
|
{
|
||||||
|
data++;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *data++;
|
||||||
|
if (c=='\"'||c=='\0')
|
||||||
|
{
|
||||||
|
qcc_token[len] = 0;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
qcc_token[len] = c;
|
||||||
|
len++;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse numbers
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
if (c == '0' && data[1] == 'x')
|
||||||
|
{ //parse hex
|
||||||
|
qcc_token[0] = '0';
|
||||||
|
c='x';
|
||||||
|
len=1;
|
||||||
|
data++;
|
||||||
|
for(;;)
|
||||||
|
{ //parse regular number
|
||||||
|
qcc_token[len] = c;
|
||||||
|
data++;
|
||||||
|
len++;
|
||||||
|
c = *data;
|
||||||
|
if ((c<'0'|| c>'9') && (c<'a'||c>'f') && (c<'A'||c>'F') && c != '.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{ //parse regular number
|
||||||
|
qcc_token[len] = c;
|
||||||
|
data++;
|
||||||
|
len++;
|
||||||
|
c = *data;
|
||||||
|
if ((c<'0'|| c>'9') && c != '.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qcc_token[len] = 0;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// parse words
|
||||||
|
else if ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_')
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
qcc_token[len] = c;
|
||||||
|
data++;
|
||||||
|
len++;
|
||||||
|
c = *data;
|
||||||
|
} while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_');
|
||||||
|
|
||||||
|
qcc_token[len] = 0;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qcc_token[len] = c;
|
||||||
|
len++;
|
||||||
|
qcc_token[len] = 0;
|
||||||
|
return data+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *VARGS qcva (char *text, ...)
|
char *VARGS qcva (char *text, ...)
|
||||||
{
|
{
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
|
|
|
@ -37,6 +37,7 @@ pbool keywords_coexist; //don't disable a keyword simply because a var was made
|
||||||
pbool output_parms; //emit some PARMX fields. confuses decompilers.
|
pbool output_parms; //emit some PARMX fields. confuses decompilers.
|
||||||
pbool autoprototype; //take two passes over the source code. First time round doesn't enter and functions or initialise variables.
|
pbool autoprototype; //take two passes over the source code. First time round doesn't enter and functions or initialise variables.
|
||||||
pbool pr_subscopedlocals; //causes locals to be valid ONLY within thier statement block. (they simply can't be referenced by name outside of it)
|
pbool pr_subscopedlocals; //causes locals to be valid ONLY within thier statement block. (they simply can't be referenced by name outside of it)
|
||||||
|
pbool flag_ifstring;
|
||||||
|
|
||||||
pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
|
pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
|
||||||
pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp.
|
pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp.
|
||||||
|
@ -969,7 +970,6 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement
|
||||||
{
|
{
|
||||||
#ifdef WRITEASM
|
#ifdef WRITEASM
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
int locks=0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QCC_def_t *def;
|
QCC_def_t *def;
|
||||||
|
@ -991,7 +991,7 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement
|
||||||
def->nextlocal = pr.localvars;
|
def->nextlocal = pr.localvars;
|
||||||
def->constant = false;
|
def->constant = false;
|
||||||
#ifdef WRITEASM
|
#ifdef WRITEASM
|
||||||
sprintf(buffer, "locked_%i", ++locks);
|
sprintf(buffer, "locked_%i", t->ofs);
|
||||||
def->name = qccHunkAlloc(strlen(buffer)+1);
|
def->name = qccHunkAlloc(strlen(buffer)+1);
|
||||||
strcpy(def->name, buffer);
|
strcpy(def->name, buffer);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1010,7 +1010,7 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement
|
||||||
def->nextlocal = pr.localvars;
|
def->nextlocal = pr.localvars;
|
||||||
def->constant = false;
|
def->constant = false;
|
||||||
#ifdef WRITEASM
|
#ifdef WRITEASM
|
||||||
sprintf(buffer, "locked_%i", ++locks);
|
sprintf(buffer, "locked_%i", t->ofs);
|
||||||
def->name = qccHunkAlloc(strlen(buffer)+1);
|
def->name = qccHunkAlloc(strlen(buffer)+1);
|
||||||
strcpy(def->name, buffer);
|
strcpy(def->name, buffer);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1029,7 +1029,7 @@ static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement
|
||||||
def->nextlocal = pr.localvars;
|
def->nextlocal = pr.localvars;
|
||||||
def->constant = false;
|
def->constant = false;
|
||||||
#ifdef WRITEASM
|
#ifdef WRITEASM
|
||||||
sprintf(buffer, "locked_%i", ++locks);
|
sprintf(buffer, "locked_%i", t->ofs);
|
||||||
def->name = qccHunkAlloc(strlen(buffer)+1);
|
def->name = qccHunkAlloc(strlen(buffer)+1);
|
||||||
strcpy(def->name, buffer);
|
strcpy(def->name, buffer);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1311,10 +1311,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var
|
||||||
if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs)
|
if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs)
|
||||||
QCC_PR_ParseWarning(0, "Result of comparison is constant");
|
QCC_PR_ParseWarning(0, "Result of comparison is constant");
|
||||||
break;
|
break;
|
||||||
case OP_IF:
|
|
||||||
case OP_IFNOT:
|
|
||||||
case OP_IFS:
|
case OP_IFS:
|
||||||
case OP_IFNOTS:
|
case OP_IFNOTS:
|
||||||
|
case OP_IF:
|
||||||
|
case OP_IFNOT:
|
||||||
// if (var_a->type->type == ev_function && !var_a->temp)
|
// if (var_a->type->type == ev_function && !var_a->temp)
|
||||||
// QCC_PR_ParseWarning(0, "Result of comparison is constant");
|
// QCC_PR_ParseWarning(0, "Result of comparison is constant");
|
||||||
if (var_a->constant && !var_a->temp)
|
if (var_a->constant && !var_a->temp)
|
||||||
|
@ -2054,7 +2054,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
|
||||||
if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
|
if (QCC_OPCodeValid(&pr_opcodes[OP_CALL1H]))
|
||||||
callconvention = OP_CALL1H; //FTE extended
|
callconvention = OP_CALL1H; //FTE extended
|
||||||
else
|
else
|
||||||
callconvention = OP_CALL1; //FTE extended
|
callconvention = OP_CALL1; //standard
|
||||||
|
|
||||||
t = func->type;
|
t = func->type;
|
||||||
|
|
||||||
|
@ -2513,7 +2513,12 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
|
||||||
if (e->type->type != ev_function && p->type != ev_integer)
|
if (e->type->type != ev_function && p->type != ev_integer)
|
||||||
if ( e->type->type != p->type )*/
|
if ( e->type->type != p->type )*/
|
||||||
{
|
{
|
||||||
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
|
if (p->type == ev_integer && e->type->type == ev_float) //convert float -> int... is this a constant?
|
||||||
|
e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
|
||||||
|
else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant?
|
||||||
|
e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
|
||||||
|
else
|
||||||
|
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
d->type = p;
|
d->type = p;
|
||||||
|
@ -2583,6 +2588,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL));
|
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL));
|
||||||
QCC_UnFreeTemp(old);
|
QCC_UnFreeTemp(old);
|
||||||
|
QCC_UnFreeTemp(&def_ret);
|
||||||
QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
|
QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2674,6 +2680,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
|
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, old, &def_ret, NULL));
|
||||||
QCC_FreeTemp(old);
|
QCC_FreeTemp(old);
|
||||||
|
QCC_UnFreeTemp(&def_ret);
|
||||||
|
QCC_UnFreeTemp(d);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
@ -3706,7 +3714,8 @@ QCC_def_t *QCC_PR_Term (void)
|
||||||
{
|
{
|
||||||
if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
|
if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P)
|
||||||
{
|
{
|
||||||
// QCC_PR_ParseWarning(0, "debug: &ent.field");
|
statements[numstatements-1].op = OP_ADDRESS;
|
||||||
|
QCC_PR_ParseWarning(0, "debug: &ent.field");
|
||||||
e->type = QCC_PR_PointerType(e->type);
|
e->type = QCC_PR_PointerType(e->type);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -3718,10 +3727,54 @@ QCC_def_t *QCC_PR_Term (void)
|
||||||
}
|
}
|
||||||
// QCC_PR_ParseWarning(0, "debug: &global");
|
// QCC_PR_ParseWarning(0, "debug: &global");
|
||||||
|
|
||||||
|
if (!QCC_OPCodeValid(&pr_opcodes[OP_GLOBALADDRESS]))
|
||||||
|
QCC_PR_ParseError (ERR_BADEXTENSION, "Cannot use addressof operator ('&') on a global. Please use the FTE target.");
|
||||||
|
|
||||||
e2 = QCC_PR_Statement (&pr_opcodes[OP_GLOBALADDRESS], e, 0, NULL);
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_GLOBALADDRESS], e, 0, NULL);
|
||||||
e2->type = QCC_PR_PointerType(e->type);
|
e2->type = QCC_PR_PointerType(e->type);
|
||||||
return e2;
|
return e2;
|
||||||
}
|
}
|
||||||
|
else if (QCC_PR_Check ("*"))
|
||||||
|
{
|
||||||
|
int st = numstatements;
|
||||||
|
e = QCC_PR_Expression (NOT_PRIORITY);
|
||||||
|
t = e->type->type;
|
||||||
|
|
||||||
|
switch(e->type->aux_type->type)
|
||||||
|
{
|
||||||
|
case ev_float:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_string:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_vector:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_entity:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_field:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_function:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_integer:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ev_pointer:
|
||||||
|
e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
e2->type = e->type->aux_type;
|
||||||
|
return e2;
|
||||||
|
}
|
||||||
|
|
||||||
if (QCC_PR_Check ("("))
|
if (QCC_PR_Check ("("))
|
||||||
{
|
{
|
||||||
|
@ -4205,6 +4258,20 @@ QCC_def_t *QCC_PR_Expression (int priority)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname)
|
||||||
|
{
|
||||||
|
if (num_gotos >= max_gotos)
|
||||||
|
{
|
||||||
|
max_gotos += 8;
|
||||||
|
pr_gotos = realloc(pr_gotos, sizeof(*pr_gotos)*max_gotos);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(pr_gotos[num_gotos].name, labelname, sizeof(pr_gotos[num_gotos].name) -1);
|
||||||
|
pr_gotos[num_gotos].lineno = pr_source_line;
|
||||||
|
pr_gotos[num_gotos].statementno = patch2 - statements;
|
||||||
|
|
||||||
|
num_gotos++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
|
@ -4296,6 +4363,11 @@ void QCC_PR_ParseStatement (void)
|
||||||
else
|
else
|
||||||
patch1 = NULL;
|
patch1 = NULL;
|
||||||
}
|
}
|
||||||
|
else if (e->type == type_string) //special case, as strings are now pointers, not offsets from string table
|
||||||
|
{
|
||||||
|
QCC_PR_ParseWarning(0, "while (string) can result in bizzare behaviour");
|
||||||
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOTS], e, 0, &patch1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
|
||||||
}
|
}
|
||||||
|
@ -4438,8 +4510,11 @@ void QCC_PR_ParseStatement (void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e->type == type_string)
|
if (e->type == type_string && flag_ifstring)
|
||||||
|
{
|
||||||
|
QCC_PR_ParseWarning(WARN_IFSTRING_USED, "do {} while(string) can result in bizzare behaviour");
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFS], e, &junkdef, (QCC_dstatement_t **)0xffffffff));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFS], e, &junkdef, (QCC_dstatement_t **)0xffffffff));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, &junkdef, (QCC_dstatement_t **)0xffffffff));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, &junkdef, (QCC_dstatement_t **)0xffffffff));
|
||||||
}
|
}
|
||||||
|
@ -4513,8 +4588,11 @@ void QCC_PR_ParseStatement (void)
|
||||||
e = QCC_PR_Expression (TOP_PRIORITY);
|
e = QCC_PR_Expression (TOP_PRIORITY);
|
||||||
conditional = false;
|
conditional = false;
|
||||||
|
|
||||||
if (e->type == type_string) //special case, as strings are now pointers, not offsets from string table
|
if (e->type == type_string && flag_ifstring) //special case, as strings are now pointers, not offsets from string table
|
||||||
|
{
|
||||||
|
QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if not(string) can result in bizzare behaviour");
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFS], e, 0, &patch1));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFS], e, 0, &patch1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, 0, &patch1));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, 0, &patch1));
|
||||||
}
|
}
|
||||||
|
@ -4525,8 +4603,11 @@ void QCC_PR_ParseStatement (void)
|
||||||
e = QCC_PR_Expression (TOP_PRIORITY);
|
e = QCC_PR_Expression (TOP_PRIORITY);
|
||||||
conditional = false;
|
conditional = false;
|
||||||
|
|
||||||
if (e->type == type_string) //special case, as strings are now pointers, not offsets from string table
|
if (e->type == type_string && flag_ifstring) //special case, as strings are now pointers, not offsets from string table
|
||||||
|
{
|
||||||
|
QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) can result in bizzare behaviour");
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOTS], e, 0, &patch1));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOTS], e, 0, &patch1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
|
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
|
||||||
}
|
}
|
||||||
|
@ -4823,19 +4904,9 @@ void QCC_PR_ParseStatement (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_gotos >= max_gotos)
|
|
||||||
{
|
|
||||||
max_gotos += 8;
|
|
||||||
pr_gotos = realloc(pr_gotos, sizeof(*pr_gotos)*max_gotos);
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(pr_gotos[num_gotos].name, pr_token, sizeof(pr_gotos[num_gotos].name) -1);
|
|
||||||
pr_gotos[num_gotos].lineno = pr_source_line;
|
|
||||||
QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2);
|
QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2);
|
||||||
pr_gotos[num_gotos].statementno = patch2 - statements;
|
|
||||||
|
|
||||||
|
QCC_PR_GotoStatement (patch2, pr_token);
|
||||||
num_gotos++;
|
|
||||||
|
|
||||||
// QCC_PR_ParseWarning("Gotos are evil");
|
// QCC_PR_ParseWarning("Gotos are evil");
|
||||||
QCC_PR_Lex();
|
QCC_PR_Lex();
|
||||||
|
@ -5078,7 +5149,7 @@ void QCC_PR_ParseState (void)
|
||||||
|
|
||||||
void QCC_PR_ParseAsm(void)
|
void QCC_PR_ParseAsm(void)
|
||||||
{
|
{
|
||||||
QCC_dstatement_t *patch1;
|
QCC_dstatement_t *patch1;
|
||||||
int op, p;
|
int op, p;
|
||||||
QCC_def_t *a, *b, *c;
|
QCC_def_t *a, *b, *c;
|
||||||
|
|
||||||
|
@ -5098,34 +5169,60 @@ QCC_dstatement_t *patch1;
|
||||||
{
|
{
|
||||||
if (pr_opcodes[op].type_a==NULL)
|
if (pr_opcodes[op].type_a==NULL)
|
||||||
{
|
{
|
||||||
p = (int)pr_immediate._float;
|
|
||||||
QCC_PR_Lex();
|
|
||||||
patch1 = &statements[numstatements];
|
patch1 = &statements[numstatements];
|
||||||
|
|
||||||
QCC_PR_Statement3(&pr_opcodes[op], NULL, NULL, NULL);
|
QCC_PR_Statement3(&pr_opcodes[op], NULL, NULL, NULL);
|
||||||
patch1->a = (int)p;
|
|
||||||
|
if (pr_token_type == tt_name)
|
||||||
|
{
|
||||||
|
QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = (int)pr_immediate._float;
|
||||||
|
patch1->a = (int)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCC_PR_Lex();
|
||||||
}
|
}
|
||||||
else if (pr_opcodes[op].type_b==NULL)
|
else if (pr_opcodes[op].type_b==NULL)
|
||||||
{
|
{
|
||||||
a = QCC_PR_ParseValue(pr_classtype);
|
|
||||||
p = (int)pr_immediate._float;
|
|
||||||
QCC_PR_Lex();
|
|
||||||
|
|
||||||
patch1 = &statements[numstatements];
|
patch1 = &statements[numstatements];
|
||||||
|
|
||||||
|
a = QCC_PR_ParseValue(pr_classtype);
|
||||||
QCC_PR_Statement3(&pr_opcodes[op], a, NULL, NULL);
|
QCC_PR_Statement3(&pr_opcodes[op], a, NULL, NULL);
|
||||||
|
|
||||||
patch1->b = (int)p;
|
if (pr_token_type == tt_name)
|
||||||
|
{
|
||||||
|
QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = (int)pr_immediate._float;
|
||||||
|
patch1->b = (int)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCC_PR_Lex();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
patch1 = &statements[numstatements];
|
||||||
|
|
||||||
a = QCC_PR_ParseValue(pr_classtype);
|
a = QCC_PR_ParseValue(pr_classtype);
|
||||||
b = QCC_PR_ParseValue(pr_classtype);
|
b = QCC_PR_ParseValue(pr_classtype);
|
||||||
p = (int)pr_immediate._float;
|
|
||||||
QCC_PR_Lex();
|
|
||||||
|
|
||||||
patch1 = &statements[numstatements];
|
|
||||||
QCC_PR_Statement3(&pr_opcodes[op], a, b, NULL);
|
QCC_PR_Statement3(&pr_opcodes[op], a, b, NULL);
|
||||||
|
|
||||||
patch1->c = (int)p;
|
if (pr_token_type == tt_name)
|
||||||
|
{
|
||||||
|
QCC_PR_GotoStatement(patch1, QCC_PR_ParseName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = (int)pr_immediate._float;
|
||||||
|
patch1->c = (int)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCC_PR_Lex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5869,7 +5966,12 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
|
||||||
{
|
{
|
||||||
if (!strcmp(pr_gotos[i].name, pr_labels[j].name))
|
if (!strcmp(pr_gotos[i].name, pr_labels[j].name))
|
||||||
{
|
{
|
||||||
statements[pr_gotos[i].statementno].a += pr_labels[j].statementno - pr_gotos[i].statementno;
|
if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_a)
|
||||||
|
statements[pr_gotos[i].statementno].a += pr_labels[j].statementno - pr_gotos[i].statementno;
|
||||||
|
else if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_b)
|
||||||
|
statements[pr_gotos[i].statementno].b += pr_labels[j].statementno - pr_gotos[i].statementno;
|
||||||
|
else
|
||||||
|
statements[pr_gotos[i].statementno].c += pr_labels[j].statementno - pr_gotos[i].statementno;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,7 @@ void QCC_PR_NewLine (pbool incomment)
|
||||||
qcc_token[0] = '\0';
|
qcc_token[0] = '\0';
|
||||||
for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++) //read on until the end of the line
|
for(a = 0; *pr_file_p != '\n' && *pr_file_p != '\0'; pr_file_p++) //read on until the end of the line
|
||||||
{
|
{
|
||||||
if ((*pr_file_p == ' ' || *pr_file_p == '\t') && !*qcc_token)
|
if ((*pr_file_p == ' ' || *pr_file_p == '\t'|| *pr_file_p == '(') && !*qcc_token)
|
||||||
{
|
{
|
||||||
msg[a] = '\0';
|
msg[a] = '\0';
|
||||||
strcpy(qcc_token, msg);
|
strcpy(qcc_token, msg);
|
||||||
|
@ -720,13 +720,34 @@ void QCC_PR_NewLine (pbool incomment)
|
||||||
strcpy(destfile, qcc_token);
|
strcpy(destfile, qcc_token);
|
||||||
printf("Outputfile: %s\n", destfile);
|
printf("Outputfile: %s\n", destfile);
|
||||||
}
|
}
|
||||||
else if (!QC_strcasecmp(qcc_token, "disable"))
|
else if (!QC_strcasecmp(qcc_token, "warning"))
|
||||||
{
|
{
|
||||||
qccwarningdisabled[atoi(msg)] = true;
|
int st;
|
||||||
}
|
char *s;
|
||||||
else if (!QC_strcasecmp(qcc_token, "enable"))
|
s = QCC_COM_Parse(msg);
|
||||||
{
|
if (!stricmp(qcc_token, "enable") || !stricmp(qcc_token, "on"))
|
||||||
qccwarningdisabled[atoi(msg)] = false;
|
st = 0;
|
||||||
|
else if (!stricmp(qcc_token, "disable") || !stricmp(qcc_token, "off"))
|
||||||
|
st = 1;
|
||||||
|
else if (!stricmp(qcc_token, "toggle"))
|
||||||
|
st = 2;
|
||||||
|
else
|
||||||
|
st = -1;
|
||||||
|
if (st>=0)
|
||||||
|
{
|
||||||
|
int wn;
|
||||||
|
s = QCC_COM_Parse(s);
|
||||||
|
wn = QCC_WarningForName(qcc_token);
|
||||||
|
if (wn < 0)
|
||||||
|
QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (st == 2) //toggle
|
||||||
|
qccwarningdisabled[wn] = true - qccwarningdisabled[wn];
|
||||||
|
else
|
||||||
|
qccwarningdisabled[wn] = st;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
|
QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
|
||||||
|
@ -1852,7 +1873,7 @@ int QCC_PR_CheakCompConst(void)
|
||||||
else
|
else
|
||||||
{ //stringify
|
{ //stringify
|
||||||
pr_file_p++;
|
pr_file_p++;
|
||||||
pr_file_p = QCC_COM_Parse(pr_file_p);
|
pr_file_p = QCC_COM_Parse2(pr_file_p);
|
||||||
if (!pr_file_p)
|
if (!pr_file_p)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1876,7 +1897,7 @@ int QCC_PR_CheakCompConst(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_file_p = QCC_COM_Parse(pr_file_p);
|
pr_file_p = QCC_COM_Parse2(pr_file_p);
|
||||||
if (!pr_file_p)
|
if (!pr_file_p)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1258,27 +1258,15 @@ int GUIprintf(const char *msg, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef Sys_Error
|
#undef Sys_Error
|
||||||
void Sys_Error(const char *text, ...);
|
|
||||||
void RunCompiler(char *args)
|
int BuildParms(char *args, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
static char param[2048];
|
||||||
char *argv[64];
|
|
||||||
char param[2048];
|
|
||||||
char *next;
|
|
||||||
int paramlen = 0;
|
int paramlen = 0;
|
||||||
int argc;
|
int argc;
|
||||||
progexterns_t ext;
|
char *next;
|
||||||
progfuncs_t funcs;
|
int i;
|
||||||
memset(&funcs, 0, sizeof(funcs));
|
|
||||||
funcs.parms = &ext;
|
|
||||||
memset(&ext, 0, sizeof(ext));
|
|
||||||
funcs.parms->ReadFile = GUIReadFile;
|
|
||||||
funcs.parms->FileSize = GUIFileSize;
|
|
||||||
funcs.parms->WriteFile = QCC_WriteFile;
|
|
||||||
funcs.parms->printf = GUIprintf;
|
|
||||||
funcs.parms->Sys_Error = Sys_Error;
|
|
||||||
GUIprintf("");
|
|
||||||
|
|
||||||
|
|
||||||
argc = 1;
|
argc = 1;
|
||||||
argv[0] = "fteqcc";
|
argv[0] = "fteqcc";
|
||||||
|
@ -1354,6 +1342,30 @@ void RunCompiler(char *args)
|
||||||
argv[argc++] = progssrcdir;
|
argv[argc++] = progssrcdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_Error(const char *text, ...);
|
||||||
|
void RunCompiler(char *args)
|
||||||
|
{
|
||||||
|
char *argv[64];
|
||||||
|
int argc;
|
||||||
|
progexterns_t ext;
|
||||||
|
progfuncs_t funcs;
|
||||||
|
|
||||||
|
memset(&funcs, 0, sizeof(funcs));
|
||||||
|
funcs.parms = &ext;
|
||||||
|
memset(&ext, 0, sizeof(ext));
|
||||||
|
funcs.parms->ReadFile = GUIReadFile;
|
||||||
|
funcs.parms->FileSize = GUIFileSize;
|
||||||
|
funcs.parms->WriteFile = QCC_WriteFile;
|
||||||
|
funcs.parms->printf = GUIprintf;
|
||||||
|
funcs.parms->Sys_Error = Sys_Error;
|
||||||
|
GUIprintf("");
|
||||||
|
|
||||||
|
|
||||||
|
argc = BuildParms(args, argv);
|
||||||
|
|
||||||
CompileParams(&funcs, true, argc, argv);
|
CompileParams(&funcs, true, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,6 +1502,30 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!*lpCmdLine)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
FILE *f;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
f = fopen("fteqcc.cfg", "rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
len = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
lpCmdLine = malloc(len+1);
|
||||||
|
fread(lpCmdLine, 1, len, f);
|
||||||
|
lpCmdLine[len] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
while(s = strchr(lpCmdLine, '\r'))
|
||||||
|
*s = ' ';
|
||||||
|
while(s = strchr(lpCmdLine, '\n'))
|
||||||
|
*s = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GuiParseCommandLine(lpCmdLine);
|
GuiParseCommandLine(lpCmdLine);
|
||||||
|
|
||||||
if (!*progssrcname)
|
if (!*progssrcname)
|
||||||
|
|
|
@ -134,6 +134,17 @@ struct {
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int QCC_WarningForName(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; warningnames[i].name; i++)
|
||||||
|
{
|
||||||
|
if (!stricmp(name, warningnames[i].name))
|
||||||
|
return warningnames[i].index;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
optimisations_t optimisations[] =
|
optimisations_t optimisations[] =
|
||||||
{
|
{
|
||||||
//level 0 = no optimisations
|
//level 0 = no optimisations
|
||||||
|
@ -194,9 +205,10 @@ struct {
|
||||||
|
|
||||||
//options
|
//options
|
||||||
{&keywords_coexist, true, "kce"},
|
{&keywords_coexist, true, "kce"},
|
||||||
{&output_parms, false, "parms"}, //controls weather to define PARMx for the parms
|
{&output_parms, false, "parms"}, //controls weather to define PARMx for the parms (note - this can screw over some decompilers)
|
||||||
{&autoprototype, false, "autoproto"},
|
{&autoprototype, false, "autoproto"}, //so you no longer need to prototype functions and things in advance.
|
||||||
{&writeasm, false, "wasm"},
|
{&writeasm, false, "wasm"}, //spit out a qc.asm file, containing an assembler dump of the ENTIRE progs. (Doesn't include initialisation of constants)
|
||||||
|
{&flag_ifstring, true, "ifstring"}, //correction for if(string) no-ifstring to get the standard behaviour.
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2428,6 +2440,7 @@ void QCC_SetDefaultProperties (void)
|
||||||
qccwarningdisabled[WARN_INEFFICIENTPLUSPLUS] = true;
|
qccwarningdisabled[WARN_INEFFICIENTPLUSPLUS] = true;
|
||||||
qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
|
qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
|
||||||
qccwarningdisabled[WARN_EXTENSION_USED] = true;
|
qccwarningdisabled[WARN_EXTENSION_USED] = true;
|
||||||
|
qccwarningdisabled[WARN_IFSTRING_USED] = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue