void *FS_ReadToMem(char *fname, void *membuf, int *len);
void FS_CloseFromMem(void *mem);
-struct qcc_includechunk_s *currentchunk;
-
unsigned int MAX_REGS;
int MAX_STRINGS;
PATHSTRING *precache_sounds;
int *precache_sounds_block;
+int *precache_sounds_used;
int numsounds;
PATHSTRING *precache_textures;
int *precache_textures_block;
+int *precache_textures_block;
int numtextures;
PATHSTRING *precache_models;
int *precache_models_block;
+int *precache_models_used;
int nummodels;
PATHSTRING *precache_files;
hashtable_t compconstantstable;
hashtable_t globalstable;
hashtable_t localstable;
+#ifdef WRITEASM
+FILE *asmfile;
+#endif
hashtable_t floatconstdefstable;
hashtable_t stringconstdefstable;
-hashtable_t stringconstdefstable_dotranslate;
-int dotranslate;
-int dotranslate_count;
+hashtable_t stringconstdefstable_trans;
+extern int dotranslate_count;
pbool qccwarningdisabled[WARN_MAX];
{&opt_return_only, "ro", 3, FLAG_KILLSDEBUGGERS, "return_only", "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."},
{&opt_compound_jumps, "cj", 3, FLAG_KILLSDEBUGGERS, "compound_jumps", "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."},
// {&opt_comexprremoval, "cer", 4, 0, "expression_removal", "Eliminate common sub-expressions"}, //this would be too hard...
- {&opt_stripfunctions, "sf", 3, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games."},
+ {&opt_stripfunctions, "sf", 4, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games. This can affect FTE_MULTIPROGS."},
{&opt_locals_marshalling, "lm", 4, FLAG_KILLSDEBUGGERS, "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."},
{&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
{NULL}
{&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output.
{&keyword_shared, defaultkeyword, "shared", "Keyword: shared", "Disables the 'shared' keyword."}, //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
{&keyword_state, nondefaultkeyword,"state", "Keyword: state", "Disables the 'state' keyword."},
+ {&keyword_optional, defaultkeyword,"optional", "Keyword: optional", "Disables the 'optional' keyword."},
{&keyword_string, defaultkeyword, "string", "Keyword: string", "Disables the 'string' keyword."},
{&keyword_struct, defaultkeyword, "struct", "Keyword: struct", "Disables the 'struct' keyword."},
{&keyword_switch, defaultkeyword, "switch", "Keyword: switch", "Disables the 'switch' keyword."},
{&flag_filetimes, 0, "filetimes", "Check Filetimes", "Recompiles the progs only if the file times are modified."},
{&flag_fasttrackarrays, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"fastarrays","fast arrays where possible", "Generates extra instructions inside array handling functions to detect engine and use extension opcodes only in supporting engines.\nAdds a global which is set by the engine if the engine supports the extra opcodes. Note that this applies to all arrays or none."},
{&flag_assume_integer, FLAG_MIDCOMPILE,"assumeint", "Assume Integers", "Numerical constants are assumed to be integers, instead of floats."},
- {&pr_subscopedlocals, FLAG_MIDCOMPILE, "subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."},
+ {&pr_subscopedlocals, FLAG_MIDCOMPILE,"subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."},
+ {&verbose, FLAG_MIDCOMPILE,"verbose", "Verbose", "Lots of extra compiler messages."},
+ {&flag_typeexplicit, FLAG_MIDCOMPILE,"typeexplicit", "Explicit types", "All type conversions must be explicit or directly supported by instruction set."},
{NULL}
};
int old;
char *s;
+ if (!str)
+ return 0;
+ if (!*str)
+ return 1;
+
if (opt_noduplicatestrings)
{
- if (!str || !*str)
- return 0;
-
for (s = strings; s < strings+strofs; s++)
if (!strcmp(s, str))
{
qcc_sourcefile = NULL;
numstatements = 1;
- strofs = 1;
+ strofs = 2;
numfunctions = 1;
numglobaldefs = 1;
numfielddefs = 1;
{
if (d->type->type == ev_function && !d->scope)// function parms are ok
{
- if (d->initialized != 1 && d->references>0)
+ if (!(d->initialized & 1) && d->references>0)
{
SafeWrite(handle, d->name, strlen(d->name)+1);
ret++;
if (compressoutput) progs.blockscompressed |=64; //line numbers
if (compressoutput) progs.blockscompressed |=128; //types
//include a type block?
- types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES"); //useful for debugging and saving (maybe, anyway...).
- if (sizeof(char *) != sizeof(string_t))
+ types = debugtarget;
+ if (types && sizeof(char *) != sizeof(string_t))
{
//qcc_typeinfo_t has a char* inside it, which changes size
printf("AMD64 builds cannot write typeinfo structures\n");
for (def = pr.def_head.next ; def ; def = def->next)
{
+ if ((def->type->type == ev_struct || def->type->type == ev_union || def->arraysize) && def->deftail)
+ {
+ QCC_def_t *d;
+ d = def;
+ while (d != def->deftail)
+ {
+ d = d->next;
+ h = d->references;
+ d->references += def->references;
+ def->references += h;
+ }
+ }
if (def->type->type == ev_vector || (def->type->type == ev_field && def->type->aux_type->type == ev_vector))
{ //do the references, so we don't get loadsa not referenced VEC_HULL_MINS_x
sprintf(element, "%s_x", def->name);
}
if (def->references<=0)
{
- if (def->constant)
- QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s no references", def->name);
- else
- QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s no references", def->name);
- if (!warnedunref)
+ int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED;
+ if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references", def->name))
{
- QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message.");
- warnedunref = true;
+ if (!warnedunref)
+ {
+ QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message.");
+ warnedunref = true;
+ }
}
if (opt_unreferenced && def->type->type != ev_field)
}
else if (def->type->type == ev_field && def->constant)
{
+ if (numfielddefs >= MAX_FIELDS)
+ QCC_PR_ParseError(0, "Too many fields. Limit is %u\n", MAX_FIELDS);
dd = &fields[numfielddefs];
numfielddefs++;
dd->type = def->type->aux_type->type;
dd->s_name = QCC_CopyString (def->name);
dd->ofs = G_INT(def->ofs);
}
- else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings))
+ else if ((def->scope||def->constant) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings)))
{
if (opt_constant_names)
{
continue;
if (dd->ofs == qcc_globals[h].ofs)
{
- if (dd->type != qcc_globals[h].type)
+ if ((dd->type&~DEF_SAVEGLOBAL) != (qcc_globals[h].type&~DEF_SAVEGLOBAL))
{
- if (dd->type != ev_vector && qcc_globals[h].type != ev_float)
+ if (!(((dd->type&~DEF_SAVEGLOBAL) == ev_vector && (qcc_globals[h].type&~DEF_SAVEGLOBAL) == ev_float) ||
+ ((dd->type&~DEF_SAVEGLOBAL) == ev_struct || (dd->type&~DEF_SAVEGLOBAL) == ev_union)))
QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name);
}
//remove the saveglobal flag on the duplicate globals.
QCC_PR_PrintOfs (d->ofs);
}*/
-QCC_type_t *QCC_PR_NewType (char *name, int basictype)
+QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed)
{
if (numtypeinfos>= maxtypeinfos)
QCC_Error(ERR_TOOMANYTYPES, "Too many types");
qcc_typeinfo[numtypeinfos].num_parms = 0;
qcc_typeinfo[numtypeinfos].param = NULL;
qcc_typeinfo[numtypeinfos].size = type_size[basictype];
+ qcc_typeinfo[numtypeinfos].arraysize = 0;
+ qcc_typeinfo[numtypeinfos].typedefed = typedefed;
numtypeinfos++;
pr_global_defs[i] = &def_void;
*/
- type_void = QCC_PR_NewType("void", ev_void);
- type_string = QCC_PR_NewType("string", ev_string);
- type_float = QCC_PR_NewType("float", ev_float);
- type_vector = QCC_PR_NewType("vector", ev_vector);
- type_entity = QCC_PR_NewType("entity", ev_entity);
- type_field = QCC_PR_NewType("field", ev_field);
- type_function = QCC_PR_NewType("function", ev_function);
- type_pointer = QCC_PR_NewType("pointer", ev_pointer);
- type_integer = QCC_PR_NewType("__integer", ev_integer);
- type_variant = QCC_PR_NewType("__variant", ev_variant);
-
- type_floatfield = QCC_PR_NewType("fieldfloat", ev_field);
+ type_void = QCC_PR_NewType("void", ev_void, true);
+ type_string = QCC_PR_NewType("string", ev_string, true);
+ type_float = QCC_PR_NewType("float", ev_float, true);
+ type_vector = QCC_PR_NewType("vector", ev_vector, true);
+ type_entity = QCC_PR_NewType("entity", ev_entity, true);
+ type_field = QCC_PR_NewType("__field", ev_field, false);
+ type_function = QCC_PR_NewType("__function", ev_function, false);
+ type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false);
+ type_integer = QCC_PR_NewType("__integer", ev_integer, true);
+ type_variant = QCC_PR_NewType("variant", ev_variant, true);
+ type_variant = QCC_PR_NewType("__variant", ev_variant, true);
+
+ type_floatfield = QCC_PR_NewType("fieldfloat", ev_field, false);
type_floatfield->aux_type = type_float;
- type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float);
+ type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float, false);
+
+ type_intpointer = QCC_PR_NewType("__intpointer", ev_pointer, false);
+ type_intpointer->aux_type = type_integer;
+ type_floatpointer = QCC_PR_NewType("__floatpointer", ev_pointer, false);
+ type_floatpointer->aux_type = type_float;
type_function->aux_type = type_void;
//type_field->aux_type = type_float;
- if (keyword_integer)
- type_integer = QCC_PR_NewType("integer", ev_integer);
- if (keyword_int)
- type_integer = QCC_PR_NewType("int", ev_integer);
+ type_integer = QCC_PR_NewType("integer", ev_integer, keyword_integer?true:false);
+ type_integer = QCC_PR_NewType("int", ev_integer, keyword_integer?true:false);
if (output_parms)
{ //this tends to confuse the brains out of decompilers. :)
numpr_globals = 1;
- QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++;
+ QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 0, false)->references++;
for (i = 0; i < MAX_PARMS; i++)
{
sprintf(name, "PARM%i", i);
- QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++;
+ QCC_PR_GetDef(type_vector, name, NULL, true, 0, false)->references++;
}
}
else
}
else
{
- QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name);
+ QCC_PR_ParseWarning(ERR_NOFUNC, "function %s was not defined",d->name);
+ QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
bodylessfuncs = true;
errors = true;
}
- s_file = NULL;
+ s_file = 0;
// errors = true;
}
else if (d->initialized==2)
QCC_def_t *d;
int f;
unsigned short crc;
+ QCC_def_t *ld;
// int c;
file[0] = '\0';
ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS));
for (d=pr.def_head.next ; d ; d=d->next)
{
+ ld = d;
if (!strcmp (d->name, "end_sys_globals"))
break;
if (d->ofs<RESERVED_OFS)
break;
case ev_vector:
ADD(qcva("\tvec3_t\t%s;\n",d->name));
- d=d->next->next->next; // skip the elements
+ if (d->deftail)
+ d=d->deftail; // skip the elements
break;
case ev_string:
ADD(qcva("\tstring_t\t%s;\n",d->name));
break;
case ev_vector:
ADD(qcva("\tvec3_t\t%s;\n",d->name));
- d=d->next->next->next; // skip the elements
+ if (d->deftail)
+ d=d->deftail; // skip the elements
break;
case ev_string:
ADD(qcva("\tstring_t\t%s;\n",d->name));
qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
qccwarningdisabled[WARN_EXTENSION_USED] = true;
qccwarningdisabled[WARN_IFSTRING_USED] = true;
+ qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true;
pHash_GetNext = &Hash_GetNext;
pHash_Add = &Hash_Add;
- MAX_REGS = 65536;
+ MAX_REGS = 1<<17;
MAX_STRINGS = 1000000;
- MAX_GLOBALS = 65535;
- MAX_FIELDS = 2048;
+ MAX_GLOBALS = 1<<17;
+ MAX_FIELDS = 1<<12;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;
maxtypeinfos = 16384;
QCC_PurgeTemps();
strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
- strofs = 1;
+ strofs = 2;
statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS);
numstatements = 0;
qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS);
numpr_globals=0;
- Hash_InitTable(&globalstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
- Hash_InitTable(&localstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
- Hash_InitTable(&floatconstdefstable, MAX_REGS+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS+1)));
- Hash_InitTable(&stringconstdefstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
- Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
- dotranslate=0;
- dotranslate_count=0;
+ Hash_InitTable(&globalstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+ Hash_InitTable(&localstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+ Hash_InitTable(&floatconstdefstable, MAX_REGS/2+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2+1)));
+ Hash_InitTable(&stringconstdefstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+ Hash_InitTable(&stringconstdefstable_trans, 1000, qccHunkAlloc(Hash_BytesForBuckets(1000)));
+ dotranslate_count = 0;
// pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);