A few changes. Reacc support

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@872 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2005-02-09 19:32:30 +00:00
parent cb487034e9
commit 4576ea829f
8 changed files with 706 additions and 71 deletions

View File

@ -45,7 +45,7 @@ void *Hash_Get(hashtable_t *table, char *name)
}
void *Hash_GetInsensative(hashtable_t *table, char *name)
{
int bucknum = Hash_Key(name, table->numbuckets);
int bucknum = Hash_KeyInsensative(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
@ -105,24 +105,39 @@ void *Hash_GetNext(hashtable_t *table, char *name, void *old)
}
return NULL;
}
#ifndef MINIMAL
void *Hash_Add(hashtable_t *table, char *name, void *data)
void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old)
{
int bucknum = Hash_Key(name, table->numbuckets);
bucket_t *buck;
int bucknum = Hash_KeyInsensative(name, table->numbuckets);
bucket_t *buck;
buck = qccHunkAlloc(sizeof(bucket_t));
buck = table->bucket[bucknum];
buck->data = data;
buck->keystring = name;
buck->next = table->bucket[bucknum];
table->bucket[bucknum] = buck;
while(buck)
{
if (!STRCMP(name, buck->keystring))
{
if (buck->data == old) //found the old one
break;
}
return buck;
buck = buck->next;
}
if (!buck)
return NULL;
buck = buck->next;//don't return old
while(buck)
{
if (!STRCMP(name, buck->keystring))
return buck->data;
buck = buck->next;
}
return NULL;
}
#endif
void *Hash_Add2(hashtable_t *table, char *name, void *data, bucket_t *buck)
void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck)
{
int bucknum = Hash_Key(name, table->numbuckets);

View File

@ -21,8 +21,8 @@ void *Hash_Get(hashtable_t *table, char *name);
void *Hash_GetInsensative(hashtable_t *table, char *name);
void *Hash_GetKey(hashtable_t *table, int key);
void *Hash_GetNext(hashtable_t *table, char *name, void *old);
void *Hash_Add(hashtable_t *table, char *name, void *data);
void *Hash_Add2(hashtable_t *table, char *name, void *data, bucket_t *buck);
void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old);
void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck);
void *Hash_AddInsensative(hashtable_t *table, char *name, void *data, bucket_t *buck);
void *Hash_AddKey(hashtable_t *table, int key, void *data);
void Hash_Remove(hashtable_t *table, char *name);

View File

@ -41,7 +41,7 @@ typedef struct {
int spare[2];
} evalc_t;
#define sizeofevalc sizeof(evalc_t)
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_struct, ev_union} etype_t;
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_struct, ev_union, ev_variant} etype_t;
struct progfuncs_s {
int progsversion; //PROGSTRUCT_VERSION

View File

@ -462,6 +462,9 @@ extern pbool keywords_coexist;
extern pbool output_parms;
extern pbool autoprototype;
extern pbool flag_ifstring;
extern pbool flag_acc;
extern pbool flag_caseinsensative;
extern pbool flag_laxcasts;
extern pbool opt_overlaptemps;
extern pbool opt_shortenifnots;
@ -516,6 +519,7 @@ QCC_type_t *QCC_PR_NewType (char *name, int basictype);
QCC_type_t *QCC_PR_ParseType (int newtype);
QCC_type_t *QCC_TypeForName(char *name);
QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype);
char *QCC_PR_ParseName (void);
CompilerConstant_t *QCC_PR_DefineName(char *name);
@ -580,6 +584,7 @@ enum {
WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about.
WARN_EXTENSION_USED, //extension that frikqcc also understands
WARN_IFSTRING_USED,
WARN_LAXCAST, //some errors become this with a compiler flag
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
@ -830,7 +835,7 @@ bool inline QCC_PR_Check (char *string)
{
if (strcmp (string, pr_token))
return false;
QCC_PR_Lex ();
return true;
}
@ -846,3 +851,6 @@ void inline QCC_PR_Expect (char *string)
void editbadfile(char *fname, int line);
char *TypeName(QCC_type_t *type);
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename);
extern void *(*pHash_Get)(hashtable_t *table, char *name);
extern void *(*pHash_GetNext)(hashtable_t *table, char *name, void *old);
extern void *(*pHash_Add)(hashtable_t *table, char *name, void *data, bucket_t *);

View File

@ -35,9 +35,12 @@ pbool keyword_class;
pbool keywords_coexist; //don't disable a keyword simply because a var was made with the same name.
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 flag_ifstring;
pbool flag_ifstring; //makes if (blah) equivelent to if (blah != "") which resolves some issues in multiprogs situations.
pbool flag_acc; //reacc like behaviour of src files (finds *.qc in start dir and compiles all in alphabetical order)
pbool flag_caseinsensative; //symbols will be matched to an insensative case if the specified case doesn't exist. This should b usable for any mod
pbool flag_laxcasts; //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code.
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.
@ -85,11 +88,15 @@ int optres_logicops;
int optres_test1;
int optres_test2;
void *(*pHash_Get)(hashtable_t *table, char *name);
void *(*pHash_GetNext)(hashtable_t *table, char *name, void *old);
void *(*pHash_Add)(hashtable_t *table, char *name, void *data, bucket_t *);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable);
QCC_type_t *QCC_PR_NewType (char *name, int basictype);
QCC_type_t *QCC_PR_FindType (QCC_type_t *type);
QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
void QCC_PR_ParseState (void);
pbool simplestore;
@ -2516,8 +2523,16 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
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));
else if (p->type != ev_variant) //can cast to variant whatever happens
{
if (flag_laxcasts)
{
QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
QCC_PR_ParsePrintDef(WARN_LAXCAST, func);
}
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;
@ -2787,7 +2802,7 @@ QCC_def_t *QCC_MakeStringDef(char *value)
QCC_def_t *cn;
int string;
cn = Hash_Get(&stringconstdefstable, value);
cn = pHash_Get(&stringconstdefstable, value);
if (cn)
return cn;
@ -2809,7 +2824,7 @@ QCC_def_t *QCC_MakeStringDef(char *value)
string = QCC_CopyString (value);
Hash_Add(&stringconstdefstable, strings+string, cn);
pHash_Add(&stringconstdefstable, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
G_INT(cn->ofs) = string;
@ -3059,6 +3074,23 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass)
if (pr_token_type == tt_immediate)
return QCC_PR_ParseImmediate ();
if (QCC_PR_Check("[")) //reacc support
{ //looks like a funky vector. :)
vec3_t v;
pr_immediate_type = type_vector;
v[0] = pr_immediate._float;
QCC_PR_Lex();
v[1] = pr_immediate._float;
QCC_PR_Lex();
v[2] = pr_immediate._float;
pr_immediate.vector[0] = v[0];
pr_immediate.vector[1] = v[1];
pr_immediate.vector[2] = v[2];
pr_immediate_type = type_vector;
d = QCC_PR_ParseImmediate();
QCC_PR_Expect("]");
return d;
}
name = QCC_PR_ParseName ();
if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar'
@ -4149,8 +4181,11 @@ QCC_def_t *QCC_PR_Expression (int priority)
op = oldop;
else
{
if (e->type->type == ev_pointer)
QCC_PR_ParseError (ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
if (flag_laxcasts)
{
op = oldop;
QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
}
else
QCC_PR_ParseError (ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, e->type->name, e2->type->name);
}
@ -4402,7 +4437,13 @@ void QCC_PR_ParseStatement (void)
if (pr_scope->type->aux_type->type != e->type->type)
QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name);
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], e, 0, NULL));
return;
return;
}
if (QCC_PR_Check("exit"))
{
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_DONE], 0, 0, NULL));
QCC_PR_Expect (";");
return;
}
if (QCC_PR_Check("while"))
@ -4666,6 +4707,16 @@ void QCC_PR_ParseStatement (void)
QCC_PR_Expect(";");
return;
}
if (QCC_PR_Check("#"))
{
char *name;
float frame = pr_immediate._float;
QCC_PR_Lex();
name = QCC_PR_ParseName();
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatDef(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0), NULL));
QCC_PR_Expect(";");
return;
}
if (QCC_PR_Check("if"))
{
@ -5961,7 +6012,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
conditional = 0;
f = (void *)qccHunkAlloc (sizeof(QCC_function_t));
//
@ -5980,6 +6031,19 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
locals_start = locals_end = OFS_PARM0; //hmm...
return f;
}
if (QCC_PR_Check("external"))
{ //reacc style builtin
if (pr_token_type != tt_immediate
|| pr_immediate_type != type_float
|| pr_immediate._float != (int)pr_immediate._float)
QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate");
f->builtin = (int)-pr_immediate._float;
QCC_PR_Lex ();
QCC_PR_Expect(";");
locals_start = locals_end = OFS_PARM0; //hmm...
return f;
}
if (type->num_parms < 0)
QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
@ -6063,11 +6127,21 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
}
else
{
if (QCC_PR_CheckInsens ("var")) //reacc support
{ //parse lots of locals
char *name;
do {
name = QCC_PR_ParseName();
QCC_PR_Expect(":");
e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1);
QCC_PR_Expect(";");
} while(!QCC_PR_Check("{"));
}
else
QCC_PR_Expect ("{");
//
// parse regular statements
//
QCC_PR_Expect ("{");
while (!QCC_PR_Check("}"))
{
QCC_PR_ParseStatement ();
@ -6602,14 +6676,14 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
if (referable)
{
if (!Hash_Get(&globalstable, "end_sys_fields"))
if (!pHash_Get(&globalstable, "end_sys_fields"))
first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off.
if (arraysize <= 1)
first->constant = false;
if (scope)
Hash_Add(&localstable, first->name, first);
pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
else
Hash_Add(&globalstable, first->name, first);
pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
if (!scope && asmfile)
fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
@ -6695,6 +6769,70 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
return def;
}
if (pHash_Get != &Hash_Get && !allocate) //do we want to try case insensative too?
{
if (scope)
{
def = pHash_Get(&localstable, name);
while(def)
{
if ( def->scope && def->scope != scope)
{
def = pHash_GetNext(&localstable, name, def);
continue; // in a different function
}
if (type && typecmp(def->type, type))
QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
if (def->arraysize != arraysize && arraysize)
QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
// if (!scope)
// QCC_PR_ParsePrintDef(def);
}
return def;
}
}
def = pHash_Get(&globalstable, name);
while(def)
{
if ( def->scope && def->scope != scope)
{
def = pHash_GetNext(&globalstable, name, def);
continue; // in a different function
}
if (type && typecmp(def->type, type))
{
if (!pr_scope)
QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type));
}
if (def->arraysize != arraysize && arraysize)
QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
{
if (pr_scope)
{ //warn? or would that be pointless?
def = pHash_GetNext(&globalstable, name, def);
continue; // in a different function
}
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
// if (!scope)
// QCC_PR_ParsePrintDef(def);
}
return def;
}
}
if (!allocate)
return NULL;
if (arraysize < 1)
@ -6878,6 +7016,7 @@ void QCC_PR_ExpandUnionToFields(QCC_type_t *type, int *fields)
QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields);
}
int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata
/*
================
PR_ParseDefs
@ -7019,6 +7158,141 @@ void QCC_PR_ParseDefs (char *classname)
return;
}
if (1)//flag_acc)
{
char *oldp;
if (QCC_PR_CheckInsens ("CodeSys")) //reacc support.
{
extern int ForcedCRC;
if (ForcedCRC)
QCC_PR_ParseError(ERR_BADEXTENSION, "progs crc was already specified - only one is allowed");
ForcedCRC = pr_immediate._float;
QCC_PR_Lex();
QCC_PR_Expect(";");
return;
}
oldp = pr_file_p;
if (QCC_PR_CheckInsens ("var")) //reacc support.
{
if (accglobalsblock == 3)
{
if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0))
QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1);
}
QCC_PR_ParseName();
if (QCC_PR_Check(":"))
accglobalsblock = 1;
pr_file_p = oldp;
QCC_PR_Lex();
}
if (QCC_PR_CheckInsens ("function")) //reacc support.
{
accglobalsblock = 2;
}
if (QCC_PR_CheckInsens ("objdata")) //reacc support.
{
if (accglobalsblock == 3)
{
if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0))
QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1);
}
else
if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0))
QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 1);
accglobalsblock = 3;
}
}
if (!pr_scope)
switch(accglobalsblock)//reacc support.
{
case 1:
{
char *oldp = pr_file_p;
name = QCC_PR_ParseName();
if (!QCC_PR_Check(":")) //nope, it wasn't!
{
QCC_PR_IncludeChunk(name, true, NULL);
QCC_PR_Lex();
QCC_PR_UnInclude();
pr_file_p = oldp;
break;
}
if (QCC_PR_CheckInsens("Object"))
QCC_PR_GetDef(type_entity, name, NULL, true, 1);
else if (QCC_PR_CheckInsens("String"))
QCC_PR_GetDef(type_string, name, NULL, true, 1);
else if (QCC_PR_CheckInsens("Real"))
{
def = QCC_PR_GetDef(type_float, name, NULL, true, 1);
if (QCC_PR_Check("="))
{
G_FLOAT(def->ofs) = pr_immediate._float;
QCC_PR_Lex();
}
}
else if (QCC_PR_CheckInsens("Vector"))
{
def = QCC_PR_GetDef(type_vector, name, NULL, true, 1);
if (QCC_PR_Check("="))
{
QCC_PR_Expect("[");
G_FLOAT(def->ofs+0) = pr_immediate._float;
QCC_PR_Lex();
G_FLOAT(def->ofs+1) = pr_immediate._float;
QCC_PR_Lex();
G_FLOAT(def->ofs+2) = pr_immediate._float;
QCC_PR_Lex();
QCC_PR_Expect("]");
}
}
else if (QCC_PR_CheckInsens("PFunc"))
QCC_PR_GetDef(type_function, name, NULL, true, 1);
else
QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
QCC_PR_Expect (";");
if (QCC_PR_Check ("system"))
QCC_PR_Expect (";");
return;
}
case 2:
name = QCC_PR_ParseName();
QCC_PR_GetDef(type_function, name, NULL, true, 1);
QCC_PR_Check (";");
return;
case 3:
{
char *oldp = pr_file_p;
name = QCC_PR_ParseName();
if (!QCC_PR_Check(":")) //nope, it wasn't!
{
QCC_PR_IncludeChunk(name, true, NULL);
QCC_PR_Lex();
QCC_PR_UnInclude();
pr_file_p = oldp;
break;
}
if (QCC_PR_CheckInsens("Object"))
QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 1);
else if (QCC_PR_CheckInsens("String"))
QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 1);
else if (QCC_PR_CheckInsens("real"))
QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 1);
else if (QCC_PR_CheckInsens("vector"))
QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 1);
else if (QCC_PR_CheckInsens("pfunc"))
QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 1);
else
QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n");
QCC_PR_Expect (";");
return;
}
}
while(1)
{
if (QCC_PR_Check("extern"))
@ -7051,6 +7325,88 @@ void QCC_PR_ParseDefs (char *classname)
externfnc=false;
}
if (!pr_scope && QCC_PR_CheckInsens("function")) //reacc support.
{
name = QCC_PR_ParseName ();
QCC_PR_Expect("(");
type = QCC_PR_ParseFunctionTypeReacc(false, type);
QCC_PR_Expect(";");
if (!stricmp(name, "null"))
printf("null!\n");
def = QCC_PR_GetDef (type, name, NULL, true, 1);
if (autoprototype)
{ //ignore the code and stuff
if (QCC_PR_Check("external"))
{ //builtin
QCC_PR_Lex();
QCC_PR_Expect(";");
}
else
{
int blev = 1;
while (!QCC_PR_Check("{")) //skip over the locals.
{
if (pr_token_type == tt_eof)
{
QCC_PR_ParseError(0, "Unexpected EOF");
break;
}
QCC_PR_Lex();
}
//balance out the { and }
while(blev)
{
if (pr_token_type == tt_eof)
break;
if (QCC_PR_Check("{"))
blev++;
else if (QCC_PR_Check("}"))
blev--;
else
QCC_PR_Lex(); //ignore it.
}
}
return;
}
def->references++;
pr_scope = def;
f = QCC_PR_ParseImmediateStatements (type);
pr_scope = NULL;
def->initialized = 1;
G_FUNCTION(def->ofs) = numfunctions;
f->def = def;
// if (pr_dumpasm)
// PR_PrintFunction (def);
// fill in the dfunction
df = &functions[numfunctions];
numfunctions++;
if (f->builtin)
df->first_statement = -f->builtin;
else
df->first_statement = f->code;
if (f->builtin && opt_function_names)
optres_function_names += strlen(f->def->name);
else
df->s_name = QCC_CopyString (f->def->name);
df->s_file = s_file2;
df->numparms = f->def->type->num_parms;
df->locals = locals_end - locals_start;
df->parm_start = locals_start;
for (i=0,parm = type->param ; i<df->numparms ; i++, parm = parm->next)
{
df->parm_size[i] = parm->size;
}
return;
}
// if (pr_scope && (type->type == ev_field) )
// QCC_PR_ParseError ("Fields must be global");
@ -7184,7 +7540,12 @@ void QCC_PR_ParseDefs (char *classname)
continue;
}
if ( QCC_PR_Check ("=") || ((type->type == ev_function) && (pr_token[0] == '{' || pr_token[0] == '[' || pr_token[0] == ':'))) //this is an initialisation (or a function)
if (type->type == ev_field && QCC_PR_Check ("alias"))
{
QCC_PR_ParseError(ERR_INTERNAL, "FTEQCC does not support this variant of decompiled hexenc\nPlease obtain the origional version released by Raven Software instead.");
name = QCC_PR_ParseName();
}
else if ( QCC_PR_Check ("=") || ((type->type == ev_function) && (pr_token[0] == '{' || pr_token[0] == '[' || pr_token[0] == ':'))) //this is an initialisation (or a function)
{
if (def->shared)
QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);

View File

@ -1020,6 +1020,8 @@ void QCC_PR_LexString (void)
continue;
}
}
else if (c == 0x74)
c = '\n';
pr_token[len] = c|texttype;
len++;
@ -1555,7 +1557,7 @@ pbool QCC_PR_UndefineName(char *name)
{
// int a;
CompilerConstant_t *c;
c = Hash_Get(&compconstantstable, name);
c = pHash_Get(&compconstantstable, name);
if (!c)
{
QCC_PR_ParseWarning(WARN_NOTDEFINED, "Precompiler constant %s was not defined", name);
@ -1609,7 +1611,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name)
if (strlen(name) >= MAXCONSTANTLENGTH || !*name)
QCC_PR_ParseError(ERR_CONSTANTTOOLONG, "Compiler constant name length is too long or short");
cnst = Hash_Get(&compconstantstable, name);
cnst = pHash_Get(&compconstantstable, name);
if (cnst )
{
QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
@ -1626,7 +1628,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name)
for (i = 0; i < MAXCONSTANTPARAMS; i++)
cnst->params[i][0] = '\0';
Hash_Add(&compconstantstable, cnst->name, cnst);
pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
if (!STRCMP(name, "OP_NODUP"))
opt_noduplicatestrings = true;
@ -1696,7 +1698,7 @@ void QCC_PR_ConditionCompilation(void)
if (!QCC_PR_SimpleGetToken ())
QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
cnst = Hash_Get(&compconstantstable, pr_token);
cnst = pHash_Get(&compconstantstable, pr_token);
if (cnst)
{
Hash_Remove(&compconstantstable, pr_token);
@ -1833,7 +1835,7 @@ int QCC_PR_CheakCompConst(void)
strncpy(pr_token, pr_file_p, end-pr_file_p);
pr_token[end-pr_file_p]='\0';
// printf("%s\n", pr_token);
c = Hash_Get(&compconstantstable, pr_token);
c = pHash_Get(&compconstantstable, pr_token);
if (c)
{
@ -2044,7 +2046,7 @@ char *QCC_PR_CheakCompConstString(char *def)
CompilerConstant_t *c;
c = Hash_Get(&compconstantstable, def);
c = pHash_Get(&compconstantstable, def);
if (c)
{
@ -2056,7 +2058,7 @@ char *QCC_PR_CheakCompConstString(char *def)
CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def)
{
CompilerConstant_t *c = Hash_Get(&compconstantstable, def);
CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
return c;
/*int a;
for (a = 0; a < numCompilerConstants; a++)
@ -2330,12 +2332,21 @@ pbool QCC_PR_Check (char *string)
{
if (STRCMP (string, pr_token))
return false;
QCC_PR_Lex ();
return true;
}
#endif
pbool QCC_PR_CheckInsens (char *string)
{
if (stricmp (string, pr_token))
return false;
QCC_PR_Lex ();
return true;
}
/*
============
PR_ParseName
@ -2662,6 +2673,85 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
return ftype;
return QCC_PR_FindType (ftype);
}
QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
{
QCC_type_t *ftype, *ptype, *nptype;
char *name;
char argname[64];
int definenames = !recursivefunctiontype;
pbool usesvariants = false;
recursivefunctiontype++;
ftype = QCC_PR_NewType(type_function->name, ev_function);
ftype->aux_type = returntype; // return type
ftype->num_parms = 0;
ptype = NULL;
if (!QCC_PR_Check (")"))
{
if (QCC_PR_Check ("..."))
ftype->num_parms = -1; // variable args
else
do
{
if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS);
if (QCC_PR_Check ("..."))
{
ftype->num_parms = (ftype->num_parms * -1) - 1;
break;
}
if (QCC_PR_Check("arg"))
{
sprintf(argname, "arg%i", ftype->num_parms);
name = argname;
nptype = QCC_PR_NewType("Variant", ev_variant);
}
else if (QCC_PR_Check("vect")) //this can only be of vector sizes, so...
{
sprintf(argname, "arg%i", ftype->num_parms);
name = argname;
nptype = QCC_PR_NewType("Vector", ev_vector);
}
else
{
name = QCC_PR_ParseName();
QCC_PR_Expect(":");
nptype = QCC_PR_ParseType(true);
}
if (nptype->type == ev_void)
break;
if (!ptype)
{
ptype = nptype;
ftype->param = ptype;
}
else
{
ptype->next = nptype;
ptype = ptype->next;
}
// type->name = "FUNC PARAMETER";
if (definenames)
strcpy (pr_parm_names[ftype->num_parms], name);
ftype->num_parms++;
} while (QCC_PR_Check (";"));
QCC_PR_Expect (")");
}
recursivefunctiontype--;
if (newtype)
return ftype;
return QCC_PR_FindType (ftype);
}
QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
{
QCC_type_t *ptype;
@ -2671,6 +2761,16 @@ QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
ptype->aux_type = pointsto;
return QCC_PR_FindType (ptype);
}
QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
{
QCC_type_t *ptype;
char name[128];
sprintf(name, "FIELD TYPE(%s)", pointsto->name);
ptype = QCC_PR_NewType(name, ev_field);
ptype->aux_type = pointsto;
ptype->size = ptype->aux_type->size;
return QCC_PR_FindType (ptype);
}
QCC_type_t *QCC_PR_ParseType (int newtype)
{
@ -2886,8 +2986,23 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
if (i == numtypeinfos)
{
QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
type = type_float; // shut up compiler warning
if (!stricmp("Void", name))
type = type_void;
else if (!stricmp("Real", name))
type = type_float;
else if (!stricmp("Vector", name))
type = type_vector;
else if (!stricmp("Object", name))
type = type_entity;
else if (!stricmp("String", name))
type = type_string;
else if (!stricmp("PFunc", name))
type = type_function;
else
{
QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name);
type = type_float; // shut up compiler warning
}
}
QCC_PR_Lex ();
@ -2904,6 +3019,5 @@ QCC_type_t *QCC_PR_ParseType (int newtype)
}
}
#endif

View File

@ -23,6 +23,7 @@ static pbool fl_nokeywords_coexist;
static pbool fl_autohighlight;
static pbool fl_compileonstart;
static pbool fl_autoprototype;
static pbool fl_acc;
char parameters[16384];
@ -1305,6 +1306,13 @@ int BuildParms(char *args, char **argv)
paramlen += strlen(param+paramlen)+1;
}
if (fl_acc)
{
strcpy(param+paramlen, "-Facc");
argv[argc++] = param+paramlen;
paramlen += strlen(param+paramlen)+1;
}
for (i = 0; optimisations[i].enabled; i++) //enabled is a pointer
{
@ -1454,6 +1462,10 @@ void GuiParseCommandLine(char *args)
{
fl_autoprototype = true;
}
else if (!strnicmp(parameters+paramlen, "-Facc", 5) || !strnicmp(parameters+paramlen, "/Facc", 5))
{
fl_acc = true;
}
else if (!strnicmp(parameters+paramlen, "-ac", 3) || !strnicmp(parameters+paramlen, "/ac", 3))
{
fl_compileonstart = true;
@ -1537,7 +1549,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
GuiParseCommandLine(lpCmdLine);
if (!*progssrcname)
if (!fl_acc && !*progssrcname)
{
strcpy(progssrcname, "preprogs.src");
if (QCC_FileSize(progssrcname)==-1)
@ -1633,6 +1645,36 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
NULL,
ghInstance,
NULL);
if (!outputbox)
outputbox=CreateWindowEx(WS_EX_CLIENTEDGE,
richedit?RICHEDIT_CLASS10A:"EDIT", //fall back to the earlier version
"",
WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 0, 0,
mainwindow,
NULL,
ghInstance,
NULL);
if (!outputbox)
{ //you've not got RICHEDIT installed properly, I guess
FreeLibrary(richedit);
richedit = NULL;
outputbox=CreateWindowEx(WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 0, 0,
mainwindow,
NULL,
ghInstance,
NULL);
}
if (richedit)
{
SendMessage(outputbox, EM_EXLIMITTEXT, 0, 1<<20);
@ -1731,6 +1773,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
}
else if (!strncmp(line, "compiling ", 10))
EditFile(line+10, -1);
else if (!strncmp(line, "prototyping ", 12))
EditFile(line+12, -1);
Edit_SetSel(outputbox, i&0xffff, i&0xffff); //deselect it.
}
}

View File

@ -209,6 +209,9 @@ struct {
{&autoprototype, false, "autoproto"}, //so you no longer need to prototype functions and things in advance.
{&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.
{&flag_acc, false, "acc"}, //reacc like behaviour of src files.
{&flag_caseinsensative, false, "caseinsens"}, //symbols will be matched to an insensative case if the specified case doesn't exist. This should b usable for any mod
{&flag_laxcasts, false, "lax"}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code.
{NULL}
};
@ -689,8 +692,8 @@ void QCC_WriteData (int crc)
{
if (def->references<=1)
QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called or referenced (spawn function or dead code)", def->name);
else
QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name);
// else
// QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name);
}
if (opt_stripfunctions && def->timescalled >= def->references-1) //make sure it's not copied into a different var.
{ //if it ever does self.think then it could be needed for saves.
@ -1615,11 +1618,14 @@ char *Sva(char *msg, ...)
}
*/
#define PROGDEFS_MAX_SIZE 16384
//write (to file buf) and add to the crc
void inline Add(char *p, unsigned short *crc, char *file)
{
char *s;
int i = strlen(file);
if (i + strlen(p)+1 >= PROGDEFS_MAX_SIZE)
return;
for(s=p;*s;s++,i++)
{
QCC_CRC_ProcessByte(crc, *s);
@ -1641,8 +1647,10 @@ void inline Add3(char *p, unsigned short *crc, char *file)
unsigned short QCC_PR_WriteProgdefs (char *filename)
{
extern int ForcedCRC;
#define ADD2(p) strcat(file, p) //no crc (later changes)
char file[16384];
#define ADD2(p) strncat(file, p, PROGDEFS_MAX_SIZE-1 - strlen(file)) //no crc (later changes)
int sent1=0xffffffff;
char file[PROGDEFS_MAX_SIZE];
int sent2=0xffffffff;
QCC_def_t *d;
int f;
unsigned short crc;
@ -1771,7 +1779,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
if (QCC_CheckParm("-progdefs"))
{
printf ("writing %s\n", filename);
f = SafeOpenWrite("progdefs.h", 16384);
f = SafeOpenWrite(filename, 16384);
SafeWrite(f, file, strlen(file));
SafeClose(f);
}
@ -2370,8 +2378,14 @@ void SetEndian(void);
void QCC_SetDefaultProperties (void)
{
extern int ForcedCRC;
int level;
int i;
Hash_InitTable(&compconstantstable, MAX_CONSTANTS, qccHunkAlloc(Hash_BytesForBuckets(MAX_CONSTANTS)));
ForcedCRC = 0;
QCC_PR_DefineName("FTEQCC");
if (QCC_CheckParm("/Oz"))
@ -2469,12 +2483,70 @@ void QCC_SetDefaultProperties (void)
}
}
//builds a list of files, pretends that they came from a progs.src
int QCC_FindQCFiles()
{
#ifdef _WIN32
WIN32_FIND_DATA fd;
HANDLE h;
#endif
int numfiles = 0, i, j;
char *filelist[256], *temp;
qccmsrc = qccHunkAlloc(8192);
strcat(qccmsrc, "progs.dat\n");//"#pragma PROGS_DAT progs.dat\n");
#ifdef _WIN32
h = FindFirstFile("*.qc", &fd);
if (h == INVALID_HANDLE_VALUE)
return 0;
do
{
filelist[numfiles] = qccHunkAlloc (strlen(fd.cFileName)+1);
strcpy(filelist[numfiles], fd.cFileName);
numfiles++;
} while(FindNextFile(h, &fd)!=0);
FindClose(h);
#else
printf("-Facc is not supported on this platform. Please make a progs.src file instead\n");
#endif
//Sort alphabetically.
//bubble. :(
for (i = 0; i < numfiles-1; i++)
{
for (j = i+1; j < numfiles; j++)
{
if (stricmp(filelist[i], filelist[j]) > 0)
{
temp = filelist[j];
filelist[j] = filelist[i];
filelist[i] = temp;
}
}
}
for (i = 0; i < numfiles; i++)
{
strcat(qccmsrc, filelist[i]);
strcat(qccmsrc, "\n");
// strcat(qccmsrc, "#include \"");
// strcat(qccmsrc, filelist[i]);
// strcat(qccmsrc, "\"\n");
}
return numfiles;
}
int qcc_compileactive = false;
extern int accglobalsblock;
char *origionalqccmsrc; //for autoprototype.
void QCC_main (int argc, char **argv) //as part of the quake engine
{
extern int pr_bracelevel;
extern int ForcedCRC;
int p;
@ -2489,6 +2561,10 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
qcc_compileactive = true;
pHash_Get = &Hash_Get;
pHash_GetNext = &Hash_GetNext;
pHash_Add = &Hash_Add;
MAX_REGS = 65536;
MAX_STRINGS = 1000000;
MAX_GLOBALS = 32768;
@ -2567,7 +2643,6 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
*compiler_flag[p].enabled = compiler_flag[p].defaultval;
}
Hash_InitTable(&compconstantstable, MAX_CONSTANTS, qccHunkAlloc(Hash_BytesForBuckets(MAX_CONSTANTS)));
QCC_SetDefaultProperties();
optres_shortenifnots = 0;
@ -2594,6 +2669,8 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
optres_test1 = 0;
optres_test2 = 0;
accglobalsblock = 0;
numtemps = 0;
@ -2659,8 +2736,6 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
#ifdef MAX_EXTRA_PARMS
memset(&extra_parms, 0, sizeof(extra_parms));
#endif
ForcedCRC = 0;
if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
{
@ -2686,6 +2761,15 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
return;
}
if (flag_caseinsensative)
{
printf("Compiling without case insensativity\n");
pHash_Get = &Hash_GetInsensative;
pHash_GetNext = &Hash_GetNextInsensative;
pHash_Add = &Hash_AddInsensative;
}
if (opt_locals_marshalling)
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nLocals marshalling might be buggy. Use with caution\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
@ -2710,25 +2794,33 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
QCC_PR_BeginCompilation ((void *)qccHunkAlloc (0x100000), 0x100000);
p = QCC_CheckParm ("-qc");
if (!p || p >= argc-1 || argv[p+1][0] == '-')
p = QCC_CheckParm ("-srcfile");
if (p && p < argc-1 )
sprintf (qccmprogsdat, "%s%s", qccmsourcedir, argv[p+1]);
if (flag_acc)
{
if (!QCC_FindQCFiles())
QCC_Error (ERR_COULDNTOPENFILE, "Couldn't open file for asm output.");
}
else
{ //look for a preprogs.src... :o)
sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir);
if (externs->FileSize(qccmprogsdat) <= 0)
sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir);
{
p = QCC_CheckParm ("-qc");
if (!p || p >= argc-1 || argv[p+1][0] == '-')
p = QCC_CheckParm ("-srcfile");
if (p && p < argc-1 )
sprintf (qccmprogsdat, "%s%s", qccmsourcedir, argv[p+1]);
else
{ //look for a preprogs.src... :o)
sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir);
if (externs->FileSize(qccmprogsdat) <= 0)
sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir);
}
printf ("Source file: %s\n", qccmprogsdat);
if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
{
return;
}
}
printf ("Source file: %s\n", qccmprogsdat);
if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
{
return;
}
newstylesource = false;
while(*qccmsrc && *qccmsrc < ' ')
@ -2840,6 +2932,7 @@ void QCC_ContinueCompile(void)
if (autoprototype)
{
qccmsrc = origionalqccmsrc;
QCC_SetDefaultProperties();
autoprototype = false;
return;
}