qccClearHunk();
strcpy(qcc_gamedir, "");
- qcchunk = malloc(qcchunksize=128*1024*1024);
+ qcchunk = malloc(qcchunksize=256*1024*1024);
while(!qcchunk && qcchunksize > 8*1024*1024)
{
qcchunksize /= 2;
st = pr_statements + s;
reeval:
+ switch (st->op & ~0x8000)
#else
st++;
-#endif
-
switch (st->op)
+#endif
{
case OP_ADD_F:
OPC->_float = OPA->_float + OPB->_float;
OPC->_vector[2] = OPB->_float / OPA->_vector[2];
break;
- case OP_BITAND:
+ case OP_BITAND_F:
OPC->_float = (float)((int)OPA->_float & (int)OPB->_float);
break;
- case OP_BITOR:
+ case OP_BITOR_F:
OPC->_float = (float)((int)OPA->_float | (int)OPB->_float);
break;
- case OP_GE:
+ case OP_GE_F:
OPC->_float = (float)(OPA->_float >= OPB->_float);
break;
case OP_GE_I:
OPC->_float = (float)(OPA->_float >= OPB->_int);
break;
- case OP_LE:
+ case OP_LE_F:
OPC->_float = (float)(OPA->_float <= OPB->_float);
break;
case OP_LE_I:
OPC->_float = (float)(OPA->_float <= OPB->_int);
break;
- case OP_GT:
+ case OP_GT_F:
OPC->_float = (float)(OPA->_float > OPB->_float);
break;
case OP_GT_I:
OPC->_float = (float)(OPA->_float > OPB->_int);
break;
- case OP_LT:
+ case OP_LT_F:
OPC->_float = (float)(OPA->_float < OPB->_float);
break;
case OP_LT_I:
OPC->_float = (float)(OPA->_float < OPB->_int);
break;
- case OP_AND:
+ case OP_AND_F:
OPC->_float = (float)(OPA->_float && OPB->_float);
break;
- case OP_OR:
+ case OP_OR_F:
OPC->_float = (float)(OPA->_float || OPB->_float);
break;
st += (sofs)st->b - 1; // offset the s++
break;
- case OP_IFNOT:
+ case OP_IFNOT_I:
RUNAWAYCHECK();
if (!OPA->_int)
st += (sofs)st->b - 1; // offset the s++
st += (sofs)st->b - 1; // offset the s++
break;
- case OP_IF:
+ case OP_IF_I:
RUNAWAYCHECK();
if (OPA->_int)
st += (sofs)st->b - 1; // offset the s++
fnum = OPA->function;
if ((fnum & ~0xff000000)==0)
{
- pr_trace++;
- printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
+ PR_RunError(progfuncs, "NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
#ifndef DEBUGABLE
goto cont;
#endif
break;
- //array/structure reading/riting.
+ //array/structure reading/writing.
case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break;
{
PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
}
- t = (eval_t *)&pr_globals[(uofs)st->a
- +((int)OPB->_float)*3];
+ t = (eval_t *)&pr_globals[(uofs)st->a + i*3];
OPC->_vector[0] = t->_vector[0];
OPC->_vector[1] = t->_vector[1];
OPC->_vector[2] = t->_vector[2];
st = &pr_statements[s]; //let the user move execution
pr_xstatement = s = st-pr_statements;
-#if 0 //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement
- memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one.
- fakeop.op &= ~0x8000;
- st = &fakeop; //a little remapping...
-#else
- st->op &= ~0x8000; //just remove the breakpoint and go around again, but this time in the debugger.
-#endif
-
goto reeval; //reexecute
}
pr_xstatement = st-pr_statements;
#endif
// hash init assumes we get clean memory
-void Hash_InitTable(hashtable_t *table, int numbucks, void *mem)
+void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem)
{
table->numbuckets = numbucks;
table->bucket = (bucket_t **)mem;
}
-int Hash_Key(const char *name, int modulus)
+unsigned int Hash_Key(const char *name, unsigned int modulus)
{ //fixme: optimize.
unsigned int key;
for (key=0;*name; name++)
key += ((key<<3) + (key>>28) + *name);
- return (int)(key%modulus);
+ return (key%modulus);
}
-int Hash_KeyInsensative(const char *name, int modulus)
+unsigned int Hash_KeyInsensative(const char *name, unsigned int modulus)
{ //fixme: optimize.
unsigned int key;
for (key=0;*name; name++)
key += ((key<<3) + (key>>28) + *name);
}
- return (int)(key%modulus);
+ return (key%modulus);
}
void *Hash_Get(hashtable_t *table, const char *name)
{
- int bucknum = Hash_Key(name, table->numbuckets);
+ unsigned int bucknum = Hash_Key(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
}
void *Hash_GetInsensative(hashtable_t *table, const char *name)
{
- int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+ unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
}
return NULL;
}
-void *Hash_GetKey(hashtable_t *table, int key)
+void *Hash_GetKey(hashtable_t *table, unsigned int key)
{
- int bucknum = key%table->numbuckets;
+ unsigned int bucknum = key%table->numbuckets;
bucket_t *buck;
buck = table->bucket[bucknum];
}
return NULL;
}
-void *Hash_GetNext(hashtable_t *table, char *name, void *old)
+/*Does _NOT_ support items that are added with two names*/
+void *Hash_GetNextKey(hashtable_t *table, unsigned int key, void *old)
{
- int bucknum = Hash_Key(name, table->numbuckets);
+ unsigned int bucknum = key%table->numbuckets;
bucket_t *buck;
buck = table->bucket[bucknum];
while(buck)
{
- if (!STRCMP(name, buck->key.string))
- {
- if (buck->data == old) //found the old one
- break;
- }
+ if (buck->data == old) //found the old one
+ break;
+ buck = buck->next;
+ }
+ if (!buck)
+ return NULL;
+
+ buck = buck->next;//don't return old
+ while(buck)
+ {
+ if (buck->key.value == key)
+ return buck->data;
+
+ buck = buck->next;
+ }
+ return NULL;
+}
+/*Does _NOT_ support items that are added with two names*/
+void *Hash_GetNext(hashtable_t *table, const char *name, void *old)
+{
+ unsigned int bucknum = Hash_Key(name, table->numbuckets);
+ bucket_t *buck;
+
+ buck = table->bucket[bucknum];
+ while(buck)
+ {
+ if (buck->data == old) //found the old one
+// if (!STRCMP(name, buck->key.string))
+ break;
buck = buck->next;
}
if (!buck)
}
return NULL;
}
-void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old)
+/*Does _NOT_ support items that are added with two names*/
+void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old)
{
- int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+ unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
while(buck)
{
- if (!STRCMP(name, buck->key.string))
+ if (buck->data == old) //found the old one
{
- if (buck->data == old) //found the old one
+// if (!stricmp(name, buck->key.string))
break;
}
buck = buck->next;//don't return old
while(buck)
{
- if (!STRCMP(name, buck->key.string))
+ if (!stricmp(name, buck->key.string))
return buck->data;
buck = buck->next;
}
-void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck)
+void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck)
{
- int bucknum = Hash_Key(name, table->numbuckets);
+ unsigned int bucknum = Hash_Key(name, table->numbuckets);
buck->data = data;
buck->key.string = name;
return buck;
}
-void *Hash_AddInsensative(hashtable_t *table, char *name, void *data, bucket_t *buck)
+void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck)
{
- int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+ unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets);
buck->data = data;
buck->key.string = name;
return buck;
}
-void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck)
+void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck)
{
- int bucknum = key%table->numbuckets;
+ unsigned int bucknum = key%table->numbuckets;
buck->data = data;
buck->key.value = key;
return buck;
}
-void Hash_Remove(hashtable_t *table, char *name)
+void Hash_Remove(hashtable_t *table, const char *name)
{
- int bucknum = Hash_Key(name, table->numbuckets);
+ unsigned int bucknum = Hash_Key(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
- if(!buck)
- return;
if (!STRCMP(name, buck->key.string))
{
return;
}
-void Hash_RemoveData(hashtable_t *table, char *name, void *data)
+void Hash_RemoveData(hashtable_t *table, const char *name, void *data)
{
- int bucknum = Hash_Key(name, table->numbuckets);
+ unsigned int bucknum = Hash_Key(name, table->numbuckets);
bucket_t *buck;
buck = table->bucket[bucknum];
- if(!buck)
- return;
if (buck->data == data)
if (!STRCMP(name, buck->key.string))
}
-void Hash_RemoveKey(hashtable_t *table, int key)
+void Hash_RemoveKey(hashtable_t *table, unsigned int key)
{
- int bucknum = key%table->numbuckets;
+ unsigned int bucknum = key%table->numbuckets;
bucket_t *buck;
buck = table->bucket[bucknum];
- if(!buck)
- return;
if (buck->key.value == key)
{
#ifndef HASH_H__
#define HASH_H__
-#define Hash_BytesForBuckets(b) (sizeof(bucket_t)*b)
+#define Hash_BytesForBuckets(b) (sizeof(bucket_t*)*(b))
#define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
typedef struct bucket_s {
void *data;
union {
const char *string;
- int value;
+ unsigned int value;
} key;
struct bucket_s *next;
} bucket_t;
typedef struct hashtable_s {
- int numbuckets;
+ unsigned int numbuckets;
bucket_t **bucket;
} hashtable_t;
-void Hash_InitTable(hashtable_t *table, int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size))
-int Hash_Key(const char *name, int modulus);
+void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size))
+unsigned int Hash_Key(const char *name, unsigned int modulus);
void *Hash_Get(hashtable_t *table, const char *name);
void *Hash_GetInsensative(hashtable_t *table, const char *name);
-void *Hash_GetKey(hashtable_t *table, int key);
-void *Hash_GetNext(hashtable_t *table, char *name, void *old);
-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_Remove(hashtable_t *table, char *name);
-void Hash_RemoveData(hashtable_t *table, char *name, void *data);
-void Hash_RemoveKey(hashtable_t *table, int key);
-void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck);
+void *Hash_GetKey(hashtable_t *table, unsigned int key);
+void *Hash_GetNext(hashtable_t *table, const char *name, void *old);
+void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old);
+void *Hash_GetNextKey(hashtable_t *table, unsigned int key, void *old);
+void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck);
+void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck);
+void Hash_Remove(hashtable_t *table, const char *name);
+void Hash_RemoveData(hashtable_t *table, const char *name, void *data);
+void Hash_RemoveKey(hashtable_t *table, unsigned int key);
+void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck);
#endif
unsigned int i;
edictrun_t *e;
-// int a;
-#ifdef QCJIT
- prinst->usejit = true;
-#endif
-
max_fields_size=0;
fields_size = 0;
progfuncs->stringtable = 0;
{
ddef16_t *var16;
ddef32_t *var32;
- switch(pr_progstate[pnum].intsize)
+ switch(pr_progstate[pnum].structtype)
{
- case 24:
- case 16:
+ case PST_KKQWSV:
+ case PST_DEFAULT:
var16 = ED_FindTypeGlobalFromProgs16(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
if (!var16)
return (f - pr_progstate[pnum].functions) | (pnum << 24);
- return *(int *)&pr_progstate[pnum].globals[var16->ofs];
- case 32:
+ return *(int *)&pr_progstate[pnum].globals[var16->ofs];
+ case PST_QTEST:
+ case PST_FTE32:
var32 = ED_FindTypeGlobalFromProgs32(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
if (!var32)
return (f - pr_progstate[pnum].functions) | (pnum << 24);
return 0;
}
-eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum)
+void QC_FindPrefixedGlobals(progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) )
+{
+ unsigned int i;
+ ddef16_t *def16;
+ ddef32_t *def32;
+ int len = strlen(prefix);
+ unsigned int pnum;
+
+ for (pnum = 0; pnum < maxprogs; pnum++)
+ {
+ if (!pr_progstate[pnum].progs)
+ continue;
+
+ switch(pr_progstate[pnum].structtype)
+ {
+ case PST_DEFAULT:
+ case PST_KKQWSV:
+ for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
+ {
+ def16 = &pr_progstate[pnum].globaldefs16[i];
+ if (!strncmp(def16->s_name+progfuncs->stringtable,prefix, len))
+ found(progfuncs, def16->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type);
+ }
+ break;
+ case PST_QTEST:
+ case PST_FTE32:
+ for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
+ {
+ def32 = &pr_progstate[pnum].globaldefs32[i];
+ if (!strncmp(def32->s_name+progfuncs->stringtable,prefix, len))
+ found(progfuncs, def32->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type);
+ }
+ break;
+ }
+ }
+}
+
+eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum, etype_t *type)
{
unsigned int i;
ddef16_t *var16;
{
if (!pr_progstate[i].progs)
continue;
- ev = PR_FindGlobal(progfuncs, globname, i);
+ ev = PR_FindGlobal(progfuncs, globname, i, type);
if (ev)
return ev;
}
}
if (pnum < 0 || (unsigned)pnum >= maxprogs || !pr_progstate[pnum].progs)
return NULL;
- switch(pr_progstate[pnum].intsize)
+ switch(pr_progstate[pnum].structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
if (!(var16 = ED_FindGlobalFromProgs16(progfuncs, globname, pnum)))
return NULL;
+ if (type)
+ *type = var16->type;
return (eval_t *)&pr_progstate[pnum].globals[var16->ofs];
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
if (!(var32 = ED_FindGlobalFromProgs32(progfuncs, globname, pnum)))
return NULL;
+ if (type)
+ *type = var32->type;
return (eval_t *)&pr_progstate[pnum].globals[var32->ofs];
}
Sys_Error("Error with def size (PR_FindGlobal)");
if (G_STRING(OFS_PARM0+i*3))
{
s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable;
+ if (strlen(out) + strlen(s) + 1 >= sizeof(out))
+ return out;
strcat (out, s);
-
-//#ifdef PARANOID
- if (strlen(out)+1 >= sizeof(out))
- Sys_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(out));
-//#endif
}
}
return out;
return NULL;
}
-char *PR_StringToNative (progfuncs_t *progfuncs, string_t str)
+char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str)
{
if ((unsigned int)str & 0xc0000000)
{
PR_StringToNative,
0,
PR_QueryField,
- QC_ClearEdict
+ QC_ClearEdict,
+ QC_FindPrefixedGlobals
};
#undef printf
//used when loading a game
NULL, //builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
NULL, //void (*loadcompleate) (int edictsize); //notification to reset any pointers.
+ NULL,
(void*)malloc, //void *(*memalloc) (int size); //small string allocation malloced and freed randomly by the executor. (use memalloc if you want)
free, //void (*memfree) (void * mem);
free(inst->addressablehunk);
#endif
+ if (inst->prinst->allocedstrings)
+ f(inst->prinst->allocedstrings);
+ inst->prinst->allocedstrings = NULL;
+ if (inst->prinst->tempstrings)
+ f(inst->prinst->tempstrings);
+ inst->prinst->tempstrings = NULL;
+
+
/*
while(inst->prinst->extensionbuiltin)
{
#define RESERVED_OFS 28
-enum {
+enum qcop_e {
OP_DONE, //0
OP_MUL_F,
OP_MUL_V,
OP_NE_E,
OP_NE_FNC,
- OP_LE, //20
- OP_GE,
- OP_LT,
- OP_GT,
+ OP_LE_F, //20
+ OP_GE_F,
+ OP_LT_F,
+ OP_GT_F,
OP_LOAD_F,
OP_LOAD_V,
OP_NOT_S,
OP_NOT_ENT,
OP_NOT_FNC,
- OP_IF,
- OP_IFNOT, //50
+ OP_IF_I,
+ OP_IFNOT_I, //50
OP_CALL0, //careful... hexen2 and q1 have different calling conventions
OP_CALL1, //remap hexen2 calls to OP_CALL2H
OP_CALL2,
OP_CALL8,
OP_STATE, //60
OP_GOTO,
- OP_AND,
- OP_OR,
+ OP_AND_F,
+ OP_OR_F,
- OP_BITAND,
- OP_BITOR,
+ OP_BITAND_F,
+ OP_BITOR_F,
//these following ones are Hexen 2 constants.
OP_ADD_I,
OP_ADD_FI,
- OP_ADD_IF, //110
+ OP_ADD_IF,
OP_SUB_I,
- OP_SUB_FI,
+ OP_SUB_FI, //120
OP_SUB_IF,
OP_CONV_ITOF,
OP_CP_FTOI,
OP_LOAD_I,
OP_STOREP_I,
- OP_STOREP_IF, //120
+ OP_STOREP_IF,
OP_STOREP_FI,
- OP_BITAND_I,
+ OP_BITAND_I, //130
OP_BITOR_I,
OP_MUL_I,
OP_IFNOT_S,
OP_IF_S,
- OP_NOT_I, //130
+ OP_NOT_I,
OP_DIV_VF,
- OP_XOR_I,
+ OP_XOR_I, //140
OP_RSHIFT_I,
OP_LSHIFT_I,
OP_LOADA_F,
OP_LOADA_V,
OP_LOADA_S,
- OP_LOADA_ENT, //140
- OP_LOADA_FLD,
- OP_LOADA_FNC,
+ OP_LOADA_ENT,
+ OP_LOADA_FLD,
+ OP_LOADA_FNC, //150
OP_LOADA_I,
OP_STORE_P, //152... erm.. wait...
OP_LOADP_V,
OP_LOADP_S,
OP_LOADP_ENT,
- OP_LOADP_FLD, //150
+ OP_LOADP_FLD,
OP_LOADP_FNC,
- OP_LOADP_I,
+ OP_LOADP_I, //160
OP_LE_I,
OP_GE_I,
OP_LE_IF,
OP_GE_IF,
OP_LT_IF,
- OP_GT_IF, //160
+ OP_GT_IF,
OP_LE_FI,
- OP_GE_FI,
+ OP_GE_FI, //170
OP_LT_FI,
OP_GT_FI,
OP_ADD_SF, //(char*)c = (char*)a + (float)b
OP_SUB_S, //(float)c = (char*)a - (char*)b
OP_STOREP_C,//(float)c = *(char*)b = (float)a
- OP_LOADP_C, //(float)c = *(char*) //170
+ OP_LOADP_C, //(float)c = *(char*)
//-------------------------------------
OP_MUL_IF,
- OP_MUL_FI,
+ OP_MUL_FI, //180
OP_MUL_VI,
OP_MUL_IV,
OP_DIV_IF,
OP_BITAND_IF,
OP_BITOR_IF,
OP_BITAND_FI,
- OP_BITOR_FI, //180
+ OP_BITOR_FI,
OP_AND_I,
- OP_OR_I,
+ OP_OR_I, //190
OP_AND_IF,
OP_OR_IF,
OP_AND_FI,
//erm... FTEQCC doesn't make use of these... These are for DP.
OP_GSTOREP_I,
- OP_GSTOREP_F, //190
+ OP_GSTOREP_F,
OP_GSTOREP_ENT,
- OP_GSTOREP_FLD, // integers
+ OP_GSTOREP_FLD, // integers //200
OP_GSTOREP_S,
OP_GSTOREP_FNC, // pointers
OP_GSTOREP_V,
OP_GLOAD_I,
OP_GLOAD_F,
OP_GLOAD_FLD,
- OP_GLOAD_ENT, //200
+ OP_GLOAD_ENT,
OP_GLOAD_S,
- OP_GLOAD_FNC,
+ OP_GLOAD_FNC, //210
OP_BOUNDCHECK,
//back to ones that we do use.
These ops are emulated out, always, and are only present in the compiler.
*/
- OP_BITSET_I,
+ OP_BITSET_I, //220
OP_BITSETP_I,
OP_MULSTORE_I,
OP_ADDSTOREP_I,
OP_SUBSTOREP_I,
- OP_MULSTORE_IF,
+ OP_MULSTORE_IF, //230
OP_MULSTOREP_IF,
OP_DIVSTORE_IF,
OP_DIVSTOREP_IF,
OP_MULSTORE_FI,
OP_MULSTOREP_FI,
- OP_DIVSTORE_FI,
+ OP_DIVSTORE_FI, //240
OP_DIVSTOREP_FI,
OP_ADDSTORE_FI,
OP_ADDSTOREP_FI,
OP_SUBSTORE_FI,
OP_SUBSTOREP_FI,
- OP_NUMOPS
+ OP_NUMOPS //246
};
+#define MAX_PARMS 8
+
+// qtest structs (used for reordering and not execution)
+typedef struct qtest_statement_s
+{
+ unsigned int line; // line number in source code file
+ unsigned short op;
+ unsigned short a,b,c;
+} qtest_statement_t;
+
+typedef struct qtest_def_s
+{
+ unsigned int type; // no DEFGLOBAL found in qtest progs
+ unsigned int s_name; // different order!
+ unsigned int ofs;
+} qtest_def_t;
+
+typedef struct qtest_function_s
+{
+ int first_statement;
+ int unused1;
+ int locals; // assumed! (always 0 in real qtest progs)
+ int profile; // assumed! (always 0 in real qtest progs)
+
+ int s_name;
+ int s_file;
+
+ int numparms;
+ int parm_start; // different order
+ int parm_size[MAX_PARMS]; // ints instead of bytes...
+} qtest_function_t;
#ifndef COMPILER
typedef struct statement16_s
#define DEF_SAVEGLOBAL (1<<15)
#define DEF_SHARED (1<<14)
-#define MAX_PARMS 8
-
#ifndef COMPILER
typedef struct
{
} QCC_dfunction_t;
#endif
-
+#define PROG_QTESTVERSION 3
#define PROG_VERSION 6
#define PROG_KKQWSVVERSION 7
#define PROG_EXTENDEDVERSION 7
int secondaryversion; //Constant - to say that any version 7 progs are actually ours, not someone else's alterations.
} dprograms_t;
-#define standard_dprograms_t_size ((int)&((dprograms_t*)NULL)->ofsfiles)
+#define standard_dprograms_t_size ((size_t)&((dprograms_t*)NULL)->ofsfiles)
#endif
int ofs; //inside a structure.
int size;
- char *name;
+ string_t name;
} typeinfo_t;
{
ddef16_t *d16;
ddef32_t *d32;
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 24:
- case 16:
+ case PST_KKQWSV:
+ case PST_DEFAULT:
d16 = ED_FindGlobal16(progfuncs, name);
return d16?d16->ofs:0;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
d32 = ED_FindGlobal32(progfuncs, name);
return d32?d32->ofs:0;
}
- Sys_Error("ED_FindGlobalOfs - bad intsize");
+ Sys_Error("ED_FindGlobalOfs - bad struct type");
return 0;
}
ddef16_t *def16;
ddef32_t *def32;
static unsigned int pos;
- switch(pr_progstate[prnum].intsize)
+ switch(pr_progstate[prnum].structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
def16 = ED_FindTypeGlobalFromProgs16(progfuncs, name, prnum, type);
if (!def16)
return NULL;
pos = def16->ofs;
return &pos;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
def32 = ED_FindTypeGlobalFromProgs32(progfuncs, name, prnum, type);
if (!def32)
return NULL;
return &def32->ofs;
}
- Sys_Error("ED_FindGlobalOfsFromProgs - bad intsize");
+ Sys_Error("ED_FindGlobalOfsFromProgs - bad struct type");
return 0;
}
sprintf (line, "%s", PR_StringToNative(progfuncs, val->string));
break;
case ev_entity:
- sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) );
+ fielddef = ED_FindField(progfuncs, "classname");
+ if (fielddef && val->edict < sv_num_edicts)
+ {
+ edictrun_t *ed;
+ string_t *v;
+ ed = (edictrun_t *)EDICT_NUM(progfuncs, val->edict);
+ v = (string_t *)((char *)edvars(ed) + fielddef->ofs*4);
+ sprintf (line, "entity %i(%s)", val->edict, PR_StringToNative(progfuncs, *v));
+ }
+ else
+ sprintf (line, "entity %i", val->edict);
break;
case ev_function:
if (!val->function)
sprintf (line, "Bad function");
else
{
- f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000);
- sprintf (line, "%i:%s()", (val->function & 0xff000000)>>24, f->s_name+progfuncs->stringtable);
+ if ((val->function &~0xff000000) >= pr_progs->numfunctions)
+ sprintf(line, "bad function %i:%i\n", (val->function & 0xff000000)>>24, val->function & ~0xff000000);
+ else
+ {
+ f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000);
+ sprintf (line, "%i:%s()", (val->function & 0xff000000)>>24, f->s_name+progfuncs->stringtable);
+ }
}
}
break;
void *val;
static char line[128];
- switch (current_progstate->intsize)
+ switch (current_progstate->structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
val = (void *)&pr_globals[ofs];
def16 = ED_GlobalAtOfs16(progfuncs, ofs);
if (!def16)
strcat (line," ");
strcat (line," ");
return line;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
val = (void *)&pr_globals[ofs];
def32 = ED_GlobalAtOfs32(progfuncs, ofs);
if (!def32)
strcat (line," ");
return line;
}
- Sys_Error("Bad offset size in PR_GlobalString");
+ Sys_Error("Bad struct type in PR_GlobalString");
return "";
}
ddef32_t *def32;
static char line[128];
- switch (current_progstate->intsize)
+ switch (current_progstate->structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
def16 = ED_GlobalAtOfs16(progfuncs, ofs);
if (!def16)
sprintf (line,"%i(?""?""?)", ofs);
else
sprintf (line,"%i(%s)", ofs, def16->s_name+progfuncs->stringtable);
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
def32 = ED_GlobalAtOfs32(progfuncs, ofs);
if (!def32)
sprintf (line,"%i(?""?""?)", ofs);
sprintf (line,"%i(%s)", ofs, def32->s_name+progfuncs->stringtable);
break;
default:
- Sys_Error("Bad offset size in PR_GlobalStringNoContents");
+ Sys_Error("Bad struct type in PR_GlobalStringNoContents");
}
i = strlen(line);
returns false if error
=============
*/
-pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits)
+pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int structtype)
{
int i;
char string[128];
string_t st;
dfunction_t *func;
- int type;
+ int type = 0; // warning about beign used without initializing it
- switch(bits)
+ switch(structtype)
{
- case 16:
+ case PST_DEFAULT:
d = (void *)((int *)base + ((ddef16_t*)key)->ofs);
if (pr_types)
else
type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL;
break;
- case 32:
+ case PST_FTE32:
d = (void *)((int *)base + ((ddef32_t*)key)->ofs);
if (pr_types)
type = ((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL;
break;
default:
- Sys_Error("Bad bits in ED_ParseEpair");
+ Sys_Error("Bad struct type in ED_ParseEpair");
d = 0;
}
{
while (*v && *v != ' ')
v++;
- *v = 0;
- ((float *)d)[i] = (float)atof (w);
- w = v = v+1;
+ if (!*v)
+ {
+ ((float *)d)[i] = (float)atof (w);
+ w = v;
+ }
+ else
+ {
+ *v = 0;
+ ((float *)d)[i] = (float)atof (w);
+ w = v = v+1;
+ }
}
break;
pbool init;
char keyname[256];
int n;
+ int nest = 1;
// eval_t *val;
// parse key
data = QCC_COM_Parse (data);
if (qcc_token[0] == '}')
+ {
+ if (--nest)
+ continue;
break;
+ }
+ if (qcc_token[0] == '{' && !qcc_token[1])
+ nest++;
if (!data)
{
printf ("ED_ParseEntity: EOF without closing brace\n");
return NULL;
}
+ if (nest > 1)
+ continue;
strncpy (keyname, qcc_token, sizeof(keyname)-1);
keyname[sizeof(keyname)-1] = 0;
if (!data)
{
printf ("ED_ParseEntity: EOF without closing brace\n");
- return NULL;
+ return NULL;
}
if (qcc_token[0] == '}')
if (!strcmp(keyname, "light")) //Quake lighthack - allows a field name and a classname to go by the same thing in the level editor
if ((key = ED_FindField (progfuncs, "light_lev")))
goto cont;
+ if (externs->badfield && externs->badfield(progfuncs, (struct edict_s*)ent, keyname, qcc_token))
+ continue;
printf ("'%s' is not a field\n", keyname);
continue;
}
cont:
- if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, 32))
+ if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, PST_FTE32))
{
continue;
// Sys_Error ("ED_ParseEdict: parse error on entities");
int type;
int curprogs = pr_typecurrent;
int len;
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
def16 = &pr_globaldefs16[i];
AddS (qcva("\"%s\"\n", PR_UglyValueString(progfuncs, def16->type&~DEF_SAVEGLOBAL, (eval_t *)v)));
}
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
def32 = &pr_globaldefs32[i];
}
break;
default:
- Sys_Error("Bad number of bits in SaveEnts");
+ Sys_Error("Bad struct type in SaveEnts");
}
return buffer;
file = QCC_COM_Parse(file);
if (file == NULL)
break; //finished reading file
+ else if (!strcmp(qcc_token, "Version"))
+ {
+ file = QCC_COM_Parse(file);
+ //qcc_token is a version number
+ }
else if (!strcmp(qcc_token, "entity"))
{
if (entsize == 0 && resethunk) //edicts have not yet been initialized, and this is a compleate load (memsize has been set)
else if (!qcc_token[0] || !file)
Sys_Error("EOF when parsing global values");
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
if (!(d16 = ED_FindGlobal16(progfuncs, qcc_token)))
{
file = QCC_COM_Parse(file);
else
{
file = QCC_COM_Parse(file);
- ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, 16);
+ ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
}
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
if (!(d32 = ED_FindGlobal32(progfuncs, qcc_token)))
{
file = QCC_COM_Parse(file);
else
{
file = QCC_COM_Parse(file);
- ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, 32);
+ ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32);
}
break;
default:
- Sys_Error("Bad intsize in LoadEnts");
+ Sys_Error("Bad struct type in LoadEnts");
}
}
else if (!qcc_token[0] || !file)
Sys_Error("EOF when parsing global values");
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
if (!(d16 = ED_FindGlobal16(progfuncs, qcc_token)))
{
file = QCC_COM_Parse(file);
else
{
file = QCC_COM_Parse(file);
- ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, 16);
+ ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
}
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
if (!(d32 = ED_FindGlobal32(progfuncs, qcc_token)))
{
file = QCC_COM_Parse(file);
else
{
file = QCC_COM_Parse(file);
- ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, 32);
+ ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32);
}
break;
default:
- Sys_Error("Bad intsize in LoadEnts");
+ Sys_Error("Bad struct type in LoadEnts");
}
}
}
if (pr_progs->version == PROG_VERSION)
{
// printf("Opening standard progs file \"%s\"\n", filename);
- current_progstate->intsize = 16;
+ current_progstate->structtype = PST_DEFAULT;
+ }
+ else if (pr_progs->version == PROG_QTESTVERSION)
+ {
+ current_progstate->structtype = PST_QTEST;
}
else if (pr_progs->version == PROG_EXTENDEDVERSION)
{
if (pr_progs->secondaryversion == PROG_SECONDARYVERSION16)
{
// printf("Opening 16bit fte progs file \"%s\"\n", filename);
- current_progstate->intsize = 16;
+ current_progstate->structtype = PST_DEFAULT;
}
else if (pr_progs->secondaryversion == PROG_SECONDARYVERSION32)
{
// printf("Opening 32bit fte progs file \"%s\"\n", filename);
- current_progstate->intsize = 32;
+ current_progstate->structtype = PST_FTE32;
}
else
{
// printf("Opening KK7 progs file \"%s\"\n", filename);
- current_progstate->intsize = 24; //KK progs. Yuck. Disabling saving would be a VERY good idea.
+ current_progstate->structtype = PST_KKQWSV; //KK progs. Yuck. Disabling saving would be a VERY good idea.
pr_progs->version = PROG_VERSION; //not fte.
}
/* else
//start decompressing stuff...
if (pr_progs->blockscompressed & 1) //statements
{
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
+ case PST_DEFAULT:
len=sizeof(dstatement16_t)*pr_progs->numstatements;
break;
- case 32:
+ case PST_FTE32:
len=sizeof(dstatement32_t)*pr_progs->numstatements;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad struct type");
}
s = PRHunkAlloc(progfuncs, len);
QC_decode(progfuncs, PRLittleLong(*(int *)pr_statements16), len, 2, (char *)(((int *)pr_statements16)+1), s);
}
if (pr_progs->blockscompressed & 2) //global defs
{
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
+ case PST_DEFAULT:
len=sizeof(ddef16_t)*pr_progs->numglobaldefs;
break;
- case 32:
+ case PST_FTE32:
len=sizeof(ddef32_t)*pr_progs->numglobaldefs;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad struct type");
}
s = PRHunkAlloc(progfuncs, len);
QC_decode(progfuncs, PRLittleLong(*(int *)pr_globaldefs16), len, 2, (char *)(((int *)pr_globaldefs16)+1), s);
}
if (pr_progs->blockscompressed & 4) //fields
{
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
+ case PST_DEFAULT:
len=sizeof(ddef16_t)*pr_progs->numglobaldefs;
break;
- case 32:
+ case PST_FTE32:
len=sizeof(ddef32_t)*pr_progs->numglobaldefs;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad struct type");
}
s = PRHunkAlloc(progfuncs, len);
QC_decode(progfuncs, PRLittleLong(*(int *)pr_fielddefs16), len, 2, (char *)(((int *)pr_fielddefs16)+1), s);
current_progstate->edict_size = pr_progs->entityfields * 4 + externs->edictsize;
// byte swap the lumps
- for (i=0 ; i<pr_progs->numfunctions; i++)
+ switch(current_progstate->structtype)
{
+ case PST_QTEST:
+ // qtest needs a struct remap
+ for (i=0 ; i<pr_progs->numfunctions; i++)
+ {
+ int j;
+ qtest_function_t qtfunc = ((qtest_function_t*)fnc)[i];
+
+ fnc[i].first_statement = PRLittleLong (qtfunc.first_statement);
+ fnc[i].parm_start = PRLittleLong (qtfunc.parm_start);
+ fnc[i].s_name = (string_t)PRLittleLong (qtfunc.s_name);
+ fnc[i].s_file = (string_t)PRLittleLong (qtfunc.s_file);
+ fnc[i].numparms = PRLittleLong (qtfunc.numparms);
+ fnc[i].locals = PRLittleLong (qtfunc.locals);
+
+ for (j=0; j<MAX_PARMS;j++)
+ fnc[i].parm_size[j] = PRLittleLong (qtfunc.parm_size[j]);
+
+ fnc[i].s_name += stringadjust;
+ fnc[i].s_file += stringadjust;
+ }
+ break;
+ case PST_KKQWSV:
+ case PST_DEFAULT:
+ case PST_FTE32:
+ for (i=0 ; i<pr_progs->numfunctions; i++)
+ {
#ifndef NOENDIAN
- fnc[i].first_statement = PRLittleLong (fnc[i].first_statement);
- fnc[i].parm_start = PRLittleLong (fnc[i].parm_start);
- fnc[i].s_name = (string_t)PRLittleLong ((long)fnc[i].s_name);
- fnc[i].s_file = (string_t)PRLittleLong ((long)fnc[i].s_file);
- fnc[i].numparms = PRLittleLong (fnc[i].numparms);
- fnc[i].locals = PRLittleLong (fnc[i].locals);
+ fnc[i].first_statement = PRLittleLong (fnc[i].first_statement);
+ fnc[i].parm_start = PRLittleLong (fnc[i].parm_start);
+ fnc[i].s_name = (string_t)PRLittleLong ((long)fnc[i].s_name);
+ fnc[i].s_file = (string_t)PRLittleLong ((long)fnc[i].s_file);
+ fnc[i].numparms = PRLittleLong (fnc[i].numparms);
+ fnc[i].locals = PRLittleLong (fnc[i].locals);
#endif
-/* if (!strncmp(fnc[i].s_name+pr_strings, "ext_", 4))
- {
- for (eb = extensionbuiltin; eb; eb = eb->prev)
- {
- if (*eb->name == '_')
- {
- if (!strncmp(fnc[i].s_name+pr_strings+4, eb->name+1, strlen(eb->name+1)))
- {
- fnc[i].first_statement = -0x7fffffff;
- *(void**)&fnc[i].profile = (void*)eb->func;
- break;
- }
- }
- else if (!strcmp(fnc[i].s_name+4, eb->name))
- {
- fnc[i].first_statement = -0x7fffffff;
- *(void**)&fnc[i].profile = (void*)eb->func;
- break;
- }
- }
+ fnc[i].s_name += stringadjust;
+ fnc[i].s_file += stringadjust;
}
-*/
- fnc[i].s_name += stringadjust;
- fnc[i].s_file += stringadjust;
+ break;
+ default:
+ Sys_Error("Bad struct type");
}
//actual global values
pr_types[i].num_parms = PRLittleLong(current_progstate->types[i].num_parms);
pr_types[i].ofs = PRLittleLong(current_progstate->types[i].ofs);
pr_types[i].size = PRLittleLong(current_progstate->types[i].size);
- pr_types[i].name = (char *)PRLittleLong((long)current_progstate->types[i].name);
+ pr_types[i].name = PRLittleLong(current_progstate->types[i].name);
#endif
pr_types[i].name += stringadjust;
}
reorg = (headercrc != -1);
QC_FlushProgsOffsets(progfuncs);
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 24:
- case 16:
+ case PST_KKQWSV:
+ case PST_DEFAULT:
//byteswap the globals and fix name offsets
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
}
break;
- case 32:
+ case PST_QTEST:
+ // qtest needs a struct remap
+ for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+ {
+ qtest_def_t qtdef = ((qtest_def_t *)pr_globaldefs32)[i];
+
+ pr_globaldefs32[i].type = qtdef.type;
+ pr_globaldefs32[i].s_name = qtdef.s_name;
+ pr_globaldefs32[i].ofs = qtdef.ofs;
+ }
+ for (i=0 ; i<pr_progs->numfielddefs ; i++)
+ {
+ qtest_def_t qtdef = ((qtest_def_t *)pr_fielddefs32)[i];
+
+ pr_fielddefs32[i].type = qtdef.type;
+ pr_fielddefs32[i].s_name = qtdef.s_name;
+ pr_fielddefs32[i].ofs = qtdef.ofs;
+ }
+ // passthrough
+ case PST_FTE32:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
#ifndef NOENDIAN
else
type = pr_fielddefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
if (progfuncs->fieldadjust && !pr_typecurrent) //we need to make sure all fields appear in their original place.
- QC_RegisterFieldVar(progfuncs, type, fld16[i].s_name+pr_strings, 4*(fld16[i].ofs+progfuncs->fieldadjust), -1);
+ QC_RegisterFieldVar(progfuncs, type, pr_fielddefs32[i].s_name+pr_strings, 4*(pr_fielddefs32[i].ofs+progfuncs->fieldadjust), -1);
else if (type == ev_vector)
QC_RegisterFieldVar(progfuncs, type, pr_fielddefs32[i].s_name+pr_strings, -1, pr_fielddefs32[i].ofs);
}
}
break;
default:
- Sys_Error("Bad int size");
+ Sys_Error("Bad struct type");
}
//ifstring fixes arn't performed anymore.
//the following switch just fixes endian and hexen2 calling conventions (by using different opcodes).
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
+ case PST_QTEST:
+ for (i=0 ; i<pr_progs->numstatements ; i++)
+ {
+ qtest_statement_t qtst = ((qtest_statement_t*)st16)[i];
+
+ st16[i].op = PRLittleShort(qtst.op);
+ st16[i].a = PRLittleShort(qtst.a);
+ st16[i].b = PRLittleShort(qtst.b);
+ st16[i].c = PRLittleShort(qtst.c);
+ // could use the line info as lno information maybe? is it really worth it?
+ // also never assuming h2 calling mechanism
+ }
+ break;
+ case PST_DEFAULT:
for (i=0 ; i<pr_progs->numstatements ; i++)
{
#ifndef NOENDIAN
if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8)
{
if (st16[i].b)
+ {
hexencalling = true;
-
+ break;
+ }
}
}
if (hexencalling)
}
break;
- case 24: //24 sucks. Guess why.
- for (i=0 ; i<pr_progs->numstatements ; i++)
- {
-#ifndef NOENDIAN
- pr_statements32[i].op = PRLittleLong(pr_statements32[i].op);
- pr_statements32[i].a = PRLittleLong(pr_statements32[i].a);
- pr_statements32[i].b = PRLittleLong(pr_statements32[i].b);
- pr_statements32[i].c = PRLittleLong(pr_statements32[i].c);
-#endif
- if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
- {
- if (pr_statements32[i].b)
- hexencalling = true;
-
- }
- }
- if (hexencalling)
- {
- for (i=0 ; i<pr_progs->numstatements ; i++)
- {
- if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
- pr_statements32[i].op += OP_CALL1H - OP_CALL1;
- }
- }
- break;
- case 32:
+ case PST_KKQWSV: //24 sucks. Guess why.
+ case PST_FTE32:
for (i=0 ; i<pr_progs->numstatements ; i++)
{
#ifndef NOENDIAN
if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
{
if (pr_statements32[i].b)
+ {
hexencalling = true;
-
+ break;
+ }
}
}
if (hexencalling)
if (headercrc == -1)
{
isfriked = true;
- if (current_progstate->intsize != 16)
+ if (current_progstate->structtype != PST_DEFAULT)
Sys_Error("Decompiling a bigprogs");
return true;
}
isfriked = -1; //partly to avoid some bad progs.
// len = 0;
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 24:
- case 16:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
if (pr_types)
}
}
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
for (i=0 ; i<pr_progs->numglobaldefs ; i++)
{
if (pr_types)
}
break;
default:
- Sys_Error("Bad int size");
+ Sys_Error("Bad struct type");
}
if ((isfriked && pr_typecurrent)) //friked progs only allow one file.
if (progfuncs->stringtablesize + progfuncs->stringtable < pr_strings + pr_progs->numstrings)
progfuncs->stringtablesize = (pr_strings + pr_progs->numstrings) - progfuncs->stringtable;
- eval = PR_FindGlobal(progfuncs, "thisprogs", progstype);
+ eval = PR_FindGlobal(progfuncs, "thisprogs", progstype, NULL);
if (eval)
eval->prog = progstype;
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
+ case PST_DEFAULT:
if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->numbodylessfuncs)
{
s = &((char *)pr_progs)[pr_progs->ofsbodylessfuncs];
}
}
break;
- case 24:
+ case PST_QTEST:
+ case PST_KKQWSV:
break; //cannot happen anyway.
- case 32:
+ case PST_FTE32:
if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->numbodylessfuncs)
{
s = &((char *)pr_progs)[pr_progs->ofsbodylessfuncs];
break;
}
- eval = PR_FindGlobal(progfuncs, "__ext__fasttrackarrays", PR_CURRENT);
+ eval = PR_FindGlobal(progfuncs, "__ext__fasttrackarrays", PR_CURRENT, NULL);
if (eval) //we support these opcodes
eval->_float = true;
#define Host_Error Sys_Error
+// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
+#ifdef _WIN32
+ #if (_MSC_VER >= 1400)
+ //with MSVC 8, use MS extensions
+ #define snprintf linuxlike_snprintf_vc8
+ int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
+ #else
+ //msvc crap
+ #define snprintf linuxlike_snprintf
+ int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf linuxlike_vsnprintf
+ int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
+ #endif
+#endif
+
//=============================================================================
for ( ; i<10 ; i++)
printf (" ");
}
-
+
if (s->op == OP_IF || s->op == OP_IFNOT)
printf ("%sbranch %i",PR_GlobalString(progfuncs, s->a),s->b);
else if (s->op == OP_GOTO)
int *globalbase;
#endif
progs = -1;
-
+
if (pr_depth == 0)
{
printf ("<NO STACK>\n");
return;
}
-
+
#ifdef STACKTRACE
globalbase = (int *)pr_globals + pr_xfunction->parm_start - pr_xfunction->locals;
#endif
for (i=pr_depth ; i>0 ; i--)
{
f = pr_stack[i].f;
-
+
if (!f)
{
printf ("<NO FUNCTION>\n");
printf ("\n");
//editbadfile(pr_strings + pr_xfunction->s_file, -1);
-
-// pr_depth = 0; // dump the stack so host_error can shutdown functions
+
+// pr_depth = 0; // dump the stack so host_error can shutdown functions
// prinst->exitdepth = 0;
Abort ("%s", string);
====================
*/
void PR_AbortStack (progfuncs_t *progfuncs);
-int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
+int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
{
int i, j, c, o;
pr_stack[pr_depth].s = pr_xstatement;
- pr_stack[pr_depth].f = pr_xfunction;
+ pr_stack[pr_depth].f = pr_xfunction;
pr_stack[pr_depth].progsnum = progsnum;
pr_stack[pr_depth].pushed = pr_spushed;
pr_depth++;
PR_LeaveFunction
====================
*/
-int PR_LeaveFunction (progfuncs_t *progfuncs)
+int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs)
{
int i, c;
ddef16_t *def16;
int i;
- switch (pr_progstate[pr_typecurrent].intsize)
+ switch (pr_progstate[pr_typecurrent].structtype)
{
- case 16:
- case 24:
+ case PST_DEFAULT:
+ case PST_KKQWSV:
//this gets parms fine, but not locals
if (pr_xfunction)
for (i = 0; i < pr_xfunction->numparms; i++)
def.s_name = def16->s_name;
def32 = &def;
break;
- case 32:
+ case PST_QTEST:
+ case PST_FTE32:
//this gets parms fine, but not locals
if (pr_xfunction)
for (i = 0; i < pr_xfunction->numparms; i++)
return NULL;
break;
default:
- Sys_Error("Bad int size in ED_FindLocalOrGlobal");
+ Sys_Error("Bad struct type in ED_FindLocalOrGlobal");
def32 = NULL;
}
-
+
*val = (eval_t *)&pr_progstate[pr_typecurrent].globals[def32->ofs];
return &def;
}
c = strchr(key, '.');
if (c) *c = '\0';
- def = ED_FindLocalOrGlobal(progfuncs, key, &val);
+ def = ED_FindLocalOrGlobal(progfuncs, key, &val);
if (!def)
{
if (atoi(key))
}
if (c) *c = '.';
if (!def)
- {
+ {
return "(Bad string)";
- }
+ }
type = def->type;
//go through ent vars
- c = strchr(key, '.');
+ c = strchr(key, '.');
while(c)
{
c2 = c+1;
if (c)*c = '.';
if (!fdef)
return "(Bad string)";
- val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4);
+ val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4);
type = fdef->type;
}
-
+
if (assignment)
{
assignment++;
case ev_string:
*(string_t *)val = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, assignment, 0));
break;
-
+
case ev_float:
*(float *)val = (float)atof (assignment);
break;
case ev_integer:
*(int *)val = atoi (assignment);
break;
-
+
/* case ev_vector:
strcpy (string, assignment);
v = string;
fdef = ED_FindField (progfuncs, assignment);
if (!fdef)
{
- int l,nl = strlen(assignment);
+ size_t l,nl = strlen(assignment);
strcpy(buf, "Can't find field ");
l = strlen(buf);
if (nl > sizeof(buf)-l-2)
func = ED_FindFunction (progfuncs, s, &i, progsnum);
if (!func)
{
- int l,nl = strlen(s);
+ size_t l,nl = strlen(s);
assignment[-1] = '=';
int snum;
dfunction_t *f = pr_xfunction;
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 16:
- for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++)
+ case PST_DEFAULT:
+ case PST_QTEST:
+ for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++)
{
if (pr_statements16[snum].op == OP_DONE)
return;
}
break;
- case 24:
- case 32:
- for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++)
+ case PST_KKQWSV:
+ case PST_FTE32:
+ for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++)
{
if (pr_statements32[snum].op == OP_DONE)
return;
}
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad struct type");
snum = 0;
}
debugstatement = snum;
unsigned int i;
int pn = pr_typecurrent;
dfunction_t *f;
- int op;
+ int op = 0; //warning about not being initialized before use
for (pn = 0; (unsigned)pn < maxprogs; pn++)
{
if ((unsigned int)pr_progstate[pn].linenums[i] > fl)
break;
- switch(pr_progstate[pn].intsize)
+ switch(pr_progstate[pn].structtype)
{
- case 16:
+ case PST_DEFAULT:
+ case PST_QTEST:
op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
break;
- case 24:
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad structtype");
op = 0;
}
switch (flag)
if (op & 0x8000)
return true;
}
- switch(pr_progstate[pn].intsize)
+ switch(pr_progstate[pn].structtype)
{
- case 16:
+ case PST_DEFAULT:
+ case PST_QTEST:
((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
break;
- case 24:
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad structtype");
op = 0;
- }
+ }
}
goto cont;
}
if (!strcmp(f->s_name+progfuncs->stringtable, filename))
{
i = f->first_statement;
- switch(pr_progstate[pn].intsize)
+ switch(pr_progstate[pn].structtype)
{
- case 16:
+ case PST_DEFAULT:
+ case PST_QTEST:
op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
break;
- case 24:
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad structtype");
}
switch (flag)
{
if (op & 0x8000)
return true;
}
- switch(pr_progstate[pn].intsize)
+ switch(pr_progstate[pn].structtype)
{
- case 16:
+ case PST_DEFAULT:
+ case PST_QTEST:
((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
break;
- case 24:
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
break;
default:
- Sys_Error("Bad intsize");
+ Sys_Error("Bad structtype");
}
break;
}
int pn = pr_typecurrent;
int i;
- dfunction_t *f = pr_xfunction;
+ dfunction_t *f = pr_xfunction;
if (f && pr_progstate[pn].linenums && externs->useeditor)
{
externs->useeditor(progfuncs, f->s_file+progfuncs->stringtable, -1, 0, NULL);
return statement;
}
-
+
return statement;
}
{
eval_t *t, *swtch=NULL;
- int swtchtype;
+ int swtchtype = 0; //warning about not being initialized before use
dstatement16_t *st16;
dstatement32_t *st32;
dfunction_t *newf;
prinst->continuestatement = -1;
#ifdef QCJIT
- if (prinst->usejit)
+ if (prinst->jit)
{
- PR_EnterJIT(progfuncs, s);
+ PR_EnterJIT(progfuncs, prinst->jit, s);
return;
}
#endif
restart: //jumped to when the progs might have changed.
glob = pr_globals;
- switch (current_progstate->intsize)
+ switch (current_progstate->structtype)
{
- case 16:
+ case PST_DEFAULT:
+ case PST_QTEST:
#define INTSIZE 16
st16 = &pr_statements16[s];
while (pr_trace)
#endif
#undef DEBUGABLE
}
-
+
while(1)
{
#include "execloop.h"
- }
+ }
#undef INTSIZE
Sys_Error("PR_ExecuteProgram - should be unreachable");
break;
- case 24:
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
#define INTSIZE 32
st32 = &pr_statements32[s];
while (pr_trace)
#endif
#undef DEBUGABLE
}
-
+
while(1)
{
#ifdef SEPARATEINCLUDES
#include "execloop.h"
#endif
}
-#undef INTSIZE
+#undef INTSIZE
Sys_Error("PR_ExecuteProgram - should be unreachable");
break;
default:
- Sys_Error("PR_ExecuteProgram - bad intsize");
+ Sys_Error("PR_ExecuteProgram - bad structtype");
}
}
int localsoffset, baselocalsoffset;
qcthread_t *thread = memalloc(sizeof(qcthread_t));
dfunction_t *f;
-
+
//copy out the functions stack.
for (i = 0,localsoffset=0; i < ed; i++)
{
baselocalsoffset = localsoffset;
for (i = ed; i < pr_depth; i++)
{
- thread->fstack[i-ed].fnum = pr_stack[i].f - pr_progstate[pr_stack[i].progsnum].functions;
+ thread->fstack[i-ed].fnum = pr_stack[i].f - pr_progstate[pr_stack[i].progsnum].functions;
thread->fstack[i-ed].progsnum = pr_stack[i].progsnum;
thread->fstack[i-ed].statement = pr_stack[i].s;
else
{
pr_stack[pr_depth].progsnum = thread->fstack[i].progsnum;
- pr_stack[pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum;
+ pr_stack[pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum;
pr_stack[pr_depth].s = thread->fstack[i].statement;
}
if (ls != thread->lstackused)
PR_RunError(progfuncs, "Thread stores incorrect locals count\n");
-
+
f = &pr_functions[fnum];
// thread->lstackused -= f->locals; //the current function is the odd one out.
{
current_progstate->builtins = builtins;
current_progstate->numbuiltins = numbuiltins;
+ if (a <= progfuncs->numprogs)
+ progfuncs->numprogs = a+1;
#ifdef QCJIT
- if (prinst->usejit)
- prinst->usejit = PR_GenerateJit(progfuncs);
+ prinst->jit = PR_GenerateJit(progfuncs);
#endif
if (oldtype>=0)
PR_SwitchProgs(progfuncs, oldtype);
//origionaloffs is used to track matching field offsets. fields with the same progs offset overlap
//note: we probably suffer from progs with renamed system globals.
-int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, int engineofs, int progsofs)
+int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, signed long engineofs, signed long progsofs)
{
// progstate_t *p;
// int pnum;
{
if (field[i].type != type)
{
- printf("Field type mismatch on \"%s\"\n", name);
+ printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type);
continue;
}
if (!progfuncs->fieldadjust && engineofs>=0)
}
}*/
if (engineofs&3)
- Sys_Error("field %s is %i&3", name, engineofs);
+ Sys_Error("field %s is %i&3", name, (int)engineofs);
field[fnum].ofs = ofs = engineofs/4;
}
else
}
*/
- switch(current_progstate->intsize)
+ switch(current_progstate->structtype)
{
- case 24:
- case 16:
+ case PST_KKQWSV:
+ case PST_DEFAULT:
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
return;
- case 32:
+ case PST_FTE32:
+ case PST_QTEST:
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
if (!strcmp(pr_fielddefs32[i].s_name+stringtable, pr_globaldefs32[num].s_name+stringtable))
instructions need to be chained. stuff that writes to C should be cacheable, etc. maybe we don't even need to do the write to C\r
it should also be possible to fold in eq+ifnot, so none of this silly storeing of floats in equality tests\r
\r
+ this means that we need to track which vars are cached and in what form: fpreg, ireg+floatasint, ireg+float.\r
+ certain qccx hacks can use fpu operations on ints, so do what the instruction says, rather than considering an add an add regardless of types.\r
+\r
+ OP_AND_F, OP_OR_F etc will generally result in ints, and we should be able to keep them as ints if they combine with other ints.\r
+\r
+ some instructions are jump sites. any cache must be flushed before the start of the instruction.\r
+ some variables are locals, and will only ever be written by a single instruction, then read by the following instruction. such temps do not need to be written, or are overwritten later in the function anyway.\r
+ such locals need to be calculated PER FUNCTION as (fte)qcc can overlap locals making multiple distinct locals on a single offset.\r
+\r
+ store locals on a proper stack instead of the current absurd mechanism.\r
+\r
eax - tmp\r
ebx - prinst->edicttable\r
ecx - tmp\r
edx - tmp\r
- esi - \r
+ esi - debug opcode number\r
edi - tmp (because its preserved by subfunctions\r
- ebp - \r
+ ebp -\r
\r
to use gas to provide binary opcodes:\r
vim -N blob.s && as blob.s && objdump.exe -d a.out\r
+\r
+\r
+ notable mods to test:\r
+ prydon gate, due to fpu mangling to carry values between maps\r
*/\r
\r
#define PROGSUSED\r
\r
static float ta, tb, nullfloat=0;\r
\r
-unsigned int *statementjumps; //[MAX_STATEMENTS*2]\r
-unsigned char **statementoffsets; //[MAX_STATEMENTS]\r
-unsigned int numjumps;\r
-unsigned char *code;\r
-unsigned int codesize;\r
-unsigned int jitstatements;\r
-\r
-void EmitByte(unsigned char byte)\r
+struct jitstate\r
{\r
- code[codesize++] = byte;\r
+ unsigned int *statementjumps; //[MAX_STATEMENTS*3]\r
+ unsigned char **statementoffsets; //[MAX_STATEMENTS]\r
+ unsigned int numjumps;\r
+ unsigned char *code;\r
+ unsigned int codesize;\r
+ unsigned int jitstatements;\r
+};\r
+\r
+static void EmitByte(struct jitstate *jit, unsigned char byte)\r
+{\r
+ jit->code[jit->codesize++] = byte;\r
}\r
-void Emit4Byte(unsigned int value)\r
+static void Emit4Byte(struct jitstate *jit, unsigned int value)\r
{\r
- code[codesize++] = (value>> 0)&0xff;\r
- code[codesize++] = (value>> 8)&0xff;\r
- code[codesize++] = (value>>16)&0xff;\r
- code[codesize++] = (value>>24)&0xff;\r
+ jit->code[jit->codesize++] = (value>> 0)&0xff;\r
+ jit->code[jit->codesize++] = (value>> 8)&0xff;\r
+ jit->code[jit->codesize++] = (value>>16)&0xff;\r
+ jit->code[jit->codesize++] = (value>>24)&0xff;\r
}\r
-void EmitAdr(void *value)\r
+static void EmitAdr(struct jitstate *jit, void *value)\r
{\r
- Emit4Byte((unsigned int)value);\r
+ Emit4Byte(jit, (unsigned int)value);\r
}\r
-void EmitFloat(float value)\r
+static void EmitFloat(struct jitstate *jit, float value)\r
{\r
union {float f; unsigned int i;} u;\r
u.f = value;\r
- Emit4Byte(u.i);\r
+ Emit4Byte(jit, u.i);\r
}\r
-void Emit2Byte(unsigned short value)\r
+static void Emit2Byte(struct jitstate *jit, unsigned short value)\r
{\r
- code[codesize++] = (value>> 0)&0xff;\r
- code[codesize++] = (value>> 8)&0xff;\r
+ jit->code[jit->codesize++] = (value>> 0)&0xff;\r
+ jit->code[jit->codesize++] = (value>> 8)&0xff;\r
}\r
\r
-void EmitFOffset(void *func, int bias)\r
+static void EmitFOffset(struct jitstate *jit, void *func, int bias)\r
{\r
union {void *f; unsigned int i;} u;\r
u.f = func;\r
- u.i -= (unsigned int)&code[codesize+bias];\r
- Emit4Byte(u.i);\r
+ u.i -= (unsigned int)&jit->code[jit->codesize+bias];\r
+ Emit4Byte(jit, u.i);\r
}\r
\r
-void Emit4ByteJump(int statementnum, int offset)\r
+static void Emit4ByteJump(struct jitstate *jit, int statementnum, int offset)\r
{\r
- statementjumps[numjumps++] = codesize;\r
- statementjumps[numjumps++] = statementnum;\r
- statementjumps[numjumps++] = offset;\r
+ jit->statementjumps[jit->numjumps++] = jit->codesize;\r
+ jit->statementjumps[jit->numjumps++] = statementnum;\r
+ jit->statementjumps[jit->numjumps++] = offset;\r
\r
//the offset is filled in later\r
- codesize += 4;\r
+ jit->codesize += 4;\r
}\r
\r
-void FixupJumps(void)\r
+enum\r
+{\r
+ REG_EAX,\r
+ REG_ECX,\r
+ REG_EDX,\r
+ REG_EBX,\r
+ REG_ESP,\r
+ REG_EBP,\r
+ REG_ESI,\r
+ REG_EDI\r
+};\r
+#define XOR(sr,dr) EmitByte(0x31);EmitByte(0xc0 | (sr<<3) | dr);\r
+#define CLEARREG(reg) XOR(reg,reg)\r
+#define LOADREG(addr, reg) if (reg == REG_EAX) {EmitByte(0xa1);} else {EmitByte(0x8b); EmitByte((reg<<3) | 0x05);} EmitAdr(addr);\r
+#define STOREREG(reg, addr) if (reg == REG_EAX) {EmitByte(0xa3);} else {EmitByte(0x89); EmitByte((reg<<3) | 0x05);} EmitAdr(addr);\r
+#define STOREF(f, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);EmitFloat(f);\r
+#define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i);\r
+#define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val);\r
+\r
+static void *LocalLoc(struct jitstate *jit)\r
+{\r
+ return &jit->code[jit->codesize];\r
+}\r
+static void *LocalJmp(struct jitstate *jit, int cond)\r
+{\r
+ /*floating point ops don't set the sign flag, thus we use the 'above/below' instructions instead of 'greater/less' instructions*/\r
+ if (cond == OP_GOTO)\r
+ EmitByte(jit, 0xeb); //jmp\r
+ else if (cond == OP_LE_F)\r
+ EmitByte(jit, 0x76); //jbe\r
+ else if (cond == OP_GE_F)\r
+ EmitByte(jit, 0x73); //jae\r
+ else if (cond == OP_LT_F)\r
+ EmitByte(jit, 0x72); //jb\r
+ else if (cond == OP_GT_F)\r
+ EmitByte(jit, 0x77); //ja\r
+ else if (cond == OP_LE_I)\r
+ EmitByte(jit, 0x7e); //jle\r
+ else if (cond == OP_LT_I)\r
+ EmitByte(jit, 0x7c); //jl\r
+ else if ((cond >= OP_NE_F && cond <= OP_NE_FNC) || cond == OP_NE_I)\r
+ EmitByte(jit, 0x75); //jne\r
+ else if ((cond >= OP_EQ_F && cond <= OP_EQ_FNC) || cond == OP_EQ_I)\r
+ EmitByte(jit, 0x74); //je\r
+#if defined(DEBUG) && defined(_WIN32)\r
+ else\r
+ {\r
+ OutputDebugString("oh noes!\n");\r
+ return NULL;\r
+ }\r
+#endif\r
+\r
+ EmitByte(jit, 0);\r
+\r
+ return LocalLoc(jit);\r
+}\r
+static void LocalJmpLoc(void *jmp, void *loc)\r
+{\r
+ int offs;\r
+ unsigned char *a = jmp;\r
+ offs = (char *)loc - (char *)jmp;\r
+#if defined(DEBUG) && defined(_WIN32)\r
+ if (offs > 127 || offs <= -128)\r
+ {\r
+ OutputDebugStringA("bad jump\n");\r
+ a[-2] = 0xcd;\r
+ a[-1] = 0xcc;\r
+ return;\r
+ }\r
+#endif\r
+ a[-1] = offs;\r
+}\r
+\r
+static void FixupJumps(struct jitstate *jit)\r
{\r
unsigned int j;\r
unsigned char *codesrc;\r
\r
unsigned int v;\r
\r
- for (j = 0; j < numjumps;)\r
+ for (j = 0; j < jit->numjumps;)\r
{\r
- v = statementjumps[j++];\r
- codesrc = &code[v];\r
+ v = jit->statementjumps[j++];\r
+ codesrc = &jit->code[v];\r
\r
- v = statementjumps[j++];\r
- codedst = statementoffsets[v];\r
+ v = jit->statementjumps[j++];\r
+ codedst = jit->statementoffsets[v];\r
\r
- v = statementjumps[j++];\r
+ v = jit->statementjumps[j++];\r
offset = (int)(codedst - (codesrc-v)); //3rd term because the jump is relative to the instruction start, not the instruction's offset\r
\r
codesrc[0] = (offset>> 0)&0xff;\r
}\r
}\r
\r
-int PR_LeaveFunction (progfuncs_t *progfuncs);\r
-int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum);\r
+int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs);\r
+int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum);\r
+\r
+void PR_CloseJit(struct jitstate *jit)\r
+{\r
+ free(jit->statementjumps);\r
+ free(jit->statementoffsets);\r
+ free(jit->code);\r
+}\r
+\r
+#define EmitByte(v) EmitByte(jit, v)\r
+#define EmitAdr(v) EmitAdr(jit, v)\r
+#define EmitFOffset(a,b) EmitFOffset(jit, a, b)\r
+#define Emit4ByteJump(a,b) Emit4ByteJump(jit, a, b)\r
+#define Emit4Byte(v) Emit4Byte(jit, v)\r
+#define EmitFloat(v) EmitFloat(jit, v)\r
+#define LocalJmp(v) LocalJmp(jit, v)\r
+#define LocalLoc() LocalLoc(jit)\r
+\r
\r
-pbool PR_GenerateJit(progfuncs_t *progfuncs)\r
+struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs)\r
{\r
+ struct jitstate *jit;\r
+\r
+ void *j0, *l0;\r
+ void *j1, *l1;\r
+ void *j2, *l2;\r
unsigned int i;\r
dstatement16_t *op = (dstatement16_t*)current_progstate->statements;\r
unsigned int numstatements = current_progstate->progs->numstatements;\r
int *glob = (int*)current_progstate->globals;\r
\r
if (current_progstate->numbuiltins)\r
- return false;\r
-\r
- jitstatements = numstatements;\r
+ return NULL;\r
+ jit = malloc(sizeof(*jit));\r
+ jit->jitstatements = numstatements;\r
\r
- statementjumps = malloc(numstatements*12);\r
- statementoffsets = malloc(numstatements*4);\r
- code = malloc(numstatements*500);\r
+ jit->statementjumps = malloc(numstatements*12);\r
+ jit->statementoffsets = malloc(numstatements*4);\r
+ jit->code = malloc(numstatements*500);\r
+ if (!jit->code)\r
+ return NULL;\r
\r
- numjumps = 0;\r
- codesize = 0;\r
+ jit->numjumps = 0;\r
+ jit->codesize = 0;\r
\r
\r
\r
for (i = 0; i < numstatements; i++)\r
{\r
- statementoffsets[i] = &code[codesize];\r
+ jit->statementoffsets[i] = &jit->code[jit->codesize];\r
+\r
+ /*DEBUG*/\r
+ SETREGI(op[i].op, REG_ESI);\r
+\r
switch(op[i].op)\r
{\r
//jumps\r
- case OP_IF:\r
+ case OP_IF_I:\r
//integer compare\r
//if a, goto b\r
\r
//cmpl $0,glob[A]\r
EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0);\r
- //jnz B\r
+ //jne B\r
EmitByte(0x0f);EmitByte(0x85);Emit4ByteJump(i + (signed short)op[i].b, -4);\r
break;\r
\r
- case OP_IFNOT:\r
+ case OP_IFNOT_I:\r
//integer compare\r
//if !a, goto b\r
\r
//cmpl $0,glob[A]\r
EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0);\r
- //jz B\r
+ //je B\r
EmitByte(0x0f);EmitByte(0x84);Emit4ByteJump(i + (signed short)op[i].b, -4);\r
break;\r
\r
{\r
//assumption: anything that returns address 0 is a void or zero return.\r
//thus clear eax and copy that to the return vector.\r
- EmitByte(0x31);EmitByte(0xc0);\r
- EmitByte(0xa3);EmitAdr(glob + OFS_RETURN+0);\r
- EmitByte(0xa3);EmitAdr(glob + OFS_RETURN+1);\r
- EmitByte(0xa3);EmitAdr(glob + OFS_RETURN+2);\r
+ CLEARREG(REG_EAX);\r
+ STOREREG(REG_EAX, glob + OFS_RETURN+0);\r
+ STOREREG(REG_EAX, glob + OFS_RETURN+1);\r
+ STOREREG(REG_EAX, glob + OFS_RETURN+2);\r
}\r
else\r
{\r
- //movl glob[A+0],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a+0);\r
- //movl glob[A+0],edx\r
- EmitByte(0x8b);EmitByte(0x0d);EmitAdr(glob + op[i].a+1);\r
- //movl glob[A+0],ecx\r
- EmitByte(0x8b);EmitByte(0x15);EmitAdr(glob + op[i].a+2);\r
- //movl eax, glob[OFS_RET+0]\r
- EmitByte(0xa3);EmitAdr(glob + OFS_RETURN+0);\r
- //movl edx, glob[OFS_RET+0]\r
- EmitByte(0x89);EmitByte(0x15);EmitAdr(glob + OFS_RETURN+1);\r
- //movl ecx, glob[OFS_RET+0]\r
- EmitByte(0x89);EmitByte(0x15);EmitAdr(glob + OFS_RETURN+2);\r
+ LOADREG(glob + op[i].a+0, REG_EAX);\r
+ LOADREG(glob + op[i].a+1, REG_EDX);\r
+ LOADREG(glob + op[i].a+2, REG_ECX);\r
+ STOREREG(REG_EAX, glob + OFS_RETURN+0);\r
+ STOREREG(REG_EDX, glob + OFS_RETURN+1);\r
+ STOREREG(REG_ECX, glob + OFS_RETURN+2);\r
}\r
\r
//call leavefunction to get the return address\r
// cmp prinst->exitdepth,%edx\r
EmitByte(0x3b);EmitByte(0x15);EmitAdr(&prinst->exitdepth);\r
// je returntoc\r
- EmitByte(0x74);EmitByte(0x09);\r
-// mov statementoffsets[%eax*4],%eax\r
- EmitByte(0x8b);EmitByte(0x04);EmitByte(0x85);EmitAdr(statementoffsets+1);\r
-// jmp eax\r
- EmitByte(0xff);EmitByte(0xe0);\r
+ j1 = LocalJmp(OP_EQ_E);\r
+// mov statementoffsets[%eax*4],%eax\r
+ EmitByte(0x8b);EmitByte(0x04);EmitByte(0x85);EmitAdr(jit->statementoffsets+1);\r
+// jmp *eax\r
+ EmitByte(0xff);EmitByte(0xe0);\r
// returntoc:\r
+ l1 = LocalLoc();\r
// ret\r
EmitByte(0xc3);\r
+\r
+ LocalJmpLoc(j1,l1);\r
break;\r
\r
//function calls\r
case OP_CALL8:\r
//save the state in place the rest of the engine can cope with\r
//movl $i, pr_xstatement\r
- EmitByte(0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i);\r
+ EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i);\r
//movl $(op[i].op-OP_CALL0), pr_argc\r
- EmitByte(0xc7);EmitByte(0x05);EmitAdr(&pr_argc);Emit4Byte(op[i].op-OP_CALL0);\r
+ EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_argc);Emit4Byte(op[i].op-OP_CALL0);\r
\r
//figure out who we're calling, and what that involves\r
//%eax = glob[A]\r
- EmitByte(0xa1); EmitAdr(glob + op[i].a);\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
//eax is now the func num\r
\r
//mov %eax,%ecx\r
//cmp %ecx,pr_typecurrent\r
EmitByte(0x39); EmitByte(0x0d); EmitAdr(&pr_typecurrent);\r
//je sameprogs\r
- EmitByte(0x74); EmitByte(0x3);\r
+ j1 = LocalJmp(OP_EQ_I);\r
{\r
//can't handle switching progs\r
\r
EmitByte(0xc3);\r
}\r
//sameprogs:\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
\r
//andl $0x00ffffff, %eax\r
EmitByte(0x25);Emit4Byte(0x00ffffff);\r
//cmp $0,%edx\r
EmitByte(0x83);EmitByte(0xfa);EmitByte(0x00);\r
//jl isabuiltin\r
- EmitByte(0x7c);EmitByte(22);\r
- \r
+ j1 = LocalJmp(OP_LT_I);\r
{\r
+ /* call the function*/\r
//push %ecx\r
EmitByte(0x51);\r
//push %eax\r
//eax is now the next statement number (first of the new function, usually equal to ecx, but not always)\r
\r
//jmp statementoffsets[%eax*4]\r
- EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(statementoffsets+1);\r
+ EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(jit->statementoffsets+1);\r
}\r
+ /*its a builtin, figure out which, and call it*/\r
//isabuiltin:\r
-\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
\r
//push current_progstate->globals\r
EmitByte(0x68);EmitAdr(current_progstate->globals);\r
\r
//but that builtin might have been Abort()\r
\r
- //mov prinst->continuestatement,%eax\r
- EmitByte(0xa1);EmitAdr(&prinst->continuestatement);\r
- //eax is now prinst->continuestatement\r
-\r
+ LOADREG(&prinst->continuestatement, REG_EAX);\r
//cmp $-1,%eax\r
EmitByte(0x83);EmitByte(0xf8);EmitByte(0xff);\r
//je donebuiltincall\r
- EmitByte(0x74);EmitByte(10+8);\r
+ j1 = LocalJmp(OP_EQ_I);\r
{\r
-EmitByte(0xcc);\r
- //jmp statementoffsets[%eax*4]\r
- EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(statementoffsets+1);\r
-\r
//mov $-1,prinst->continuestatement\r
- EmitByte(0xc7);EmitByte(0x05);EmitAdr(&prinst->continuestatement+1);Emit4Byte((unsigned int)-1);\r
+ EmitByte(0xc7);EmitByte(0x05);EmitAdr(&prinst->continuestatement);Emit4Byte((unsigned int)-1);\r
+\r
+ //jmp statementoffsets[%eax*4]\r
+ EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(jit->statementoffsets);\r
}\r
//donebuiltincall:\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
break;\r
\r
case OP_MUL_F:\r
break;\r
\r
case OP_NOT_F:\r
- //flds glob[A]\r
- EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a);\r
//fldz\r
EmitByte(0xd9);EmitByte(0xee);\r
+ //fcomps glob[A]\r
+ EmitByte(0xd8); EmitByte(0x1d); EmitAdr(glob + op[i].a);\r
//fnstsw %ax\r
EmitByte(0xdf);EmitByte(0xe0);\r
//testb 0x40,%ah\r
EmitByte(0xf6);EmitByte(0xc4);EmitByte(0x40);\r
- //je noteq\r
- EmitByte(0x74);EmitByte(0x0c);\r
- //movl 1.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05);EmitAdr(glob + op[i].c);EmitFloat(0.0f);\r
- //jmp end\r
- EmitByte(0xeb);EmitByte(0x0a);\r
- //noteq:\r
- //movl 0.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05);EmitAdr(glob + op[i].c);EmitFloat(1.0f);\r
+ \r
+ j1 = LocalJmp(OP_NE_F);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ j2 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ //noteq:\r
+ l1 = LocalLoc();\r
+ STOREF(1.0f, glob + op[i].c);\r
+ }\r
//end:\r
+ l2 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+ LocalJmpLoc(j2,l2);\r
break;\r
\r
case OP_STORE_F:\r
case OP_STORE_ENT:\r
case OP_STORE_FLD:\r
case OP_STORE_FNC:\r
- //movl glob[A],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
- //movl eax,glob[B]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].b);\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
+ STOREREG(REG_EAX, glob + op[i].b);\r
break;\r
\r
case OP_STORE_V:\r
- //movl glob[A+0],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a+0);\r
- //movl glob[A+1],edx\r
- EmitByte(0x8b);EmitByte(0x0d);EmitAdr(glob + op[i].a+1);\r
- //movl glob[A+2],ecx\r
- EmitByte(0x8b);EmitByte(0x15);EmitAdr(glob + op[i].a+2);\r
-\r
- //movl eax, glob[B+0]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].b+0);\r
- //movl edx, glob[B+1]\r
- EmitByte(0x89);EmitByte(0x15);EmitAdr(glob + op[i].b+1);\r
- //movl ecx, glob[B+2]\r
- EmitByte(0x89);EmitByte(0x15);EmitAdr(glob + op[i].b+2);\r
+ LOADREG(glob + op[i].a+0, REG_EAX);\r
+ LOADREG(glob + op[i].a+1, REG_EDX);\r
+ LOADREG(glob + op[i].a+2, REG_ECX);\r
+ STOREREG(REG_EAX, glob + op[i].b+0);\r
+ STOREREG(REG_EDX, glob + op[i].b+1);\r
+ STOREREG(REG_ECX, glob + op[i].b+2);\r
break;\r
\r
case OP_LOAD_F:\r
//a is the ent number, b is the field\r
//c is the dest\r
\r
- //movl glob[A+0],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
- //mov glob[B],ecx\r
- EmitByte(0x8b); EmitByte(0x0d);EmitAdr(glob + op[i].b);\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
+ LOADREG(glob + op[i].b, REG_ECX);\r
+\r
//FIXME: bound eax (ent number)\r
//FIXME: bound ecx (field index)\r
//mov (ebx,eax,4).%eax\r
EmitByte(0x8b);EmitByte(0x50);EmitByte((int)&((edictrun_t*)NULL)->fields);\r
//edx is now the field array for that ent\r
\r
- //mov fieldajust(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust\r
+ //mov fieldajust(%edx,%ecx,4),%eax\r
EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(progfuncs->fieldadjust*4);\r
- //mov edx,glob[C]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].c);\r
+\r
+ STOREREG(REG_EAX, glob + op[i].c)\r
\r
if (op[i].op == OP_LOAD_V)\r
{\r
- //mov fieldajust+4(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust\r
+ //mov fieldajust+4(%edx,%ecx,4),%eax\r
EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(4+progfuncs->fieldadjust*4);\r
- //mov edx,glob[C+1]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].c+1);\r
+ STOREREG(REG_EAX, glob + op[i].c+1)\r
\r
- //mov fieldajust+8(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust\r
- EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(4+progfuncs->fieldadjust*4);\r
- //mov edx,glob[C+1]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].c+2);\r
+ //mov fieldajust+8(%edx,%ecx,4),%eax\r
+ EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(8+progfuncs->fieldadjust*4);\r
+ STOREREG(REG_EAX, glob + op[i].c+2)\r
}\r
break;\r
\r
//a is the ent number, b is the field\r
//c is the dest\r
\r
- //movl glob[A+0],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
- //mov glob[B],ecx\r
- EmitByte(0x8b); EmitByte(0x0d);EmitAdr(glob + op[i].b);\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
+ LOADREG(glob + op[i].b, REG_ECX);\r
+\r
//FIXME: bound eax (ent number)\r
//FIXME: bound ecx (field index)\r
//mov (ebx,eax,4).%eax\r
//mov fieldajust(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust\r
//EmitByte(0x8d); EmitByte(0x84); EmitByte(0x8a); EmitByte(progfuncs->fieldadjust*4);\r
EmitByte(0x8d); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(progfuncs->fieldadjust*4);\r
- //mov edx,glob[C]\r
- EmitByte(0xa3);EmitAdr(glob + op[i].c);\r
+ STOREREG(REG_EAX, glob + op[i].c);\r
break;\r
\r
case OP_STOREP_F:\r
case OP_STOREP_ENT:\r
case OP_STOREP_FLD:\r
case OP_STOREP_FNC:\r
- //movl glob[A],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
- //mov glob[B],ecx\r
- EmitByte(0x8b); EmitByte(0x0d);EmitAdr(glob + op[i].b);\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
+ LOADREG(glob + op[i].b, REG_ECX);\r
//mov %eax,(%ecx)\r
EmitByte(0x89);EmitByte(0x01);\r
break;\r
\r
case OP_STOREP_V:\r
- //mov glob[B],ecx\r
- EmitByte(0x8b); EmitByte(0x0d);EmitAdr(glob + op[i].b);\r
- //movl glob[A],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a+0);\r
+ LOADREG(glob + op[i].b, REG_ECX);\r
+\r
+ LOADREG(glob + op[i].a+0, REG_EAX);\r
//mov %eax,0(%ecx)\r
EmitByte(0x89);EmitByte(0x01);\r
- //movl glob[A],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a+0);\r
+\r
+ LOADREG(glob + op[i].a+1, REG_EAX);\r
//mov %eax,4(%ecx)\r
EmitByte(0x89);EmitByte(0x41);EmitByte(0x04);\r
- //movl glob[A],eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a+0);\r
+\r
+ LOADREG(glob + op[i].a+2, REG_EAX);\r
//mov %eax,8(%ecx)\r
EmitByte(0x89);EmitByte(0x41);EmitByte(0x08);\r
break;\r
\r
+ case OP_NE_I:\r
+ case OP_NE_E:\r
+ case OP_NE_FNC:\r
+ case OP_EQ_I:\r
case OP_EQ_E:\r
case OP_EQ_FNC:\r
//integer equality\r
- //movl glob[A],%eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
- //cmp glob[B],%eax\r
- EmitByte(0x3b); EmitByte(0x0f); EmitAdr(glob + op[i].b);\r
- //je 12\r
- EmitByte(0x74);EmitByte(0x0c);\r
- //mov 0.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(0.0f);\r
- //jmp 10\r
- EmitByte(0xeb);EmitByte(0x0a);\r
- //mov 1.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(1.0f);\r
- break;\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
\r
- case OP_NE_E:\r
- case OP_NE_FNC:\r
- //integer equality\r
- //movl glob[A],%eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
//cmp glob[B],%eax\r
- EmitByte(0x3b); EmitByte(0x0f); EmitAdr(glob + op[i].b);\r
- //je 12\r
- EmitByte(0x74);EmitByte(0x0c);\r
- //mov 0.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(1.0f);\r
- //jmp 10\r
- EmitByte(0xeb);EmitByte(0x0a);\r
- //mov 1.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(0.0f);\r
+ EmitByte(0x3b); EmitByte(0x04); EmitByte(0x25); EmitAdr(glob + op[i].b);\r
+ j1 = LocalJmp(op[i].op);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ j2 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ l1 = LocalLoc();\r
+ STOREF(1.0f, glob + op[i].c);\r
+ }\r
+ l2 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+ LocalJmpLoc(j2,l2);\r
break;\r
\r
+ case OP_NOT_I:\r
case OP_NOT_ENT:\r
case OP_NOT_FNC:\r
- //cmp glob[B],%eax\r
- EmitByte(0x8c); EmitByte(0x3d); EmitAdr(glob + op[i].a);EmitByte(0x00);\r
- //je 12\r
- EmitByte(0x74);EmitByte(0x0c);\r
- //mov 0.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(0.0f);\r
- //jmp 10\r
- EmitByte(0xeb);EmitByte(0x0a);\r
- //mov 1.0f,glob[C]\r
- EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].c);EmitFloat(1.0f);\r
+ //cmp glob[B],$0\r
+ EmitByte(0x83); EmitByte(0x3d); EmitAdr(glob + op[i].a); EmitByte(0x00); \r
+ j1 = LocalJmp(OP_NE_I);\r
+ {\r
+ STOREF(1.0f, glob + op[i].c);\r
+ j2 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ l1 = LocalLoc();\r
+ STOREF(0.0f, glob + op[i].c);\r
+ }\r
+ l2 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+ LocalJmpLoc(j2,l2);\r
break;\r
\r
- case OP_BITOR: //floats...\r
+ case OP_BITOR_F: //floats...\r
//flds glob[A]\r
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a);\r
//flds glob[B]\r
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b);\r
//fistp tb\r
- EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb);\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb);\r
//fistp ta\r
- EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta);\r
- //mov ta,%eax\r
- EmitByte(0xa1); EmitAdr(&ta);\r
- //and tb,%eax\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta);\r
+ LOADREG(&ta, REG_EAX)\r
+ //or %eax,tb\r
EmitByte(0x09); EmitByte(0x05);EmitAdr(&tb);\r
//fild tb\r
- EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb);\r
+ EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb);\r
//fstps glob[C]\r
EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c);\r
break;\r
\r
- case OP_BITAND:\r
+ case OP_BITAND_F:\r
//flds glob[A]\r
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a);\r
//flds glob[B]\r
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b);\r
//fistp tb\r
- EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb);\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb);\r
//fistp ta\r
- EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta);\r
- //mov ta,%eax\r
- EmitByte(0xa1); EmitAdr(&ta);\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta);\r
+ /*two args are now at ta and tb*/\r
+ LOADREG(&ta, REG_EAX)\r
//and tb,%eax\r
EmitByte(0x21); EmitByte(0x05);EmitAdr(&tb);\r
+ /*we just wrote the int value to tb, convert that to a float and store it at c*/\r
//fild tb\r
- EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb);\r
+ EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb);\r
//fstps glob[C]\r
EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c);\r
break;\r
\r
- case OP_AND:\r
+ case OP_AND_F:\r
//test floats properly, so we don't get confused with -0.0\r
\r
//flds glob[A]\r
EmitByte(0xdf); EmitByte(0xe0);\r
//test $0x40,%ah\r
EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40);\r
- //je onefalse\r
+ //jz onefalse\r
EmitByte(0x75); EmitByte(0x1f);\r
\r
//flds glob[B]\r
EmitByte(0xdf); EmitByte(0xe0);\r
//test $0x40,%ah\r
EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40);\r
- //jne onefalse\r
+ //jnz onefalse\r
EmitByte(0x75); EmitByte(0x0c);\r
\r
//mov float0,glob[C]\r
EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f);\r
//done:\r
break;\r
- case OP_OR:\r
+ case OP_OR_F:\r
//test floats properly, so we don't get confused with -0.0\r
\r
//flds glob[A]\r
\r
case OP_EQ_S:\r
case OP_NE_S:\r
+ {\r
//put a in ecx\r
+ LOADREG(glob + op[i].a, REG_ECX);\r
//put b in edi\r
- //mov a,%ecx\r
- EmitByte(0x8b); EmitByte(0x0d); EmitAdr(glob + op[i].a);\r
- //mov b,%edi\r
- EmitByte(0x8b); EmitByte(0x3d); EmitAdr(glob + op[i].b);\r
-\r
+ LOADREG(glob + op[i].b, REG_EDI);\r
+/*\r
//early out if they're equal\r
//cmp %ecx,%edi\r
- EmitByte(0x39); EmitByte(0xd1);\r
- //je _true\r
- EmitByte(0x74); EmitByte(0x68);\r
+ EmitByte(0x39); EmitByte(0xc0 | (REG_EDI<<3) | REG_ECX);\r
+ j1c = LocalJmp(OP_EQ_S);\r
\r
//if a is 0, check if b is ""\r
//jecxz ais0\r
EmitByte(0x83); EmitByte(0xc4); EmitByte(0x08);\r
//cmpb $0,(%eax)\r
EmitByte(0x80); EmitByte(0x38); EmitByte(0x00);\r
+ j1b = LocalJmp(OP_EQ_S);\r
+ j0b = LocalJmp(OP_GOTO);\r
+ }\r
+\r
+ //ais0:\r
+ {\r
+ //push edi\r
+ EmitByte(0x57);\r
+ //push progfuncs\r
+ EmitByte(0x68); EmitAdr(progfuncs);\r
+ //call PR_StringToNative\r
+ EmitByte(0xe8); EmitFOffset(PR_StringToNative,4);\r
+ //add $8,%esp\r
+ EmitByte(0x83); EmitByte(0xc4); EmitByte(0x08);\r
+ //cmpb $0,(%eax)\r
+ EmitByte(0x80); EmitByte(0x38); EmitByte(0x00);\r
//je _true\r
- EmitByte(0x74); EmitByte(0x4b);\r
+ EmitByte(0x74); EmitByte(0x36);\r
//jmp _false\r
- EmitByte(0xeb); EmitByte(0x3d);\r
-\r
- //ais0:\r
- {\r
- //push edi\r
- EmitByte(0x57);\r
- //push progfuncs\r
- EmitByte(0x68); EmitAdr(progfuncs);\r
- //call PR_StringToNative\r
- EmitByte(0xe8); EmitFOffset(PR_StringToNative,4);\r
- //add $8,%esp\r
- EmitByte(0x83); EmitByte(0xc4); EmitByte(0x08);\r
- //cmpb $0,(%eax)\r
- EmitByte(0x80); EmitByte(0x38); EmitByte(0x00);\r
- //je _true\r
- EmitByte(0x74); EmitByte(0x36);\r
- //jmp _false\r
- EmitByte(0xeb); EmitByte(0x28);\r
- }\r
+ EmitByte(0xeb); EmitByte(0x28);\r
}\r
//bnot0:\r
-\r
+*/\r
+LOADREG(glob + op[i].a, REG_ECX);\r
//push ecx\r
EmitByte(0x51);\r
//push progfuncs\r
//push %eax\r
EmitByte(0x50);\r
\r
+LOADREG(glob + op[i].b, REG_EDI);\r
//push %edi\r
EmitByte(0x57);\r
//push progfuncs\r
EmitByte(0xe8); EmitFOffset(strcmp,4);\r
//add $16,%esp\r
EmitByte(0x83); EmitByte(0xc4); EmitByte(0x10);\r
+\r
//cmp $0,%eax\r
EmitByte(0x83); EmitByte(0xf8); EmitByte(0x00);\r
- //je _true\r
- EmitByte(0x74); EmitByte(0x0c);\r
-//_false:\r
- //mov 0.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat((op[i].op == OP_NE_S)?1.0f:0.0f);\r
- //jmp done\r
- EmitByte(0xeb); EmitByte(0x0a);\r
-//_true:\r
- //mov 1.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat((op[i].op == OP_NE_S)?0.0f:1.0f);\r
-//_done:\r
+ j1 = LocalJmp(OP_EQ_S);\r
+ {\r
+ l0 = LocalLoc();\r
+ STOREF((op[i].op == OP_NE_S)?1.0f:0.0f, glob + op[i].c);\r
+ j2 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ l1 = LocalLoc();\r
+ STOREF((op[i].op == OP_NE_S)?0.0f:1.0f, glob + op[i].c);\r
+ }\r
+ l2 = LocalLoc();\r
+\r
+// LocalJmpLoc(j0b, l0);\r
+ LocalJmpLoc(j1, l1);\r
+// LocalJmpLoc(j1b, l1);\r
+ LocalJmpLoc(j2, l2);\r
+ }\r
break;\r
\r
case OP_NOT_S:\r
- //mov A,%eax\r
- EmitByte(0xa1);EmitAdr(glob + op[i].a);\r
+ LOADREG(glob + op[i].a, REG_EAX)\r
+\r
//cmp $0,%eax\r
EmitByte(0x83); EmitByte(0xf8); EmitByte(0x00);\r
- //je _true\r
- EmitByte(0x74); EmitByte(0x1f);\r
+ j2 = LocalJmp(OP_EQ_S);\r
+\r
//push %eax\r
EmitByte(0x50);\r
//push progfuncs\r
EmitByte(0xe8); EmitFOffset(PR_StringToNative,4);\r
//add $8,%esp\r
EmitByte(0x83); EmitByte(0xc4); EmitByte(0x08);\r
+\r
//cmpb $0,(%eax)\r
EmitByte(0x80); EmitByte(0x38); EmitByte(0x00);\r
- //je _true\r
- EmitByte(0x74); EmitByte(0x0c);\r
-//_false:\r
- //mov 0.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f);\r
- //jmp done\r
- EmitByte(0xeb); EmitByte(0x0a);\r
-//_true:\r
- //mov 1.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f);\r
-//_done:\r
+ j1 = LocalJmp(OP_EQ_S);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ j0 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ l1 = LocalLoc();\r
+ STOREF(1.0f, glob + op[i].c);\r
+ }\r
+ l2 = LocalLoc();\r
+ LocalJmpLoc(j2, l1);\r
+ LocalJmpLoc(j1, l1);\r
+ LocalJmpLoc(j0, l2);\r
break;\r
\r
case OP_ADD_V:\r
\r
case OP_EQ_F:\r
case OP_NE_F:\r
- case OP_LE:\r
- case OP_GE:\r
- case OP_LT:\r
- case OP_GT:\r
+ case OP_LE_F:\r
+ case OP_GE_F:\r
+ case OP_LT_F:\r
+ case OP_GT_F:\r
//flds glob[A]\r
- EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a);\r
- //flds glob[B]\r
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b);\r
+ //flds glob[B]\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a);\r
//fcomip %st(1),%st\r
EmitByte(0xdf);EmitByte(0xe9);\r
//fstp %st(0) (aka: pop)\r
EmitByte(0xdd);EmitByte(0xd8);\r
\r
- //jcc _true\r
- if (op[i].op == OP_LE)\r
- EmitByte(0x7e); //jle\r
- else if (op[i].op == OP_GE)\r
- EmitByte(0x7d); //jge\r
- else if (op[i].op == OP_LT)\r
- EmitByte(0x7c); //jl\r
- else if (op[i].op == OP_GT)\r
- EmitByte(0x7f); //jg\r
- else if (op[i].op == OP_NE_F)\r
- EmitByte(0x75); //jne\r
- else\r
- EmitByte(0x74); //je\r
- EmitByte(0x0c);\r
-//_false:\r
- //mov 0.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f);\r
- //jmp done\r
- EmitByte(0xeb); EmitByte(0x0a);\r
-//_true:\r
- //mov 1.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f);\r
-//_done:\r
+ j1 = LocalJmp(op[i].op);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ j2 = LocalJmp(OP_GOTO);\r
+ }\r
+ {\r
+ l1 = LocalLoc();\r
+ STOREF(1.0f, glob + op[i].c);\r
+ }\r
+ l2 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+ LocalJmpLoc(j2,l2);\r
break;\r
\r
case OP_MUL_FV:\r
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + f);\r
\r
//flds glob[V0]\r
- EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+0);\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+0);\r
//fmul st(1)\r
EmitByte(0xd8);EmitByte(0xc9);\r
//fstps glob[C]\r
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+0);\r
\r
//flds glob[V0]\r
- EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+1);\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+1);\r
//fmul st(1)\r
EmitByte(0xd8);EmitByte(0xc9);\r
//fstps glob[C]\r
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+1);\r
\r
//flds glob[V0]\r
- EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+2);\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+2);\r
//fmul st(1)\r
EmitByte(0xd8);EmitByte(0xc9);\r
//fstps glob[C]\r
//add $12,%esp\r
EmitByte(0x83); EmitByte(0xc4); EmitByte(0x0c);\r
break;\r
-#if 0\r
- case OP_NOT_V:\r
+#if 1\r
+/* case OP_NOT_V:\r
//flds 0\r
//flds glob[A+0]\r
//fcomip %st(1),%st\r
//mov 0,C\r
//done:\r
break;\r
-\r
+*/\r
+ \r
+ case OP_NOT_V:\r
+ EmitByte(0xcd);EmitByte(op[i].op);\r
+ printf("QCJIT: instruction %i is not implemented\n", op[i].op);\r
+ break;\r
+#endif\r
+ case OP_NE_V:\r
case OP_EQ_V:\r
+ {\r
+ void *f0, *f1, *f2, *floc;\r
+//compare v[0]\r
//flds glob[A]\r
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+0);\r
//flds glob[B]\r
//fstp %st(0) (aka: pop)\r
EmitByte(0xdd);EmitByte(0xd8);\r
\r
- //jncc _true\r
- if (op[i].op == OP_NE_V)\r
- EmitByte(0x74); //je\r
- else\r
- EmitByte(0x75); //jne\r
- EmitByte(0x0c);\r
-//_false0:\r
- //mov 0.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f);\r
- //jmp done\r
- EmitByte(0xeb); EmitByte(0x0a);\r
+ /*if the condition is true, don't fail*/\r
+ j1 = LocalJmp(op[i].op);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ f0 = LocalJmp(OP_GOTO);\r
+ }\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
\r
+//compare v[1]\r
+ //flds glob[A]\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+1);\r
+ //flds glob[B]\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b+1);\r
+ //fcomip %st(1),%st\r
+ EmitByte(0xdf);EmitByte(0xe9);\r
+ //fstp %st(0) (aka: pop)\r
+ EmitByte(0xdd);EmitByte(0xd8);\r
\r
-//_true:\r
- //mov 1.0f,c\r
- EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f);\r
-//_done:\r
+ /*if the condition is true, don't fail*/\r
+ j1 = LocalJmp(op[i].op);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ f1 = LocalJmp(OP_GOTO);\r
+ }\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+\r
+//compare v[2]\r
+ //flds glob[A]\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+2);\r
+ //flds glob[B]\r
+ EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b+2);\r
+ //fcomip %st(1),%st\r
+ EmitByte(0xdf);EmitByte(0xe9);\r
+ //fstp %st(0) (aka: pop)\r
+ EmitByte(0xdd);EmitByte(0xd8);\r
+\r
+ /*if the condition is true, don't fail*/\r
+ j1 = LocalJmp(op[i].op);\r
+ {\r
+ STOREF(0.0f, glob + op[i].c);\r
+ f2 = LocalJmp(OP_GOTO);\r
+ }\r
+ l1 = LocalLoc();\r
+ LocalJmpLoc(j1,l1);\r
+\r
+//success!\r
+ STOREF(1.0f, glob + op[i].c);\r
+\r
+ floc = LocalLoc();\r
+ LocalJmpLoc(f0,floc);\r
+ LocalJmpLoc(f1,floc);\r
+ LocalJmpLoc(f2,floc);\r
break;\r
+ }\r
\r
+ /*fteqcc generates these from reading 'fast arrays', and are part of hexenc extras*/\r
+ case OP_FETCH_GBL_F:\r
+ case OP_FETCH_GBL_S:\r
+ case OP_FETCH_GBL_E:\r
+ case OP_FETCH_GBL_FNC:\r
+ case OP_FETCH_GBL_V:\r
+ {\r
+ unsigned int max = ((unsigned int*)glob)[op[i].a-1];\r
+ unsigned int base = op[i].a;\r
+ //flds glob[B]\r
+ EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b);\r
+ //fistp ta\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta);\r
+ LOADREG(&ta, REG_EAX)\r
+ //FIXME: if eax >= $max, abort\r
\r
- case OP_EQ_V:\r
- EmitByte(0xcd);EmitByte(op[i].op);\r
- printf("QCJIT: instruction %i is not implemented\n", op[i].op);\r
+ if (op[i].op == OP_FETCH_GBL_V)\r
+ {\r
+ /*scale the index by 3*/\r
+ SETREGI(3, REG_EDX)\r
+ //mul %edx\r
+ EmitByte(0xf7); EmitByte(0xe2);\r
+ }\r
+\r
+ //lookup global\r
+ //mov &glob[base](,%eax,4),%edx\r
+ EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+0));\r
+ STOREREG(REG_EDX, glob + op[i].c+0)\r
+ if (op[i].op == OP_FETCH_GBL_V)\r
+ {\r
+ //mov &glob[base+1](,%eax,4),%edx\r
+ EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+1));\r
+ STOREREG(REG_EDX, glob + op[i].c+1)\r
+ //mov &glob[base+2](,%eax,4),%edx\r
+ EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+2));\r
+ STOREREG(REG_EDX, glob + op[i].c+2)\r
+ }\r
break;\r
+ }\r
\r
- case OP_NE_V:\r
- EmitByte(0xcd);EmitByte(op[i].op);\r
- printf("QCJIT: instruction %i is not implemented\n", op[i].op);\r
+ /*fteqcc generates these from writing 'fast arrays'*/\r
+ case OP_GLOBALADDRESS:\r
+ LOADREG(glob + op[i].b, REG_EAX);\r
+ //lea &glob[A](, %eax, 4),%eax\r
+ EmitByte(0x8d);EmitByte(0x04);EmitByte(0x85);EmitAdr(glob + op[i].b+2);\r
+ STOREREG(REG_EAX, glob + op[i].c);\r
+ break;\r
+// case OP_BOUNDCHECK:\r
+ //FIXME: assert b <= a < c\r
+ break;\r
+ case OP_CONV_FTOI:\r
+ //flds glob[A]\r
+ EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a);\r
+ //fistp glob[C]\r
+ EmitByte(0xdb); EmitByte(0x1d);EmitAdr(glob + op[i].c);\r
+ break;\r
+ case OP_MUL_I:\r
+ LOADREG(glob + op[i].a, REG_EAX);\r
+ //mull glob[C] (arg*eax => edx:eax)\r
+ EmitByte(0xfc); EmitByte(0x25);EmitAdr(glob + op[i].b);\r
+ STOREREG(REG_EAX, glob + op[i].c);\r
break;\r
\r
- case OP_NOT_V:\r
- EmitByte(0xcd);EmitByte(op[i].op);\r
- printf("QCJIT: instruction %i is not implemented\n", op[i].op);\r
+ /*other extended opcodes*/\r
+ case OP_BITOR_I:\r
+ LOADREG(glob + op[i].a, REG_EAX)\r
+ //or %eax,tb\r
+ EmitByte(0x0b); EmitByte(0x05);EmitAdr(glob + op[i].b);\r
+ STOREREG(REG_EAX, glob + op[i].c);\r
break;\r
-#endif\r
+\r
+\r
default:\r
- printf("QCJIT: Extended instruction set %i is not supported, not using jit.\n", op[i].op);\r
+ {\r
+ enum qcop_e e = op[i].op;\r
+ printf("QCJIT: Extended instruction set %i is not supported, not using jit.\n", e);\r
+ }\r
\r
\r
- free(statementjumps); //[MAX_STATEMENTS]\r
- free(statementoffsets); //[MAX_STATEMENTS]\r
- free(code);\r
- statementoffsets = NULL;\r
- return false;\r
+ free(jit->statementjumps); //[MAX_STATEMENTS]\r
+ free(jit->statementoffsets); //[MAX_STATEMENTS]\r
+ free(jit->code);\r
+ free(jit);\r
+ return NULL;\r
}\r
}\r
\r
- FixupJumps();\r
+ FixupJumps(jit);\r
\r
#ifdef _WIN32\r
{\r
\r
//this memory is on the heap.\r
//this means that we must maintain read/write protection, or libc will crash us\r
- VirtualProtect(code, codesize, PAGE_EXECUTE_READWRITE, &old);\r
+ VirtualProtect(jit->code, jit->codesize, PAGE_EXECUTE_READWRITE, &old);\r
}\r
#endif\r
\r
-// externs->WriteFile("jit.x86", code, codesize);\r
+// externs->WriteFile("jit.x86", jit->code, jit->codesize);\r
\r
- return true;\r
+ return jit;\r
+}\r
+\r
+float foo(float arg)\r
+{\r
+ float f;\r
+ if (!arg)\r
+ f = 1;\r
+ else\r
+ f = 0;\r
+ return f;\r
}\r
\r
-void PR_EnterJIT(progfuncs_t *progfuncs, int statement)\r
+void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jit, int statement)\r
{\r
#ifdef __GNUC__\r
//call, it clobbers pretty much everything.\r
- asm("call *%0" :: "r"(statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx");\r
+ asm("call *%0" :: "r"(jit->statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx");\r
#elif defined(_MSC_VER)\r
- void *entry = statementoffsets[statement+1];\r
+ void *entry = jit->statementoffsets[statement+1];\r
void *edicttable = prinst->edicttable;\r
__asm {\r
pushad\r
#ifdef _WIN32
-
+ #define _CRT_SECURE_NO_WARNINGS
+ #define _CRT_NONSTDC_NO_WARNINGS
#ifndef AVAIL_ZLIB
#ifdef _MSC_VER
//#define AVAIL_ZLIB
typedef unsigned char qbyte;
#include <stdio.h>
-#if defined(_M_IX86) || defined(__i386__)
-//#define QCJIT
-#endif
-
#define DLL_PROG
#ifndef PROGSUSED
#define PROGSUSED
#include "progtype.h"
#include "progslib.h"
+#ifdef _MSC_VER
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4267)
+#endif
+
//extern progfuncs_t *progfuncs;
#define prinst progfuncs->prinst
void QC_StartShares(progfuncs_t *progfuncs);
void QC_AddSharedVar(progfuncs_t *progfuncs, int num, int type);
void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable);
-int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, int requestedpos, int originalofs);
+int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, signed long requestedpos, signed long originalofs);
pbool Decompile(progfuncs_t *progfuncs, char *fname);
int PR_ToggleBreakpoint(progfuncs_t *progfuncs, char *filename, int linenum, int flag);
void StripExtension (char *path);
int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags);
char *SaveEnt (progfuncs_t *progfuncs, char *buf, int *size, struct edict_s *ed);
struct edict_s *RestoreEnt (progfuncs_t *progfuncs, char *buf, int *size, struct edict_s *ed);
-char *PF_VarString (int first);
void PR_StackTrace (progfuncs_t *progfuncs);
extern int noextensions;
+typedef enum
+{
+ PST_DEFAULT, //16
+ PST_FTE32, //32
+ PST_KKQWSV, //24
+ PST_QTEST,
+} progstructtype_t;
+
#ifndef COMPILER
typedef struct progstate_s
{
int *linenums; //debug versions only
- int intsize; //16 for standard (more limiting) versions
+ progstructtype_t structtype;
} progstate_t;
typedef struct extensionbuiltin_s {
typedef struct prinst_s {
#ifdef QCJIT
- pbool usejit;
+ struct jitstate *jit;
#endif
char **tempstrings;
int maxtempstrings;
} prinst_t;
extern vec3_t vec3_origin;
-eval_t *PR_FindGlobal(progfuncs_t *prfuncs, char *globname, progsnum_t pnum);
+eval_t *PR_FindGlobal(progfuncs_t *prfuncs, char *globname, progsnum_t pnum, etype_t *type);
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum);
ddef32_t *ED_GlobalAtOfs32 (progfuncs_t *progfuncs, unsigned int ofs);
string_t PR_StringToProgs (progfuncs_t *inst, char *str);
-char *PR_StringToNative (progfuncs_t *inst, string_t str);
+char *ASMCALL PR_StringToNative (progfuncs_t *inst, string_t str);
void PR_FreeTemps (progfuncs_t *progfuncs, int depth);
pbool CompileFile(progfuncs_t *progfuncs, char *filename);
-pbool PR_GenerateJit(progfuncs_t *progfuncs);
-void PR_EnterJIT(progfuncs_t *progfuncs, int statement);
+struct jitstate;
+struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs);
+void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jitstate, int statement);
char *QCC_COM_Parse (char *data);
extern char qcc_token[1024];
#ifndef PROGSLIB_H
#define PROGSLIB_H
-/*#define true 1
-#define false 0
-
-#define PITCH 0
-#define YAW 1
-#define ROLL 2
-
-typedef char bool;
-//typedef float vec3_t[3];
-typedef int progsnum_t;
-typedef int func_t;
-#ifndef COMPILER
-typedef char *string_t;
-#endif
-//typedef struct globalvars_s globalvars_t;
-//typedef struct edict_s edict_t;
-#define globalvars_t void
-#define edict_t void
-*/
-
#ifdef _MSC_VER
#define VARGS __cdecl
#endif
#define VARGS
#endif
+#if defined(_M_IX86) || defined(__i386__)
+//#define QCJIT
+#endif
+
+#ifdef QCJIT
+#define ASMCALL VARGS
+#else
+#define ASMCALL
+#endif
+#define QCBUILTIN ASMCALL
+
struct edict_s;
struct entvars_s;
struct globalvars_s;
struct qcthread_s;
typedef struct progfuncs_s progfuncs_t;
-typedef void (*builtin_t) (progfuncs_t *prinst, struct globalvars_s *gvars);
+typedef void (ASMCALL *builtin_t) (progfuncs_t *prinst, struct globalvars_s *gvars);
//used by progs engine. All nulls is reset.
typedef struct {
char *(*saveent) (progfuncs_t *prinst, char *buf, int *size, struct edict_s *ed); //will save just one entities vars
struct edict_s *(*restoreent) (progfuncs_t *prinst, char *buf, int *size, struct edict_s *ed); //will restore the entity that had it's values saved (can use NULL for ed)
- union eval_s *(*FindGlobal) (progfuncs_t *prinst, char *name, progsnum_t num); //find a pointer to the globals value
+ union eval_s *(*FindGlobal) (progfuncs_t *prinst, char *name, progsnum_t num, etype_t *type); //find a pointer to the globals value
char *(*AddString) (progfuncs_t *prinst, char *val, int minlength); //dump a string into the progs memory (for setting globals and whatnot)
void *(*Tempmem) (progfuncs_t *prinst, int ammount, char *whatfor); //grab some mem for as long as the progs stays loaded
int lastcalledbuiltinnumber; //useful with non-implemented opcodes.
- int (*RegisterFieldVar) (progfuncs_t *prinst, unsigned int type, char *name, int requestedpos, int originalofs);
+ int (*RegisterFieldVar) (progfuncs_t *prinst, unsigned int type, char *name, signed long requestedpos, signed long originalofs);
char *tempstringbase; //for engine's use. Store your base tempstring pointer here.
int tempstringnum; //for engine's use.
string_t (*TempString) (progfuncs_t *prinst, char *str);
string_t (*StringToProgs) (progfuncs_t *prinst, char *str);
- char *(*StringToNative) (progfuncs_t *prinst, string_t str);
+ char *(ASMCALL *StringToNative) (progfuncs_t *prinst, string_t str);
int stringtablesize;
int (*QueryField) (progfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache); //find info on a field definition at an offset
void (*EntClear) (progfuncs_t *progfuncs, struct edict_s *e);
+ void (*FindPrefixGlobals) (progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) );
};
typedef struct progexterns_s {
int progsversion; //PROGSTRUCT_VERSION
- unsigned char *(*ReadFile) (char *fname, void *buffer, int len);
- int (*FileSize) (char *fname); //-1 if file does not exist
- pbool (*WriteFile) (char *name, void *data, int len);
+ unsigned char *(*ReadFile) (const char *fname, void *buffer, int len);
+ int (*FileSize) (const char *fname); //-1 if file does not exist
+ pbool (*WriteFile) (const char *name, void *data, int len);
int (VARGS *printf) (const char *, ...) LIKEPRINTF(1);
void (VARGS *Sys_Error) (const char *, ...) LIKEPRINTF(1);
void (VARGS *Abort) (char *, ...) LIKEPRINTF(1);
void (*entspawn) (struct edict_s *ent, int loading); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
pbool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
- void (*stateop) (progfuncs_t *prinst, float var, func_t func); //what to do on qc's state opcode.
- void (*cstateop) (progfuncs_t *prinst, float vara, float varb, func_t currentfunc); //a hexen2 opcode.
- void (*cwstateop) (progfuncs_t *prinst, float vara, float varb, func_t currentfunc); //a hexen2 opcode.
- void (*thinktimeop) (progfuncs_t *prinst, struct edict_s *ent, float varb); //a hexen2 opcode.
+ void (ASMCALL *stateop) (progfuncs_t *prinst, float var, func_t func); //what to do on qc's state opcode.
+ void (ASMCALL *cstateop) (progfuncs_t *prinst, float vara, float varb, func_t currentfunc); //a hexen2 opcode.
+ void (ASMCALL *cwstateop) (progfuncs_t *prinst, float vara, float varb, func_t currentfunc); //a hexen2 opcode.
+ void (ASMCALL *thinktimeop) (progfuncs_t *prinst, struct edict_s *ent, float varb); //a hexen2 opcode.
//used when loading a game
builtin_t *(*builtinsfor) (int num, int headercrc); //must return a pointer to the builtins that were used before the state was saved.
void (*loadcompleate) (int edictsize); //notification to reset any pointers.
+ pbool (*badfield)(progfuncs_t *prinst, struct edict_s *ent, const char *keyname, const char *value); //called for any fields that are not registered
void *(VARGS *memalloc) (int size); //small string allocation malloced and freed randomly by the executor. (use malloc if you want)
void (VARGS *memfree) (void * mem);
#define PR_PrintEdict(pf,ed) (*pf->PrintEdict) (pf, ed)
#define PR_FindFunction(pf, name, num) (*pf->FindFunction) (pf, name, num)
-#define PR_FindGlobal(pf, name, progs) (*pf->FindGlobal) (pf, name, progs)
+#define PR_FindGlobal(pf, name, progs, type) (*pf->FindGlobal) (pf, name, progs, type)
#define PR_AddString(pf, ed, len) (*pf->AddString) (pf, ed, len)
#define PR_Alloc(pf,size) (*pf->Tempmem) (pf, size)
#define MAX_ERRORS 10
-#define MAX_NAME 64 // chars long
+#define MAX_NAME 128 // chars long
extern unsigned int MAX_REGS;
extern int MAX_CONSTANTS;
#define MAXCONSTANTLENGTH 64
-#define MAXCONSTANTVALUELENGTH 1024
#define MAXCONSTANTPARAMLENGTH 32
#define MAXCONSTANTPARAMS 32
-typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_DARKPLACES, QCF_FTE, QCF_FTEDEBUG, QCF_KK7} qcc_targetformat_t;
+typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_DARKPLACES, QCF_FTE, QCF_FTEDEBUG, QCF_KK7, QCF_QTEST} qcc_targetformat_t;
extern qcc_targetformat_t qcc_targetformat;
pbool used;
unsigned int size;
} temp_t;
+void QCC_PurgeTemps(void);
//not written
typedef struct QCC_def_s
pbool shared;
pbool saved;
pbool isstatic;
+ pbool subscoped_away;
temp_t *temp;
} QCC_def_t;
typedef struct
{
char name[MAXCONSTANTLENGTH];
- char value[MAXCONSTANTVALUELENGTH];
+ char *value;
char params[MAXCONSTANTPARAMS][MAXCONSTANTPARAMLENGTH];
int numparams;
pbool used;
extern pbool flag_fasttrackarrays;
extern pbool flag_assume_integer;
extern pbool flag_msvcstyle;
+extern pbool flag_filetimes;
extern pbool opt_overlaptemps;
extern pbool opt_shortenifnots;
void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin);
#ifndef COMMONINLINES
+pbool QCC_PR_CheckImmediate (char *string);
pbool QCC_PR_CheckToken (char *string);
pbool QCC_PR_CheckName (char *string);
void QCC_PR_Expect (char *string);
void VARGS QCC_PR_ParseError (int errortype, char *error, ...);
void VARGS QCC_PR_ParseWarning (int warningtype, char *error, ...);
void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...);
+void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...);
void QCC_PR_ParsePrintDef (int warningtype, QCC_def_t *def);
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...);
ERR_TOOMANYPAKFILES,
ERR_PRECOMPILERCONSTANTTOOLONG,
ERR_MACROTOOMANYPARMS,
- ERR_CONSTANTTOOLONG,
ERR_TOOMANYFRAMEMACROS,
//limitations, some are imposed by compiler, some arn't.
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname);
+void PostCompile(void);
+pbool PreCompile(void);
+
//=============================================================================
extern char pr_immediate_string[8192];
extern int maxtypeinfos;
extern int ForcedCRC;
+extern pbool defaultnoref;
extern pbool defaultstatic;
extern int *qcc_tempofs;
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename);
void QCC_PR_IncludeChunkEx(char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst);
pbool QCC_PR_UnInclude(void);
-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 *);
+extern void *(*pHash_Get)(hashtable_t *table, const char *name);
+extern void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);
+extern void *(*pHash_Add)(hashtable_t *table, const char *name, void *data, bucket_t *);
extern jmp_buf qcccompileerror;
#endif
+// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
+#ifdef __MINGW64__
+#ifndef QCCONLY
+ #if (_MSC_VER >= 1400)
+ //with MSVC 8, use MS extensions
+ #define snprintf linuxlike_snprintf_vc8
+ int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
+ #else
+ //msvc crap
+ #define snprintf linuxlike_snprintf
+ int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf linuxlike_vsnprintf
+ int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
+ #endif
+#endif
+#endif
+
// set these before calling CheckParm
int myargc;
char **myargv;
float QCC_SwapFloat (float l)
{
union {qbyte b[4]; float f;} in, out;
-
+
in.f = l;
out.b[0] = in.b[3];
out.b[1] = in.b[2];
out.b[2] = in.b[1];
out.b[3] = in.b[0];
-
+
return out.f;
}
static int secbase;
gettimeofday(&tp, &tzp);
-
+
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
-
+
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
int QC_strncasecmp (const char *s1, const char *s2, int n)
{
int c1, c2;
-
+
while (1)
{
c1 = *s1++;
if (!n--)
return 0; // strings are equal until end point
-
+
if (c1 != c2)
{
if (c1 >= 'a' && c1 <= 'z')
// s1++;
// s2++;
}
-
+
return -1;
}
{
int c;
int len;
-
+
len = 0;
qcc_token[0] = 0;
-
+
if (!data)
return NULL;
-
+
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
}
data++;
}
-
+
// skip // comments
if (c=='/' && data[1] == '/')
{
data+=2;
goto skipwhite;
}
-
+
// handle quoted strings specially
if (c == '\"')
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c=='\"' || c==',')
break;
} while (c>32);
-
+
qcc_token[len] = 0;
return data;
}
{
int c;
int len;
-
+
len = 0;
qcc_token[0] = 0;
-
+
if (!data)
return NULL;
-
+
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
}
data++;
}
-
+
// skip // comments
if (c=='/' && data[1] == '/')
{
data++;
goto skipwhite;
}
-
+
// handle quoted strings specially
if (c == '\"')
break;
}
}
-
+
qcc_token[len] = 0;
return data;
}
len++;
c = *data;
} while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_');
-
+
qcc_token[len] = 0;
return data;
}
char *VARGS qcva (char *text, ...)
{
va_list argptr;
- static char msg[2048];
+ static char msg[2048];
va_start (argptr,text);
QC_vsnprintf (msg,sizeof(msg)-1, text,argptr);
{
extern int numsourcefiles;
va_list argptr;
- char msg[2048];
+ char msg[2048];
va_start (argptr,error);
QC_vsnprintf (msg,sizeof(msg)-1, error,argptr);
numsourcefiles = 0;
#ifndef QCC
- longjmp(qcccompileerror, 1);
+ longjmp(qcccompileerror, 1);
#else
print ("Press any key\n");
getch();
int handle;
umask (0);
-
+
handle = open(filename,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
, 0666);
void ResizeBuf(int hand, int newsize)
{
-// int wasmal = qccfile[hand].buffismalloc;
+// int wasmal = qccfile[hand].buffismalloc;
char *nb;
if (qccfile[hand].buffsize >= newsize)
// qccfile[hand].buffismalloc = false;
// nb = memalloc(newsize);
// }
-
+
memcpy(nb, qccfile[hand].buff, qccfile[hand].maxofs);
// if (wasmal)
free(qccfile[hand].buff);
}
void SafeClose(int hand)
{
- externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs);
+ externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs);
// if (qccfile[hand].buffismalloc)
free(qccfile[hand].buff);
// else
return -1;
// Abort("failed to find file %s", filename);
}
- mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+2);
+ mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+2);
((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
- qcc_sourcefile->size = len;
- mem += sizeof(qcc_cachedsourcefile_t);
+ qcc_sourcefile->size = len;
+ mem += sizeof(qcc_cachedsourcefile_t);
strcpy(qcc_sourcefile->filename, filename);
qcc_sourcefile->file = mem;
qcc_sourcefile->type = FT_CODE;
-
+
externs->ReadFile(filename, mem, len+2);
mem[len] = '\n';
mem[len+1] = '\0';
*bufferptr=mem;
-
+
return len;
}
void QCC_AddFile (char *filename)
len = externs->FileSize(filename);
if (len < 0)
Abort("failed to find file %s", filename);
- mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+1);
+ mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+1);
((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
- qcc_sourcefile->size = len;
- mem += sizeof(qcc_cachedsourcefile_t);
+ qcc_sourcefile->size = len;
+ mem += sizeof(qcc_cachedsourcefile_t);
strcpy(qcc_sourcefile->filename, filename);
qcc_sourcefile->file = mem;
qcc_sourcefile->type = FT_DATA;
pbool flag_fasttrackarrays; //Faster arrays, dynamically detected, activated only in supporting engines.
pbool flag_msvcstyle; //MSVC style warnings, so msvc's ide works properly
pbool flag_assume_integer; //5 - is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
+pbool flag_filetimes;
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.
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 *);
+void *(*pHash_Get)(hashtable_t *table, const char *name);
+void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);
+void *(*pHash_Add)(hashtable_t *table, const 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, pbool saved);
QCC_type_t *QCC_PR_NewType (char *name, int basictype);
{6, "==", "EQ_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
{6, "==", "EQ_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
{6, "==", "EQ_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
-
+
{6, "!=", "NE_F", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, "!=", "NE_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_float},
{6, "!=", "NE_S", 5, ASSOC_LEFT, &type_string, &type_string, &type_float},
{6, "!=", "NE_E", 5, ASSOC_LEFT, &type_entity, &type_entity, &type_float},
{6, "!=", "NE_FNC", 5, ASSOC_LEFT, &type_function, &type_function, &type_float},
-
+
{6, "<=", "LE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, ">=", "GE", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, "<", "LT", 5, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, "=", "STOREP_FNC", 6, ASSOC_RIGHT, &type_pointer, &type_function, &type_function},
{6, "<RETURN>", "RETURN", -1, ASSOC_LEFT, &type_float, &type_void, &type_void},
-
+
{6, "!", "NOT_F", -1, ASSOC_LEFT, &type_float, &type_void, &type_float},
{6, "!", "NOT_V", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
{6, "!", "NOT_S", -1, ASSOC_LEFT, &type_vector, &type_void, &type_float},
{6, "!", "NOT_ENT", -1, ASSOC_LEFT, &type_entity, &type_void, &type_float},
{6, "!", "NOT_FNC", -1, ASSOC_LEFT, &type_function, &type_void, &type_float},
-
+
{6, "<IF>", "IF", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
{6, "<IFNOT>", "IFNOT", -1, ASSOC_RIGHT, &type_float, NULL, &type_void},
-
+
// calls returns REG_RETURN
{6, "<CALL0>", "CALL0", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL1>", "CALL1", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
- {6, "<CALL2>", "CALL2", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
- {6, "<CALL3>", "CALL3", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
+ {6, "<CALL2>", "CALL2", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
+ {6, "<CALL3>", "CALL3", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL4>", "CALL4", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL5>", "CALL5", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL6>", "CALL6", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL7>", "CALL7", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
{6, "<CALL8>", "CALL8", -1, ASSOC_LEFT, &type_function, &type_void, &type_void},
-
+
{6, "<STATE>", "STATE", -1, ASSOC_LEFT, &type_float, &type_float, &type_void},
-
+
{6, "<GOTO>", "GOTO", -1, ASSOC_RIGHT, NULL, &type_void, &type_void},
-
+
{6, "&&", "AND", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, "||", "OR", 7, ASSOC_LEFT, &type_float, &type_float, &type_float},
//Later are additions by DMW.
{7, "<CALL1H>", "CALL1H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_void},
- {7, "<CALL2H>", "CALL2H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
- {7, "<CALL3H>", "CALL3H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
+ {7, "<CALL2H>", "CALL2H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
+ {7, "<CALL3H>", "CALL3H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
{7, "<CALL4H>", "CALL4H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
{7, "<CALL5H>", "CALL5H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
{7, "<CALL6H>", "CALL6H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector},
{7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
{7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
{7, "+", "ADD_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
-
+
{7, "-", "SUB_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
{7, "-", "SUB_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float},
{7, "-", "SUB_IF", 4, ASSOC_LEFT, &type_integer, &type_float, &type_float},
{7, "!=", "NE_IF", 5, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
{7, "!=", "NE_FI", 5, ASSOC_LEFT, &type_float, &type_float, &type_integer},
-
+
&pr_opcodes[OP_DIV_I],
&pr_opcodes[OP_DIV_VF],
- &pr_opcodes[OP_BITAND],
+ &pr_opcodes[OP_BITAND_F],
&pr_opcodes[OP_BITAND_I],
&pr_opcodes[OP_BITAND_IF],
&pr_opcodes[OP_BITAND_FI],
- &pr_opcodes[OP_BITOR],
+ &pr_opcodes[OP_BITOR_F],
&pr_opcodes[OP_BITOR_I],
&pr_opcodes[OP_BITOR_IF],
&pr_opcodes[OP_BITOR_FI],
&pr_opcodes[OP_EQ_I],
&pr_opcodes[OP_EQ_IF],
&pr_opcodes[OP_EQ_FI],
-
+
&pr_opcodes[OP_NE_F],
&pr_opcodes[OP_NE_V],
&pr_opcodes[OP_NE_S],
&pr_opcodes[OP_NE_I],
&pr_opcodes[OP_NE_IF],
&pr_opcodes[OP_NE_FI],
-
- &pr_opcodes[OP_LE],
+
+ &pr_opcodes[OP_LE_F],
&pr_opcodes[OP_LE_I],
&pr_opcodes[OP_LE_IF],
&pr_opcodes[OP_LE_FI],
- &pr_opcodes[OP_GE],
+ &pr_opcodes[OP_GE_F],
&pr_opcodes[OP_GE_I],
&pr_opcodes[OP_GE_IF],
&pr_opcodes[OP_GE_FI],
- &pr_opcodes[OP_LT],
+ &pr_opcodes[OP_LT_F],
&pr_opcodes[OP_LT_I],
&pr_opcodes[OP_LT_IF],
&pr_opcodes[OP_LT_FI],
- &pr_opcodes[OP_GT],
+ &pr_opcodes[OP_GT_F],
&pr_opcodes[OP_GT_I],
&pr_opcodes[OP_GT_IF],
&pr_opcodes[OP_GT_FI],
NULL
}, { //7
- &pr_opcodes[OP_AND],
+ &pr_opcodes[OP_AND_F],
&pr_opcodes[OP_AND_I],
&pr_opcodes[OP_AND_IF],
&pr_opcodes[OP_AND_FI],
- &pr_opcodes[OP_OR],
+ &pr_opcodes[OP_OR_F],
&pr_opcodes[OP_OR_I],
&pr_opcodes[OP_OR_IF],
&pr_opcodes[OP_OR_FI],
{
case QCF_STANDARD:
case QCF_KK7:
+ case QCF_QTEST:
if (num < OP_MULSTORE_F)
return true;
return false;
case OP_LOADA_FNC:
case OP_LOADA_V:
return false; //DPFIXME: DP does not bounds check these properly. I won't generate them.
-
+
case OP_CONV_ITOF:
case OP_CONV_FTOI:
return true; //these look fine.
case OP_IFNOT_S:
case OP_IF_S:
return true;
-
+
case OP_IFNOT_F: //added, but not in dp yet
case OP_IF_F:
return false;
if (var->type->type == ev_pointer && var->type->aux_type)
{
if (var->type->aux_type->type == ev_float && wanted == ev_integer)
- return OP_CP_FTOI;
+ return OP_CP_FTOI;
if (var->type->aux_type->type == ev_integer && wanted == ev_float)
return OP_CP_ITOF;
if (o <= 0) //no conversion
return var;
-
+
return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value
}
prev = fofs;
}
}
-
+
ofs = numpr_globals;
numpr_globals+=size;
#endif
var_c = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (var_c, 0, sizeof(QCC_def_t));
+ memset (var_c, 0, sizeof(QCC_def_t));
var_c->type = type;
var_c->name = "temp";
t->size = type->size;
t->next = functemps;
functemps = t;
-
+
t->ofs = QCC_GetFreeOffsetSpace(t->size);
numtemps+=t->size;
#else
#define QCC_FreeTemps()
#endif
+void QCC_PurgeTemps(void)
+{
+ functemps = NULL;
+}
//temps that are still in use over a function call can be considered dodgy.
//we need to remap these to locally defined temps, on return from the function so we know we got them all.
t->scope = pr_scope;
t = t->next;
}
+
}
static void QCC_LockTemp(QCC_def_t *d)
{
if (var->ofs >= paramstart && var->ofs < paramend)
continue;
- fprintf(f, "local %s %s;\n", TypeName(var->type), var->name);
+ fprintf(f, "local %s %s; /* at %d */\n", TypeName(var->type), var->name, var->ofs);
}
for (t = functemps, i = 0; t; t = t->next, i++)
{
if (t->lastfunc == pr_scope)
{
- fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i);
+ fprintf(f, "local %s temp_%i; /* at %d */\n", (t->size == 1)?"float":"vector", i, t->ofs);
}
}
}
// }
// //can't convert the left componant of an assignment operation
// if (var_b && var_b->type && var_b->type != op->type_b->type)
-// var_b = QCC_SupplyConversion(var_b, op->type_b->type->type);
+// var_b = QCC_SupplyConversion(var_b, op->type_b->type->type);
}
}
//both are constants
switch (op - pr_opcodes) //improve some of the maths.
{
- case OP_BITOR:
+ case OP_BITOR_F:
optres_constantarithmatic++;
return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs)));
- case OP_BITAND:
+ case OP_BITAND_F:
optres_constantarithmatic++;
return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
case OP_MUL_F:
optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs));
- case OP_AND:
+ case OP_AND_F:
optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs));
- case OP_OR:
+ case OP_OR_F:
optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs));
case OP_MUL_V: //mul_f is actually a dot-product
//a is const, b is not
switch (op - pr_opcodes)
{
- case OP_BITOR:
- case OP_OR:
+ case OP_BITOR_F:
+ case OP_OR_F:
case OP_ADD_F:
if (G_FLOAT(var_a->ofs) == 0)
{
return var_b;
}
break;
- case OP_BITAND:
- case OP_AND:
+ case OP_BITAND_F:
+ case OP_AND_F:
if (G_FLOAT(var_a->ofs) != 0)
{
optres_constantarithmatic++;
//b is const, a is not
switch (op - pr_opcodes)
{
- case OP_BITOR:
- case OP_OR:
+ case OP_BITOR_F:
+ case OP_OR_F:
case OP_SUB_F:
case OP_ADD_F:
if (G_FLOAT(var_b->ofs) == 0)
}
break;
//no bitand_f, I don't trust the casts
- case OP_AND:
+ case OP_AND_F:
if (G_FLOAT(var_b->ofs) != 0)
{
optres_constantarithmatic++;
switch (op - pr_opcodes)
{
- case OP_AND:
+ case OP_AND_F:
if (var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
if (var_a->constant || var_b->constant)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
break;
- case OP_OR:
+ case OP_OR_F:
if (var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same");
if (var_a->constant || var_b->constant)
case OP_NE_E:
case OP_NE_FNC:
- case OP_LE:
- case OP_GE:
- case OP_LT:
- case OP_GT:
+ case OP_LE_F:
+ case OP_GE_F:
+ case OP_LT_F:
+ case OP_GT_F:
if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
break;
case OP_IFNOT_S:
case OP_IF_F:
case OP_IFNOT_F:
- case OP_IF:
- case OP_IFNOT:
+ case OP_IF_I:
+ case OP_IFNOT_I:
// if (var_a->type->type == ev_function && !var_a->temp)
// QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
if (var_a->constant && !var_a->temp)
if (numstatements)
{ //optimise based on last statement.
- if (op - pr_opcodes == OP_IFNOT)
+ if (op - pr_opcodes == OP_IFNOT_I)
{
if (opt_shortenifnots && var_a && (statements[numstatements-1].op == OP_NOT_F || statements[numstatements-1].op == OP_NOT_FNC || statements[numstatements-1].op == OP_NOT_ENT))
{
if (statements[numstatements-1].op == OP_NOT_F)
op = &pr_opcodes[OP_IF_F];
else
- op = &pr_opcodes[OP_IF];
+ op = &pr_opcodes[OP_IF_I];
numstatements--;
QCC_FreeTemp(var_a);
memcpy(&nvara, var_a, sizeof(nvara));
}
}
simplestore=false;
-
+
statement = &statements[numstatements];
numstatements++;
numstatements++;
QCC_FreeTemp(var_a);
- op = &pr_opcodes[OP_IF];
+ op = &pr_opcodes[OP_IF_I];
break;
case OP_IFNOT_S:
numstatements++;
QCC_FreeTemp(var_a);
- op = &pr_opcodes[OP_IFNOT];
+ op = &pr_opcodes[OP_IFNOT_I];
break;
case OP_IF_F:
numstatements++;
QCC_FreeTemp(var_a);
- op = &pr_opcodes[OP_IF];
+ op = &pr_opcodes[OP_IF_I];
break;
case OP_IFNOT_F:
numstatements++;
QCC_FreeTemp(var_a);
- op = &pr_opcodes[OP_IFNOT];
+ op = &pr_opcodes[OP_IFNOT_I];
break;
case OP_ADDSTORE_F:
var_c = var_a;
break;
case OP_BITSET:
- op = &pr_opcodes[OP_BITOR];
+ op = &pr_opcodes[OP_BITOR_F];
var_c = var_b;
var_b = var_a;
var_a = var_c;
QCC_UnFreeTemp(var_b);
numstatements--;
- var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND], var_b, var_a, NULL);
+ var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND_F], var_b, var_a, NULL);
QCC_FreeTemp(var_c);
statement = &statements[numstatements];
numstatements++;
-
+
QCC_FreeTemp(var_a);
QCC_FreeTemp(var_b);
if (statements[st].c == var_b->ofs)
break;
- if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H)
+ if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
need_lock = true;
- //printf("%s\n", pr_opcodes[statements[st].op].opname);
-
if (statements[st].c == var_b->ofs)
QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name);
}
if (st < 0)
QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement");
var_c = QCC_GetTemp(*op->type_c);
- if(need_lock)
- QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps
+ if (need_lock)
+ QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
statement_linenums[statement-statements] = statement_linenums[st];
statement->op = OP_ADDRESS;
statement->op = OP_DIV_F;
break;
case OP_BITSETP:
- statement->op = OP_BITOR;
+ statement->op = OP_BITOR_F;
break;
case OP_BITSETP_I:
statement->op = OP_BITOR_I;
case OP_BITCLRP:
//float pointer float
temp = QCC_GetTemp(type_float);
- statement->op = OP_BITAND;
+ statement->op = OP_BITAND_F;
statement->a = var_c ? var_c->ofs : 0;
statement->b = var_a ? var_a->ofs : 0;
statement->c = temp->ofs;
op = &pr_opcodes[OP_STOREP_F];
QCC_FreeTemp(var_c);
-
var_c = NULL;
QCC_FreeTemp(var_b);
if (statements[st].c == var_b->ofs)
break;
- if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H)
+ if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H))
need_lock = true;
if (statements[st].c == var_b->ofs)
if (st < 0)
QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_V couldn't find pointer generation");
var_c = QCC_GetTemp(*op->type_c);
- if(need_lock)
- QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps
+ if (need_lock)
+ QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/
statement_linenums[statement-statements] = statement_linenums[st];
statement->op = OP_ADDRESS;
op = &pr_opcodes[OP_STOREP_V];
-
-
+
+
QCC_FreeTemp(var_c);
var_c = NULL;
QCC_FreeTemp(var_b);
if (outstatement)
*outstatement = statement;
-
+
statement_linenums[statement-statements] = pr_source_line;
statement->op = op - pr_opcodes;
statement->a = var_a ? var_a->ofs : 0;
void QCC_PR_Statement3 ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_def_t *var_c, int force)
{
- QCC_dstatement_t *statement;
+ QCC_dstatement_t *statement;
if (!force && !QCC_OPCodeValid(op))
{
QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target\n", op->name, op->opname);
}
- statement = &statements[numstatements];
+ statement = &statements[numstatements];
numstatements++;
-
+
statement_linenums[statement-statements] = pr_source_line;
statement->op = op - pr_opcodes;
statement->a = var_a ? var_a->ofs : 0;
}
}
else if (pr_immediate_type == type_integer)
- {
+ {
if ( G_INT(cn->ofs) == pr_immediate._int )
{
QCC_PR_Lex ();
return cn;
}
}
- else
+ else
QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "weird immediate type");
}
if (pr_immediate_type == type_string)
pr_immediate.string = QCC_CopyString (pr_immediate_string);
-
+
memcpy (qcc_pr_globals + cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
-
+
QCC_PR_Lex ();
return cn;
if (e->type->type != ev_string)
return;
-
+
if (!e->ofs || e->temp || !e->constant)
return;
n = G_STRING(e->ofs);
if (e->type->type != ev_string)
return;
-
+
if (!e->ofs || e->temp || !e->constant)
- return;
+ return;
n = G_STRING(e->ofs);
if (!*n)
return;
if (e->type->type != ev_string)
return;
-
+
if (!e->ofs || e->temp || !e->constant)
- return;
+ return;
n = G_STRING(e->ofs);
if (!*n)
return;
if (e->type->type != ev_string)
return;
-
+
if (!e->ofs || e->temp || !e->constant)
return;
n = G_STRING(e->ofs);
if (e->type->type != ev_string)
return;
-
+
if (!e->ofs || e->temp || !e->constant)
return;
n = G_STRING(e->ofs);
}
else
np = t->num_parms;
-
+
if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs)
{ //we're entering OO code with a different self.
//eg: other.touch(self)
}
}
}
-
+
//restore the class owner
if (oself)
QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false);
*/
QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could have no name set if it's a field call.
{
- QCC_def_t *e, *d, *old, *oself, *out;
+ QCC_def_t *e, *d, *old = {0}, *oself, *out; // warning: \91old\92 may be used uninitialized in this function
int arg;
QCC_type_t *t, *p;
int extraparms=false;
int np;
- int laststatement = numstatements;
int callconvention;
out = QCC_GetTemp(type_float);
else
out = &def_ret;
-
+
if (e)
{
if (d)
}
else
old = NULL;
-
+
if (e)
{
if (d)
if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{
- t = QCC_PR_Statement(&pr_opcodes[OP_GT], d, e, NULL);
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], t, 0, &st));
+ t = QCC_PR_Statement(&pr_opcodes[OP_GT_F], d, e, NULL);
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], t, 0, &st));
st->b = 3;
t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], d, e, NULL);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_GOTO], 0, 0, &st));
st->a = 3;
}
-
+
t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], e, d, NULL);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
QCC_FreeTemp(t);
out = QCC_GetTemp(type_vector);
else
out = &def_ret;
-
+
if (e)
{
if (d)
}
else
old = NULL;
-
+
if (e)
{
if (d)
if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{
t = QCC_GetTemp(type_float);
- QCC_PR_SimpleStatement(OP_GT, d->ofs+2, e->ofs+2, t->ofs, false);
- QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
+ QCC_PR_SimpleStatement(OP_GT_F, d->ofs+2, e->ofs+2, t->ofs, false);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
}
-
+
t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false);
QCC_FreeTemp(t);
QCC_PR_SimpleStatement(OP_ADD_F, OFS_RETURN, d->ofs+2, OFS_RETURN+2, false);
-
-
+
+
QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false);
if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{
t = QCC_GetTemp(type_float);
- QCC_PR_SimpleStatement(OP_GT, d->ofs+1, e->ofs+1, t->ofs, false);
- QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
+ QCC_PR_SimpleStatement(OP_GT_F, d->ofs+1, e->ofs+1, t->ofs, false);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
}
-
+
t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false);
if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{
t = QCC_GetTemp(type_float);
- QCC_PR_SimpleStatement(OP_GT, d->ofs, e->ofs, t->ofs, false);
- QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false);
+ QCC_PR_SimpleStatement(OP_GT_F, d->ofs, e->ofs, t->ofs, false);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
QCC_PR_SimpleStatement(OP_GOTO, 3, 0, 0, false);
}
-
+
t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false);
QCC_PR_Expect(")");
}
-
+
if (def_ret.temp->used)
{
old = QCC_GetTemp(def_ret.type);
return d;
}
-
+
def_ret.type = rettype;
return &def_ret;
}
QCC_def_t *QCC_MakeIntDef(int value)
{
QCC_def_t *cn;
-
+
// check for a constant with the same value
for (cn=pr.def_head.next ; cn ; cn=cn->next)
{
typechecks++;
if ( G_INT(cn->ofs) == value )
- {
+ {
return cn;
- }
+ }
}
// allocate a new one
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
-
- G_INT(cn->ofs) = value;
-
+
+ G_INT(cn->ofs) = value;
+
return cn;
}
QCC_def_t *QCC_MakeVectorDef(float a, float b, float c)
{
QCC_def_t *cn;
-
+
// check for a constant with the same value
for (cn=pr.def_head.next ; cn ; cn=cn->next)
{
if ( G_FLOAT(cn->ofs+0) == a &&
G_FLOAT(cn->ofs+1) == b &&
G_FLOAT(cn->ofs+2) == c)
- {
+ {
return cn;
- }
+ }
}
// allocate a new one
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]);
-
+
G_FLOAT(cn->ofs+0) = a;
G_FLOAT(cn->ofs+1) = b;
G_FLOAT(cn->ofs+2) = c;
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
-
+
Hash_AddKey(&floatconstdefstable, fi.i, cn, qccHunkAlloc(sizeof(bucket_t)));
-
- G_FLOAT(cn->ofs) = value;
-
+
+ G_FLOAT(cn->ofs) = value;
+
return cn;
}
// copy the immediate to the global area
cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]);
-
+
string = QCC_CopyString (value);
pHash_Add(tbl, strings+string, cn, qccHunkAlloc(sizeof(bucket_t)));
-
- G_INT(cn->ofs) = string;
-
+
+ G_INT(cn->ofs) = string;
+
return cn;
}
ft = QCC_PR_FindType(ft);
sprintf(membername, "__f_%s_%i", ft->name, ++basictypefield[mt->type]);
f = QCC_PR_GetDef(ft, membername, NULL, true, 1, true);
-
+
for (o = 0; o < m->type->size; o++)
((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs];
if (!virt)
QCC_Error(ERR_INTERNAL, "spawn function was not defined\n");
QCC_PR_SimpleStatement(OP_CALL0, virt->ofs, 0, 0, false); //calling convention doesn't come into it.
-
+
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], &def_ret, ed, NULL));
ed->references = 1; //there may be no functions.
};
char membername[2048];
-
+
// if the token is an immediate, allocate a constant for it
if (pr_token_type == tt_immediate)
return QCC_PR_ParseImmediate ();
// look through the defs
od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false);
-
+
if (!d)
{
if ( (!strcmp(name, "random" )) ||
QCC_type_t *newtype;
if (ao)
{
- numstatements--; //remove the last statement
+ numstatements--; //remove the last statement
nd = QCC_PR_Expression (TOP_PRIORITY, 0);
QCC_PR_Expect("]");
- if (d->type->size != 1) //we need to multiply it to find the offset.
+ if (d->type->size != 1) //we need to multiply it to find the offset.
{
if (ao->type->type == ev_integer)
nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], nd, QCC_MakeIntDef(d->type->size), NULL); //get add part
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
break;
case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
+ nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
break;
case ev_field:
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
def_parms[0].type = type_float;
funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false);
-
+
args[0] = ao;
nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1);
nd->type = d->type->aux_type;
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
break;
case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
+ nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
break;
case ev_field:
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def.
}
else
QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type");
-
+
d->type = newtype;
goto reloop;
}
d = od;
nd = QCC_MakeIntDef(type->ofs);
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
+ ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
//so that we may offset it and readd it.
}
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def.
break;
case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, ao, NULL); //get pointer to precise def.
+ nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, ao, NULL); //get pointer to precise def.
break;
case ev_field:
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, ao, NULL); //get pointer to precise def.
QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
nd = NULL;
break;
- }
+ }
d=nd;
break;
for (j = type->num_parms; j;j--)
type++;
}
- }
+ }
if (!i)
QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
d = od;
nd = QCC_MakeIntDef(type->ofs);
- ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
+ ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part
//so that we may offset it and readd it.
}
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def.
break;
case ev_entity:
- nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
+ nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def.
break;
case ev_field:
nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def.
QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler");
nd = NULL;
break;
- }
+ }
d=nd;
break;
for (j = type->num_parms; j;j--)
type++;
}
- }
+ }
if (!i)
QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name);
break;
}
}
-*/
+*/
if (!keyword_class)
return d;
case ev_field:
d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL);
nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (nd, 0, sizeof(QCC_def_t));
+ memset (nd, 0, sizeof(QCC_def_t));
nd->type = field->type->aux_type;
nd->ofs = d->ofs;
nd->temp = d->temp;
{ //complicated for a typecast
d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL);
nd = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (nd, 0, sizeof(QCC_def_t));
+ memset (nd, 0, sizeof(QCC_def_t));
nd->type = field->type->aux_type;
nd->ofs = d->ofs;
nd->temp = d->temp;
else
QCC_PR_IncludeChunk(".", false, NULL);
}
- }
+ }
return d;
}
}
return e;
}
-
+
if (QCC_PR_CheckToken ("!"))
{
e = QCC_PR_Expression (NOT_PRIORITY, EXPR_DISALLOW_COMMA|EXPR_WARN_ABOVE_1);
}
return e2;
}
-
+
if (QCC_PR_CheckToken ("("))
{
if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts
QCC_PR_ParseWarning (0, "Not all vars make sence as floats");
e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (e2, 0, sizeof(QCC_def_t));
+ memset (e2, 0, sizeof(QCC_def_t));
e2->type = type_float;
e2->ofs = e->ofs;
e2->constant = true;
QCC_PR_Expect (")");
e = QCC_PR_Term();
e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));
- memset (e2, 0, sizeof(QCC_def_t));
+ memset (e2, 0, sizeof(QCC_def_t));
e2->type = classtype;
e2->ofs = e->ofs;
e2->constant = true;
return 1;
}
}
-
+
/* if (from->type->type == ev_pointer && from->type->aux_type->type == to)
return 1;
if (QCC_PR_CheckToken ("?"))
{
QCC_dstatement32_t *fromj, *elsej;
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, NULL, &fromj));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, NULL, &fromj));
e = QCC_PR_Expression(TOP_PRIORITY, 0);
e2 = QCC_GetTemp(e->type);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL));
optres_logicops++;
st = &statements[numstatements];
if (*op->name == '&') //statement 3 because we don't want to optimise this into if from not ifnot
- QCC_PR_Statement3(&pr_opcodes[OP_IFNOT], e, NULL, NULL, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_IFNOT_I], e, NULL, NULL, false);
else
- QCC_PR_Statement3(&pr_opcodes[OP_IF], e, NULL, NULL, false);
+ QCC_PR_Statement3(&pr_opcodes[OP_IF_I], e, NULL, NULL, false);
}
e2 = QCC_PR_Expression (priority-1, exprflags);
}
else
type_c = ev_void;
-
+
oldop = op;
bestop = NULL;
- numconversions = 32767;
+ numconversions = 32767;
while (op)
{
if (!(type_c != ev_void && type_c != (*op->type_c)->type))
if (c == 0)//can't get less conversions than 0...
break;
}
- }
+ }
else
break;
}
}
else
e = QCC_PR_Statement (op, e, e2, NULL);
-
+
if (type_c != ev_void/* && type_c != ev_string*/) // field access gets type from field
e->type = e2->type->aux_type;
if (priority > 1 && exprflags & EXPR_WARN_ABOVE_1)
QCC_PR_ParseWarning(0, "You may wish to add brackets after that ! operator");
-
+
break;
}
if (!op)
QCC_FreeTemp(e);
return QCC_PR_Expression(TOP_PRIORITY, exprflags);
}
-
+
return e;
}
if (pr_subscopedlocals)
{
- for (e2 = pr.localvars; e2 != e; e2 = e2->nextlocal)
+ for (e2 = pr.localvars; e2 != e; e2 = e2->nextlocal)
{
- Hash_RemoveData(&localstable, e2->name, e2);
+ if (!e2->subscoped_away)
+ {
+ Hash_RemoveData(&localstable, e2->name, e2);
+ e2->subscoped_away = true;
+ }
}
}
return;
}
-
+
if (QCC_PR_CheckKeyword(keyword_return, "return"))
{
/*if (pr_classtype)
QCC_PR_Expect (";");
return;
}
-
+
if (QCC_PR_CheckKeyword(keyword_while, "while"))
{
continues = num_continues;
else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) //special case, as negative 0 is also zero
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
else
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
}
QCC_PR_Expect (")"); //after the line number is noted..
QCC_PR_ParseStatement ();
numtemp = 0;
if (e)
- QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, 0, &patch1));
+ QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
else
patch1 = NULL;
if (!QCC_PR_CheckToken(";"))
if (breaks != num_breaks)
{
for(i = breaks; i < num_breaks; i++)
- {
+ {
patch1 = &statements[pr_breaks[i]];
statements[pr_breaks[i]].a = &statements[numstatements] - patch1;
}
else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2));
else
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, NULL, &patch2));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &patch2));
patch2->b = patch1 - patch2;
}
return;
}
-
+
if (QCC_PR_CheckKeyword(keyword_local, "local"))
{
- QCC_type_t *functionsclasstype = pr_classtype;
+ QCC_type_t *functionsclasstype = pr_classtype;
// if (locals_end != numpr_globals) //is this breaking because of locals?
// QCC_PR_ParseWarning("local vars after temp vars\n");
QCC_PR_ParseDefs (NULL);
QCC_PR_Expect(";");
return;
}
-
+
if (QCC_PR_CheckKeyword(keyword_if, "if"))
{
pbool negate = QCC_PR_CheckKeyword(keyword_not, "not");
else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1));
else
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, 0, &patch1));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, 0, &patch1));
}
else
{
else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])))
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
else
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1));
}
QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after
//default:
// break;
//}
-
+
//to
// x = CONDITION, goto start
//x is emitted in an opcode, stored as a register that we cannot access later.
//it should be possible to nest these.
-
+
switchtype = e->type;
switch(switchtype->type)
{
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], e, 0, &patch1));
QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after
-
+
oldst = numstatements;
QCC_PR_ParseStatement ();
if (e->type->type == ev_float)
{
- e2 = QCC_PR_Statement (&pr_opcodes[OP_GE], e, pr_casesdef[i], NULL);
- e3 = QCC_PR_Statement (&pr_opcodes[OP_LE], e, pr_casesdef2[i], NULL);
- e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL);
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_F], e, pr_casesdef[i], NULL);
+ e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_F], e, pr_casesdef2[i], NULL);
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_F], e2, e3, NULL);
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
patch3->b = &statements[pr_cases[i]] - patch3;
}
else if (e->type->type == ev_integer)
{
e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_I], e, pr_casesdef[i], NULL);
e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_I], e, pr_casesdef2[i], NULL);
- e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL);
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
+ e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_I], e2, e3, NULL);
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
patch3->b = &statements[pr_cases[i]] - patch3;
}
else
e2 = NULL;
break;
}
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3));
}
else
{
else if (e->type->type == ev_float)
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3));
else
- QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch3));
+ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch3));
}
patch3->b = &statements[pr_cases[i]] - patch3;
}
}
- }
+ }
}
if (defaultcase>=0)
{
if (s1->type->type != ev_float || def->type->type != ev_float)
QCC_PR_ParseError(ERR_STATETYPEMISMATCH, "state type mismatch");
-
+
if (QCC_OPCodeValid(&pr_opcodes[OP_CSTATE]))
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_CSTATE], s1, def, NULL));
//make sure the frame is within the bounds given.
ftemp = frame->temp;
frame->temp = NULL;
- t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL);
- t2 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL);
- t1 = QCC_PR_Statement(&pr_opcodes[OP_OR], t1, t2, NULL);
- QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 2, 0, false);
+ t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
+ t2 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
+ t1 = QCC_PR_Statement(&pr_opcodes[OP_OR_F], t1, t2, NULL);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 2, 0, false);
QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false);
- t1 = QCC_PR_Statement(&pr_opcodes[OP_GE], def, s1, NULL);
- QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 7, 0, false);
+ t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 7, 0, false);
QCC_FreeTemp(t1); //this block is the 'it's in a forwards direction'
QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
- t1 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL);
- QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false);
+ t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
QCC_UnFreeTemp(frame);
QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
//reverse animation.
QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false);
- t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL);
- QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false);
+ t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
+ QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
QCC_UnFreeTemp(frame);
if (cycle_wrapped)
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL));
-
+
//self.frame = frame happens with the normal state opcode.
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], frame, pr_scope, NULL));
}
return;
}
-
+
if (pr_token_type != tt_immediate || pr_immediate_type != type_float)
QCC_PR_ParseError (ERR_STATETYPEMISMATCH, "state frame must be a number");
s1 = QCC_PR_ParseImmediate ();
-
+
QCC_PR_CheckToken (",");
name = QCC_PR_ParseName ();
pr_scope = NULL;
def = QCC_PR_GetDef (type_function, name, NULL, true, 1, false);
pr_scope = sc;
-
+
QCC_PR_Expect ("]");
-
+
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], s1, def, NULL));
}
}
}
else
- {
+ {
if (pr_opcodes[op].type_a != &type_void)
a = QCC_PR_ParseValue(pr_classtype, false);
else
QCC_PR_Statement3(&pr_opcodes[op], a, b, c, true);
}
-
+
QCC_PR_Expect(";");
return;
}
if (statements[last-1].op == OP_DONE)
last--; //don't want the done
-
+
if (rettype != ev_void)
if (statements[last-1].op != OP_RETURN)
{
locals_start = MAX_REGS;
locals_end = newofs;
-
+
optres_locals_marshalling+=newofs-MAX_REGS;
for (local = pr.localvars; local; local = local->nextlocal)
break;
}
if (param)
- fprintf(asmfile, "%s %s", TypeName(type), param->name);
+ fprintf(asmfile, "%s %s /* at %d */", TypeName(type), param->name, o);
else
- fprintf(asmfile, "%s", TypeName(type));
+ fprintf(asmfile, "%s /* at %d */", TypeName(type), o);
o += type->size;
}
if (type->num_parms < 0)
QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
-
+
f->builtin = 0;
//
// define the parms
QCC_def_t *eq;
if (min == max || min+1 == max)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = array->ofs + min*array->type->size;
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
else
st = NULL;
QCC_def_t *eq;
if (min == max || min+1 == max)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = array->ofs + min*3;
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
else
st = NULL;
locals_end = numpr_globals;
df->locals = locals_end - df->parm_start;
QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp, false);
- QCC_PR_Statement3(pr_opcodes+OP_BITAND, temp, temp, temp, false);//round down to int
+ QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int
QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up
if (fasttrackpossible)
{
- QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st);
+ QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st);
//fetch_gbl takes: (float size, variant array[]), float index, variant pos
//note that the array size is coded into the globals, one index before the array.
div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false);
intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false);
- eq = QCC_PR_Statement(pr_opcodes+OP_GE, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st);
div3->references++;
- QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
+ QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), div3, false);
- QCC_PR_Statement3(pr_opcodes+OP_BITAND, div3, div3, intdiv3, false);
+ QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, div3, div3, intdiv3, false);
QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false);
QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false);
QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
QCC_FreeTemp(div3);
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(0+0.5f), NULL);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(0+0.5f), NULL);
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 0;
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(1+0.5f), NULL);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(1+0.5f), NULL);
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 1;
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(2+0.5), NULL);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(2+0.5), NULL);
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 2;
}
else
{
- QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
+ QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize);
}
{
eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 3;
if (array->type->size == 3)
QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st);
if (max-min>4)
{
- eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef((float)mid), NULL);
+ eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef((float)mid), NULL);
QCC_UnFreeTemp(index);
- QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st));
+ QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
}
else
st = NULL;
{
QCC_dstatement_t *st;
- QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st);
+ QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st);
//note that the array size is coded into the globals, one index before the array.
QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats
st->b = &statements[numstatements] - st;
}
- QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false);
+ QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize);
QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
strcpy (def->name, newname);
def->type = type;
- def->scope = scope;
+ def->scope = scope;
def->saved = saved;
// if (arraysize>1)
{
int partnum;
QCC_type_t *parttype;
- parttype = type->param;
+ parttype = type->param;
for (partnum = 0; partnum < type->num_parms; partnum++)
{
switch (parttype->type)
case ev_float:
case ev_string:
case ev_entity:
- case ev_field:
+ case ev_field:
case ev_pointer:
case ev_integer:
case ev_struct:
break;
}
parttype=parttype->next;
- }
+ }
}
else if (type->type == ev_vector)
{ //do the vector thing.
{
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)
+ if (arraysize <= 1 && first->type->type != ev_field)
first->constant = false;
if (scope)
pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
if (!scope && asmfile)
- fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name);
+ fprintf(asmfile, "%s %s; /* at %d */\n", TypeName(first->type), first->name, first->ofs);
}
return first;
strcpy (def->name, newname);
def->type = type;
- def->scope = scope;
+ def->scope = scope;
def->ofs = QCC_GetFreeOffsetSpace(1);
((int *)qcc_pr_globals)[def->ofs] = *fieldofs;
- *fieldofs++;
+ fieldofs++;
if (!first)
first = def;
}
type = parttype;
parttype=parttype->next;
- }
+ }
}
}
QCC_def_t *def, *d;
QCC_function_t *f;
QCC_dfunction_t *df;
- int i;
- extern pbool defaultstatic;
+ int i = 0; // warning: \91i\92 may be used uninitialized in this function
pbool shared=false;
pbool isstatic=defaultstatic;
pbool externfnc=false;
pbool isconstant = false;
pbool isvar = false;
- pbool noref = false;
+ pbool noref = defaultnoref;
pbool nosave = false;
pbool allocatenew = true;
pbool inlinefunction = false;
if (QCC_PR_CheckToken("}"))
break;
QCC_PR_Expect(",");
+ if (QCC_PR_CheckToken("}"))
+ break; // accept trailing comma
}
}
else
if (QCC_PR_CheckToken("}"))
break;
QCC_PR_Expect(",");
+ if (QCC_PR_CheckToken("}"))
+ break; // accept trailing comma
}
}
QCC_PR_Expect(";");
}
//check for an array
-
+
if ( QCC_PR_CheckToken ("[") )
{
char *oldprfile = pr_file_p;
def->references++;
if (!def->initialized && shared) //shared count as initiialised
- {
+ {
def->shared = shared;
def->initialized = true;
}
continue;
}
-#pragma message("this is experimental")
if (pr_scope)
{
d = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
+ if (typecmp(def->type, d->type))
+ QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name);
if (d->constant)
{
- for (i = 0; i < d->type->size; i++)
+ for (i = 0; (unsigned)i < def->type->size; i++)
G_INT(def->ofs+i) = G_INT(d->ofs+i);
def->constant = !isvar;
def->initialized = 1;
}
continue;
}
-
+
else if (type->type == ev_function)
{
if (isvar)
def->constant = false;
else
def->constant = true;
- if (QCC_PR_CheckImmediate("0"))
+ if (QCC_PR_CheckImmediate("0") || QCC_PR_CheckImmediate("0i"))
{
def->constant = 0;
def->initialized = 1; //fake function
{
df->parm_size[i] = parm->size;
}
-
+
continue;
}
def->constant = false;
// if (constant)
// QCC_PR_ParseError("const used on a struct isn't useful");
-
+
//FIXME: should do this recursivly
QCC_PR_Expect("{");
for (arraypart = 0; arraypart < arraysize; arraypart++)
d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i;
*/
- G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0;
+ G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0;
}
QCC_PR_Expect("}");
}
}
break;
default:
- QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type);
+ QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type);
QCC_PR_Lex();
break;
}
def->initialized = 1;
}
- if (isconstant && type->type == ev_field)
- def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant.
+ if (type->type == ev_field)
+ {
+ if (isconstant)
+ def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant.
+ else if (isvar)
+ def->constant = 0;
+ else
+ def->constant = 1;
+ }
else
def->constant = isconstant;
}
-
+
} while (QCC_PR_CheckToken (","));
if (type->type == ev_function)
============
*/
pbool QCC_PR_CompileFile (char *string, char *filename)
-{
+{
jmp_buf oldjb;
if (!pr.memory)
QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear");
QCC_PR_ClearGrabMacros (); // clear the frame macros
compilingfile = filename;
-
+
if (opt_filenames)
{
optres_filenames += strlen(filename);
}
pr_scope = NULL; // outside all functions
-
+
QCC_PR_ParseDefs (NULL);
}
memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
-
+
return (pr_error_count == 0);
}
#endif
#include "time.h"
+// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
+#ifdef __MINGW64__
+#ifndef QCCONLY
+ #if (_MSC_VER >= 1400)
+ //with MSVC 8, use MS extensions
+ #define snprintf linuxlike_snprintf_vc8
+ int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
+ #else
+ //msvc crap
+ #define snprintf linuxlike_snprintf
+ int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf linuxlike_vsnprintf
+ int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
+ #endif
+#endif
+#endif
+
#define MEMBERFIELDNAME "__m%s"
#define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc
//also meant to include it.
void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
{
- char fullname[10248];
- char *stripfrom;
+ char fullname[1024];
int doubledots;
char *end = fullname;
return;
doubledots = 0;
+ /*count how far up we need to go*/
while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
{
newfile+=3;
currentfile += strlen(rootpath); //could this be bad?
- for(stripfrom = currentfile+strlen(currentfile)-1; stripfrom>currentfile; stripfrom--)
+ strcpy(fullname, rootpath);
+ end = fullname+strlen(end);
+ if (*fullname && end[-1] != '/')
+ {
+ strcpy(end, "/");
+ end = end+strlen(end);
+ }
+ strcpy(end, currentfile);
+ end = end+strlen(end);
+
+ while (end > fullname)
{
- if (*stripfrom == '/' || *stripfrom == '\\')
+ end--;
+ /*stop at the slash, unless we're meant to go further*/
+ if (*end == '/' || *end == '\\')
{
- if (doubledots>0)
- doubledots--;
- else
+ if (!doubledots)
{
- stripfrom++;
+ end++;
break;
}
+ doubledots--;
}
}
- strcpy(end, rootpath); end = end+strlen(end);
- if (*fullname && end[-1] != '/')
- {
- strcpy(end, "/");
- end = end+strlen(end);
- }
- strncpy(end, currentfile, stripfrom - currentfile); end += stripfrom - currentfile; *end = '\0';
+
strcpy(end, newfile);
QCC_Include(fullname);
}
+pbool defaultnoref;
pbool defaultstatic;
int ForcedCRC;
int QCC_PR_LexInteger (void);
int ParsePrecompilerIf(void)
{
CompilerConstant_t *c;
- int eval;
- char *start = pr_file_p;
+ int eval = 0;
+ //char *start = pr_file_p; //warning: unused variable âstartâ
if (!QCC_PR_SimpleGetToken())
- {
+ {
if (*pr_file_p == '(')
{
eval = ParsePrecompilerIf();
eval = true;
if (ifmode == 1)
- eval = eval?false:true;
+ eval = eval?false:true;
}
while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
}
}
else if (!strncmp(directive, "endif", 5))
- {
+ {
while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
{
pr_file_p++;
- }
+ }
if (ifs <= 0)
QCC_PR_ParseError(ERR_NOPRECOMPILERIF, "unmatched #endif");
else
return true;
}
else if (!strncmp(directive, "error", 5))
- {
+ {
pr_file_p = directive+5;
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
QCC_PR_ParseError(ERR_HASHERROR, "#Error: %s", msg);
}
else if (!strncmp(directive, "warning", 7))
- {
+ {
pr_file_p = directive+7;
for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
QCC_PR_ParseWarning(WARN_PRECOMPILERMESSAGE, "#warning: %s", msg);
}
else if (!strncmp(directive, "message", 7))
- {
+ {
pr_file_p = directive+7;
for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
else if (!strncmp(directive, "copyright", 9))
{
pr_file_p = directive+9;
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
pr_file_p=directive+4;
if (!strncmp(pr_file_p, "id", 2))
pr_file_p+=3;
- else
+ else
{
- ifmode = QCC_PR_LexInteger();
+ ifmode = QCC_PR_LexInteger();
if (ifmode == 0)
ifmode = 1;
pr_file_p++;
}
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
else if (ifmode <= 5)
strcpy(QCC_Packname[ifmode-1], msg);
else
- QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
+ QCC_PR_ParseError(ERR_TOOMANYPACKFILES, "No more than 5 packs are allowed");
}
else if (!strncmp(directive, "forcecrc", 8))
- {
+ {
pr_file_p=directive+8;
- ForcedCRC = QCC_PR_LexInteger();
+ ForcedCRC = QCC_PR_LexInteger();
pr_file_p++;
-
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
{
pr_file_p++;
- }
+ }
}
else if (!strncmp(directive, "includelist", 11))
{
if (*pr_file_p == '\r')
pr_file_p++;
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
pr_file_p++;
}
}
-
+
while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
{
pr_file_p++;
{
if (*pr_file_p == '\n')
{
- QCC_PR_ParseError(0, "#include continued over line boundy\n");
+ QCC_PR_ParseError(0, "#include continued over line boundry\n");
break;
}
msg[a++] = *pr_file_p;
}
}
else if (!strncmp(directive, "datafile", 8))
- {
+ {
pr_file_p=directive+8;
while(*pr_file_p <= ' ')
pr_file_p++;
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
printf("Outputfile: %s\n", destfile);
pr_file_p++;
-
- for (a = 0; a < 1023 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
+
+ for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
}
msg[a++] = *pr_file_p;
}
-
+
msg[a] = '\0';
{
char *end;
{
ForcedCRC = atoi(msg);
}
+ else if (!strncmp(qcc_token, "noref", 8))
+ {
+ defaultnoref = atoi(msg);
+ }
else if (!strncmp(qcc_token, "defaultstatic", 13))
{
defaultstatic = atoi(msg);
{
#define MAXSOURCEFILESLIST 8
extern char sourcefileslist[MAXSOURCEFILESLIST][1024];
- extern int currentsourcefile;
+ //extern int currentsourcefile; // warning: unused variable âcurrentsourcefileâ
extern int numsourcefiles;
int i;
qcc_targetformat = QCF_STANDARD;
else if (!QC_strcasecmp(msg, "DEBUG"))
qcc_targetformat = QCF_FTEDEBUG;
+ else if (!QC_strcasecmp(msg, "QTEST"))
+ qcc_targetformat = QCF_QTEST;
else
QCC_PR_ParseWarning(WARN_BADTARGET, "Unknown target \'%s\'. Ignored.", msg);
}
#ifndef QCCONLY
p=0;
- s2 = qcc_token;
+ s2 = qcc_token;
if (!strncmp(s2, "./", 2))
s2+=2;
else
int c;
int len;
char tmpbuf[2048];
-
+
char *text;
char *oldf;
int oldline;
pr_file_p = oldf-1;
QCC_PR_LexWhitespace();
if (*pr_file_p != '\"') //annother string
- break;
+ break;
}
QCC_PR_LexWhitespace();
- text = pr_file_p;
-
+ text = pr_file_p;
+
} while (1);
strcpy(pr_token, tmpbuf);
char *end, *cnst;
int texttype=0;
-
+
len = 0;
pr_file_p++;
do
pr_token[len] = 0;
pr_token_type = tt_immediate;
pr_immediate_type = type_string;
- strcpy (pr_immediate_string, pr_token);
+ strcpy (pr_immediate_string, pr_token);
return;
}
else if (c == '#')
{
int c;
int len;
-
+
len = 0;
c = *pr_file_p;
if (pr_file_p[0] == '0' && pr_file_p[1] == 'x')
base = 10;
while((c = *pr_file_p))
- {
+ {
if (c >= '0' && c <= '9')
{
pr_token[tokenlen++] = c;
break;
}
else
- {
+ {
break;
}
pr_file_p++;
{
int c;
int len;
-
+
len = 0;
c = *pr_file_p;
do
void QCC_PR_LexVector (void)
{
int i;
-
+
pr_file_p++;
if (*pr_file_p == '\\')
{
int c;
int len;
-
+
len = 0;
c = *pr_file_p;
do
len++;
pr_file_p++;
c = *pr_file_p;
- } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
- || (c >= '0' && c <= '9'));
+ } while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
+ || (c >= '0' && c <= '9'));
pr_token[len] = 0;
- pr_token_type = tt_name;
+ pr_token_type = tt_name;
}
/*
int i;
int len;
char *p;
-
+
pr_token_type = tt_punct;
-
+
for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
{
len = strlen(p);
return;
}
}
-
+
QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
}
-
+
/*
==============
PR_LexWhitespace
void QCC_PR_LexWhitespace (void)
{
int c;
-
+
while (1)
{
// skip whitespace
pr_file_p++;
}
}
-
+
// skip // comments
if (c=='/' && pr_file_p[1] == '/')
{
QCC_PR_NewLine(false);
continue;
}
-
+
// skip /* */ comments
if (c=='/' && pr_file_p[1] == '*')
{
pr_file_p+=2;
continue;
}
-
+
break; // a real character has been found
}
}
==============
*/
void QCC_PR_LexGrab (void)
-{
+{
pr_file_p++; // skip the $
// if (!QCC_PR_SimpleGetToken ())
// QCC_PR_ParseError ("hanging $");
QCC_PR_LexMacroName();
if (!*pr_token)
QCC_PR_ParseError (ERR_BADFRAMEMACRO, "hanging $");
-
+
// check for $frame
if (!STRCMP (pr_token, "frame") || !STRCMP (pr_token, "framesave"))
{
{
QCC_PR_LexMacroName ();
pr_macrovalue = atoi(pr_token);
-
+
QCC_PR_Lex ();
}
else if (!STRCMP (pr_token, "framerestore"))
QCC_PR_LexMacroName ();
QCC_PR_ExpandMacro();
pr_macrovalue = (int)pr_immediate._float;
-
+
QCC_PR_Lex ();
}
else if (!STRCMP (pr_token, "modelname"))
pr_macrovalue = i;
else
i = 0;
-
+
QCC_PR_Lex ();
}
// look for a frame name macro
Hash_Remove(&compconstantstable, name);
return true;
- /*
- a = c-CompilerConstant;
-// for (a = 0; a < numCompilerConstants; a++)
- {
-// if (!STRCMP(name, CompilerConstant[a].name))
- {
- memmove(&CompilerConstant[a], &CompilerConstant[a+1], sizeof(CompilerConstant_t) * (numCompilerConstants-a));
- numCompilerConstants--;
-
-
-
-
- if (!STRCMP(name, "OP_NODUP"))
- qccop_noduplicatestrings = false;
-
- if (!STRCMP(name, "OP_COMP_ALL")) //group
- {
- QCC_PR_UndefineName("OP_COMP_STATEMENTS");
- QCC_PR_UndefineName("OP_COMP_DEFS");
- QCC_PR_UndefineName("OP_COMP_FIELDS");
- QCC_PR_UndefineName("OP_COMP_FUNCTIONS");
- QCC_PR_UndefineName("OP_COMP_STRINGS");
- QCC_PR_UndefineName("OP_COMP_GLOBALS");
- QCC_PR_UndefineName("OP_COMP_LINES");
- QCC_PR_UndefineName("OP_COMP_TYPES");
- }
-
- return true;
- }
- }
-// return false;
-*/
}
CompilerConstant_t *QCC_PR_DefineName(char *name)
// QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS);
if (strlen(name) >= MAXCONSTANTLENGTH || !*name)
- QCC_PR_ParseError(ERR_CONSTANTTOOLONG, "Compiler constant name length is too long or short");
-
+ QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short");
+
cnst = pHash_Get(&compconstantstable, name);
- if (cnst )
+ if (cnst)
{
QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "Duplicate definition for Precompiler constant %s", name);
Hash_Remove(&compconstantstable, name);
cnst->numparams = 0;
strcpy(cnst->name, name);
cnst->namelen = strlen(name);
- *cnst->value = '\0';
+ cnst->value = cnst->name + strlen(cnst->name);
for (i = 0; i < MAXCONSTANTPARAMS; i++)
cnst->params[i][0] = '\0';
pHash_Add(&compconstantstable, cnst->name, cnst, qccHunkAlloc(sizeof(bucket_t)));
- if (!STRCMP(name, "OP_NODUP"))
- opt_noduplicatestrings = true;
-
-
- if (!STRCMP(name, "OP_TIME")) //group - optimize for a fast compiler
- {
- QCC_PR_UndefineName("OP_SIZE");
- QCC_PR_UndefineName("OP_SPEED");
-
- QCC_PR_UndefineName("OP_NODUP");
- QCC_PR_UndefineName("OP_COMP_ALL");
- }
-
- if (!STRCMP(name, "OP_SPEED")) //group - optimize run speed
- {
- QCC_PR_UndefineName("OP_SIZE");
- QCC_PR_UndefineName("OP_TIME");
-
-// QCC_PR_UndefineName("OP_NODUP");
- QCC_PR_UndefineName("OP_COMP_ALL");
- }
-
- if (!STRCMP(name, "OP_SIZE")) //group - produce small output.
- {
- QCC_PR_UndefineName("OP_SPEED");
- QCC_PR_UndefineName("OP_TIME");
-
- QCC_PR_DefineName("OP_NODUP");
- QCC_PR_DefineName("OP_COMP_ALL");
- }
-
- if (!STRCMP(name, "OP_COMP_ALL")) //group - compress the output
- {
- QCC_PR_DefineName("OP_COMP_STATEMENTS");
- QCC_PR_DefineName("OP_COMP_DEFS");
- QCC_PR_DefineName("OP_COMP_FIELDS");
- QCC_PR_DefineName("OP_COMP_FUNCTIONS");
- QCC_PR_DefineName("OP_COMP_STRINGS");
- QCC_PR_DefineName("OP_COMP_GLOBALS");
- QCC_PR_DefineName("OP_COMP_LINES");
- QCC_PR_DefineName("OP_COMP_TYPES");
- }
-
-
-
return cnst;
}
{
char *oldval;
char *d;
+ char *dbuf;
+ int dbuflen;
char *s;
int quote=false;
CompilerConstant_t *cnst;
QCC_PR_SimpleGetToken ();
- if (!QCC_PR_SimpleGetToken ())
+ if (!QCC_PR_SimpleGetToken ())
QCC_PR_ParseError(ERR_NONAME, "No name defined for compiler constant");
cnst = pHash_Get(&compconstantstable, pr_token);
else cnst->numparams = -1;
s = pr_file_p;
- d = cnst->value;
+ d = dbuf = NULL;
+ dbuflen = 0;
while(*s == ' ' || *s == '\t')
s++;
while(1)
{
+ if ((d - dbuf) + 2 >= dbuflen)
+ {
+ int len = d - dbuf;
+ dbuflen = (len+128) * 2;
+ dbuf = qccHunkAlloc(dbuflen);
+ memcpy(dbuf, d - len, len);
+ d = dbuf + len;
+ }
+
if( *s == '\\' )
{
// read over a newline if necessary
*d++ = *s++;
}
}
- }
+ }
else if(*s == '\r' || *s == '\n' || *s == '\0')
{
break;
s++;
}
*d = '\0';
- d--;
- while(*d<= ' ' && d >= cnst->value)
- *d-- = '\0';
- if (strlen(cnst->value) >= sizeof(cnst->value)) //this is too late.
- QCC_PR_ParseError(ERR_CONSTANTTOOLONG, "Macro %s too long (%i not %i)", cnst->name, strlen(cnst->value), sizeof(cnst->value));
+
+ cnst->value = dbuf;
if (oldval)
{ //we always warn if it was already defined
return true;
}
if (!strncmp(pr_file_p, "__FILE__", 8))
- {
+ {
static char retbuf[256];
sprintf(retbuf, "\"%s\"", strings + s_file);
pr_file_p = retbuf;
return true;
}
if (!strncmp(pr_file_p, "__FUNC__", 8))
- {
+ {
static char retbuf[256];
sprintf(retbuf, "\"%s\"",pr_scope->name);
pr_file_p = retbuf;
char *QCC_PR_CheakCompConstString(char *def)
{
char *s;
-
+
CompilerConstant_t *c;
c = pHash_Get(&compconstantstable, def);
- if (c)
+ if (c)
{
s = QCC_PR_CheakCompConstString(c->value);
return s;
{
CompilerConstant_t *c = pHash_Get(&compconstantstable, def);
return c;
- /*int a;
- for (a = 0; a < numCompilerConstants; a++)
- {
- if (!strncmp(def, CompilerConstant[a].name, CompilerConstant[a].namelen+1))
- return &CompilerConstant[a];
- }
- return NULL;
- */
}
//============================================================================
int c;
pr_token[0] = 0;
-
+
if (!pr_file_p)
{
if (QCC_PR_UnInclude())
- {
+ {
QCC_PR_Lex();
return;
}
if (!pr_file_p)
{
if (QCC_PR_UnInclude())
- {
+ {
QCC_PR_Lex();
return;
}
}
c = *pr_file_p;
-
+
if (!c)
{
if (QCC_PR_UnInclude())
- {
+ {
QCC_PR_Lex();
return;
}
return;
}
-
+
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
{
if (flag_hashonly || !QCC_PR_CheakCompConst()) //look for a macro.
if (pr_token_type == tt_eof)
{
if (QCC_PR_UnInclude())
- {
+ {
QCC_PR_Lex();
return;
}
}
return;
}
-
+
if (c == '$')
{
QCC_PR_LexGrab ();
return;
}
-
+
// parse symbol strings until a non-symbol is found
QCC_PR_LexPunctuation ();
}
printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
else
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
-
+
longjmp (pr_parse_abort, 1);
}
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error, ...)
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
QCC_PR_ParsePrintDef(WARN_ERROR, def);
-
+
longjmp (pr_parse_abort, 1);
}
void VARGS QCC_PR_ParseWarning (int type, char *error, ...)
}
}
+void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...)
+{
+ va_list argptr;
+ char string[1024];
+
+ if (qccwarningdisabled[type])
+ return;
+
+ va_start (argptr,error);
+ QC_vsnprintf (string,sizeof(string)-1, error,argptr);
+ va_end (argptr);
+
+ QCC_PR_PrintScope();
+ if (file)
+ {
+ if (flag_msvcstyle)
+ printf ("%s(%i) : note: %s\n", file, line, string);
+ else
+ printf ("%s:%i: note: %s\n", file, line, string);
+ }
+ else
+ printf ("note: %s\n", string);
+}
+
void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...)
{
va_list argptr;
if (STRCMP (string, pr_token))
return false;
-
+
QCC_PR_Lex ();
return true;
}
if (STRCMP (string, pr_token))
return false;
-
+
QCC_PR_Lex ();
return true;
}
{
if (pr_token_type != tt_name)
return false;
- if (flag_caseinsensative)
+ if (flag_caseinsensative)
{
if (stricmp (string, pr_token))
return false;
{
if (!keywordenabled)
return false;
- if (flag_caseinsensative)
+ if (flag_caseinsensative)
{
if (stricmp (string, pr_token))
return false;
{
static char ident[MAX_NAME];
char *ret;
-
+
if (pr_token_type != tt_name)
- QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
+ QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token);
if (strlen(pr_token) >= MAX_NAME-1)
QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long");
strcpy (ident, pr_token);
QCC_PR_Lex ();
-
+
ret = qccHunkAlloc(strlen(ident)+1);
strcpy(ret, ident);
return ret;
// check = &qcc_typeinfo[t];
if (typecmp(&qcc_typeinfo[t], type))
continue;
-
+
// c2 = check->next;
// n2 = type->next;
strcpy (pr_parm_names[ftype->num_parms], "");
ftype->num_parms++;
} while (QCC_PR_CheckToken (","));
-
+
QCC_PR_Expect (")");
}
recursivefunctiontype--;
strcpy (pr_parm_names[ftype->num_parms], name);
ftype->num_parms++;
} while (QCC_PR_CheckToken (";"));
-
+
QCC_PR_Expect (")");
}
recursivefunctiontype--;
{
newt = &qcc_typeinfo[i];
break;
- }
+ }
}
if (newt && forwarddeclaration)
return NULL;
}
-
+
if (QCC_PR_CheckToken(":"))
{
newt = QCC_PR_NewType("union", ev_union);
newt->size=0;
QCC_PR_Expect("{");
-
+
type = NULL;
if (QCC_PR_CheckToken(","))
QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
if (newparm->size > newt->size)
newt->size = newparm->size;
newt->num_parms++;
-
+
if (type)
type->next = newparm;
else
}
}
QCC_PR_Lex ();
-
+
if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
{
type_inlinefunction = true;
{
if (newtype)
{
- type = QCC_PR_DuplicateType(type);
+ type = QCC_PR_DuplicateType(type);
}
return type;
#define PROGSUSED
#include "qcc.h"
-int mkdir(const char *path);
+#include <sys/stat.h>
+#ifdef _WIN32
+#include <direct.h>
+#endif
+
+#include "errno.h"
char QCC_copyright[1024];
int QCC_packid;
char QCC_Packname[5][128];
-extern QCC_def_t *functemps; //floats/strings/funcs/ents...
-
extern int optres_test1;
extern int optres_test2;
{&flag_hashonly, FLAG_MIDCOMPILE,"hashonly", "Hash-only constants", "Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile"},
{&opt_logicops, FLAG_MIDCOMPILE,"lo", "Logic ops", "This changes the behaviour of your code. It generates additional if operations to early-out in if statements. With this flag, the line if (0 && somefunction()) will never call the function. It can thus be considered an optimisation. However, due to the change of behaviour, it is not considered so by fteqcc. Note that due to inprecisions with floats, this flag can cause runaway loop errors within the player walk and run functions (without iffloat also enabled). This code is advised:\nplayer_stand1:\n if (self.velocity_x || self.velocity_y)\nplayer_run\n if (!(self.velocity_x || self.velocity_y))"},
{&flag_msvcstyle, FLAG_MIDCOMPILE,"msvcstyle", "MSVC-style errors", "Generates warning and error messages in a format that msvc understands, to facilitate ide integration."},
+ {&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", "Allow locals to only be valid in the block they are defined in (like 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."},
{NULL}
};
{QCF_FTE, "fte"},
{QCF_DARKPLACES,"darkplaces"},
{QCF_DARKPLACES,"dp"},
+ {QCF_QTEST, "qtest"},
{0, NULL}
};
char *m;
char cmd[1024];
char name[256];
+ size_t result;
p = QCC_CheckParm ("-bspmodels");
if (!p)
if (p == myargc-1)
QCC_Error (ERR_BADPARMS, "-bspmodels must preceed a game directory");
gamedir = myargv[p+1];
-
+
for (i=0 ; i<nummodels ; i++)
{
m = precache_models[i];
strcpy (name, m);
name[strlen(m)-4] = 0;
sprintf (cmd, "qbsp %s/%s ; light -extra %s/%s", gamedir, name, gamedir, name);
- system (cmd);
+ result = system (cmd); // do something with the result
+
+ if (result != 0)
+ QCC_Error(ERR_INTERNAL, "QCC_BspModels() system returned non zero (failure) with: qbsp %s/%s ; light -extra %s/%s (%i)\n", gamedir, name, gamedir, name, errno);
}
}
for (s = strings+strofs-1; s>strings ; s--)
if (!strcmp(s, str))
return s-strings;
-
+
old = strofs;
strcpy (strings+strofs, str);
strofs += strlen(str)+1;
void QCC_PrintStrings (void)
{
int i, l, j;
-
+
for (i=0 ; i<strofs ; i += l)
{
l = strlen(strings+i) + 1;
{
int i,j;
QCC_dfunction_t *d;
-
+
for (i=0 ; i<numfunctions ; i++)
{
d = &functions[i];
{
int i;
QCC_ddef_t *d;
-
+
for (i=0 ; i<numfielddefs ; i++)
{
d = &fields[i];
{
int i;
QCC_ddef_t *d;
-
+
for (i=0 ; i<numglobaldefs ; i++)
{
d = &qcc_globals[i];
num++;
}
- ofs = SafeSeek(h, 0, SEEK_CUR);
+ ofs = SafeSeek(h, 0, SEEK_CUR);
SafeWrite(h, &num, sizeof(int));
SafeWrite(h, idf, sizeof(includeddatafile_t)*num);
int i;
qcc_sourcefile = NULL;
-
+
numstatements = 1;
strofs = 1;
numfunctions = 1;
numfielddefs = 1;
memset(&ret_temp, 0, sizeof(ret_temp));
-
+
def_ret.ofs = OFS_RETURN;
def_ret.name = "return";
def_ret.temp = &ret_temp;
int i, len;
pbool debugtarget = false;
pbool types = false;
- int outputsize = 16;
+ int outputsttype = PST_DEFAULT;
+ pbool warnedunref = false;
if (numstatements==1 && numfunctions==1 && numglobaldefs==1 && numfielddefs==1)
{
if (numpr_globals > 65530 )
{
printf("Forcing target to FTE32 due to numpr_globals\n");
- outputsize = 32;
+ outputsttype = PST_FTE32;
}
else if (qcc_targetformat == QCF_HEXEN2)
{
if (numpr_globals > 65530)
{
printf("Using 32 bit target due to numpr_globals\n");
- outputsize = 32;
+ outputsttype = PST_FTE32;
}
if (qcc_targetformat == QCF_DARKPLACES)
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))
+ {
+ //qcc_typeinfo_t has a char* inside it, which changes size
+ printf("AMD64 builds cannot write typeinfo structures\n");
+ types = false;
+ }
if (verbose)
{
printf("Warning: Saving is not supported. Ensure all engine read fields and globals are defined early on.\n");
printf("A KK compatible executor will be required (FTE/KK)\n");
+ outputsttype = PST_KKQWSV;
break;
+ case QCF_QTEST:
+ printf("Compiled QTest progs will most likely not work at all. YOU'VE BEEN WARNED!\n");
+ outputsttype = PST_QTEST;
+ break;
+ default:
+ Sys_Error("invalid progs type chosen!");
}
//part of how compilation works. This def is always present, and never used.
h=0;
def->references = h;
-
-
+
+
if (!h)
h = 1;
if (comp_x)
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)
+ {
+ 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)
{
// numfunctions++;
}
- else if (def->type->type == ev_field)// && !def->constant)
+ else if (def->type->type == ev_field && def->constant)
{
dd = &fields[numfielddefs];
numfielddefs++;
printf ("%6i numfielddefs (%i unique) (of %i)\n", numfielddefs, pr.size_fields, MAX_FIELDS);
printf ("%6i numpr_globals (of %i)\n", numpr_globals, MAX_REGS);
}
-
+
if (!*destfile)
strcpy(destfile, "progs.dat");
if (verbose)
progs.numstrings = strofs;
if (progs.blockscompressed&16)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, strofs*sizeof(char), 2, (char *)strings, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
for (i=0 ; i<numstatements ; i++)
- switch(qcc_targetformat == QCF_KK7?32:outputsize) //KK7 sucks.
+ switch(outputsttype)
{
- case 32:
+ case PST_KKQWSV:
+ case PST_FTE32:
for (i=0 ; i<numstatements ; i++)
{
statements[i].op = PRLittleLong/*PRLittleShort*/(statements[i].op);
statements[i].b = PRLittleLong/*PRLittleShort*/(statements[i].b);
statements[i].c = PRLittleLong/*PRLittleShort*/(statements[i].c);
}
-
+
if (progs.blockscompressed&1)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement32_t), 2, (char *)statements, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
else
SafeWrite (h, statements, numstatements*sizeof(QCC_dstatement32_t));
break;
- case 16:
+ case PST_QTEST:
+#define qtst ((qtest_statement_t*) statements)
+ for (i=0 ; i<numstatements ; i++) // scale down from 16-byte internal to 12-byte qtest
+ {
+ QCC_dstatement_t stmt = statements[i];
+ qtst[i].line = 0; // no line support
+ qtst[i].op = PRLittleShort((unsigned short)stmt.op);
+ if (stmt.a < 0)
+ qtst[i].a = PRLittleShort((short)stmt.a);
+ else
+ qtst[i].a = (unsigned short)PRLittleShort((unsigned short)stmt.a);
+ if (stmt.b < 0)
+ qtst[i].b = PRLittleShort((short)stmt.b);
+ else
+ qtst[i].b = (unsigned short)PRLittleShort((unsigned short)stmt.b);
+ if (stmt.c < 0)
+ qtst[i].c = PRLittleShort((short)stmt.c);
+ else
+ qtst[i].c = (unsigned short)PRLittleShort((unsigned short)stmt.c);
+ }
+
+ // no compression
+ SafeWrite (h, qtst, numstatements*sizeof(qtest_statement_t));
+#undef qtst
+ break;
+ case PST_DEFAULT:
#define statements16 ((QCC_dstatement16_t*) statements)
for (i=0 ; i<numstatements ; i++) //resize as we go - scaling down
{
else
statements16[i].c = (unsigned short)PRLittleShort((unsigned short)statements[i].c);
}
-
+
if (progs.blockscompressed&1)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numstatements*sizeof(QCC_dstatement16_t), 2, (char *)statements16, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
SafeWrite (h, statements16, numstatements*sizeof(QCC_dstatement16_t));
break;
default:
- Sys_Error("intsize error");
+ Sys_Error("structtype error");
}
progs.ofs_functions = SafeSeek (h, 0, SEEK_CUR);
progs.numfunctions = numfunctions;
- for (i=0 ; i<numfunctions ; i++)
+
+ switch (outputsttype)
{
- functions[i].first_statement = PRLittleLong (functions[i].first_statement);
- functions[i].parm_start = PRLittleLong (functions[i].parm_start);
- functions[i].s_name = PRLittleLong (functions[i].s_name);
- functions[i].s_file = PRLittleLong (functions[i].s_file);
- functions[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
- functions[i].locals = PRLittleLong (functions[i].locals);
- }
+ case PST_QTEST:
+ {
+ // this sucks but the structures are just too different
+ qtest_function_t *qtestfuncs = (qtest_function_t *)qccHunkAlloc(sizeof(qtest_function_t)*numfunctions);
- if (progs.blockscompressed&8)
- {
- SafeWrite (h, &len, sizeof(int)); //save for later
- len = QC_encode(progfuncs, numfunctions*sizeof(QCC_dfunction_t), 2, (char *)functions, h); //write
- i = SafeSeek (h, 0, SEEK_CUR);
- SafeSeek(h, progs.ofs_functions, SEEK_SET);//seek back
- len = PRLittleLong(len);
- SafeWrite (h, &len, sizeof(int)); //write size.
- SafeSeek(h, i, SEEK_SET);
+ for (i=0 ; i<numfunctions ; i++)
+ {
+ int j;
+
+ qtestfuncs[i].unused1 = 0;
+ qtestfuncs[i].profile = 0;
+ qtestfuncs[i].first_statement = PRLittleLong (functions[i].first_statement);
+ qtestfuncs[i].parm_start = PRLittleLong (functions[i].parm_start);
+ qtestfuncs[i].s_name = PRLittleLong (functions[i].s_name);
+ qtestfuncs[i].s_file = PRLittleLong (functions[i].s_file);
+ qtestfuncs[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
+ qtestfuncs[i].locals = PRLittleLong (functions[i].locals);
+ for (j = 0; j < MAX_PARMS; j++)
+ qtestfuncs[i].parm_size[j] = PRLittleLong((int)functions[i].parm_size[j]);
+ }
+
+ SafeWrite (h, qtestfuncs, numfunctions*sizeof(qtest_function_t));
+ }
+ break;
+ case PST_DEFAULT:
+ case PST_KKQWSV:
+ case PST_FTE32:
+ for (i=0 ; i<numfunctions ; i++)
+ {
+ functions[i].first_statement = PRLittleLong (functions[i].first_statement);
+ functions[i].parm_start = PRLittleLong (functions[i].parm_start);
+ functions[i].s_name = PRLittleLong (functions[i].s_name);
+ functions[i].s_file = PRLittleLong (functions[i].s_file);
+ functions[i].numparms = PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
+ functions[i].locals = PRLittleLong (functions[i].locals);
+ }
+
+ if (progs.blockscompressed&8)
+ {
+ SafeWrite (h, &len, sizeof(int)); //save for later
+ len = QC_encode(progfuncs, numfunctions*sizeof(QCC_dfunction_t), 2, (char *)functions, h); //write
+ i = SafeSeek (h, 0, SEEK_CUR);
+ SafeSeek(h, progs.ofs_functions, SEEK_SET);//seek back
+ len = PRLittleLong(len);
+ SafeWrite (h, &len, sizeof(int)); //write size.
+ SafeSeek(h, i, SEEK_SET);
+ }
+ else
+ SafeWrite (h, functions, numfunctions*sizeof(QCC_dfunction_t));
+ break;
+ default:
+ Sys_Error("structtype error");
}
- else
- SafeWrite (h, functions, numfunctions*sizeof(QCC_dfunction_t));
- switch(outputsize)
+ switch(outputsttype)
{
- case 32:
+ case PST_QTEST:
+ // qtest needs a struct remap but should be able to get away with a simple swap here
+ for (i=0 ; i<numglobaldefs ; i++)
+ {
+ qtest_def_t qtdef = ((qtest_def_t *)qcc_globals)[i];
+ qcc_globals[i].type = qtdef.type;
+ qcc_globals[i].ofs = qtdef.ofs;
+ qcc_globals[i].s_name = qtdef.s_name;
+ }
+ for (i=0 ; i<numfielddefs ; i++)
+ {
+ qtest_def_t qtdef = ((qtest_def_t *)fields)[i];
+ fields[i].type = qtdef.type;
+ fields[i].ofs = qtdef.ofs;
+ fields[i].s_name = qtdef.s_name;
+ }
+ // passthrough.. reuse FTE32 code
+ case PST_FTE32:
progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
progs.numglobaldefs = numglobaldefs;
for (i=0 ; i<numglobaldefs ; i++)
}
if (progs.blockscompressed&2)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef_t), 2, (char *)qcc_globals, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
}
if (progs.blockscompressed&4)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef_t), 2, (char *)fields, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
else
SafeWrite (h, fields, numfielddefs*sizeof(QCC_ddef_t));
break;
- case 16:
+ case PST_KKQWSV:
+ case PST_DEFAULT:
#define qcc_globals16 ((QCC_ddef16_t*)qcc_globals)
#define fields16 ((QCC_ddef16_t*)fields)
progs.ofs_globaldefs = SafeSeek (h, 0, SEEK_CUR);
}
if (progs.blockscompressed&2)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numglobaldefs*sizeof(QCC_ddef16_t), 2, (char *)qcc_globals16, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
}
if (progs.blockscompressed&4)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numfielddefs*sizeof(QCC_ddef16_t), 2, (char *)fields16, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
SafeWrite (h, fields16, numfielddefs*sizeof(QCC_ddef16_t));
break;
default:
- Sys_Error("intsize error");
+ Sys_Error("structtype error");
}
progs.ofs_globals = SafeSeek (h, 0, SEEK_CUR);
((int *)qcc_pr_globals)[i] = PRLittleLong (((int *)qcc_pr_globals)[i]);
if (progs.blockscompressed&32)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numpr_globals*4, 2, (char *)qcc_pr_globals, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
SafeSeek(h, i, SEEK_SET);
}
else
- SafeWrite (h, qcc_pr_globals, numpr_globals*4);
+ SafeWrite (h, qcc_pr_globals, numpr_globals*4);
if (types)
for (i=0 ; i<numtypeinfos ; i++)
qcc_typeinfo[i].aux_type = (QCC_type_t*)(qcc_typeinfo[i].aux_type - qcc_typeinfo);
if (qcc_typeinfo[i].next)
qcc_typeinfo[i].next = (QCC_type_t*)(qcc_typeinfo[i].next - qcc_typeinfo);
- qcc_typeinfo[i].name = (char *)QCC_CopyDupBackString(qcc_typeinfo[i].name);
+ qcc_typeinfo[i].name = (char*)QCC_CopyDupBackString(qcc_typeinfo[i].name);
}
progs.ofsfiles = 0;
switch(qcc_targetformat)
{
+ case QCF_QTEST:
+ progs.version = PROG_QTESTVERSION;
+ break;
case QCF_KK7:
progs.version = PROG_KKQWSVVERSION;
break;
case QCF_FTEDEBUG:
progs.version = PROG_EXTENDEDVERSION;
- if (outputsize == 32)
+ if (outputsttype == PST_FTE32)
progs.secondaryversion = PROG_SECONDARYVERSION32;
else
progs.secondaryversion = PROG_SECONDARYVERSION16;
progs.ofsbodylessfuncs = SafeSeek (h, 0, SEEK_CUR);
- progs.numbodylessfuncs = WriteBodylessFuncs(h);
+ progs.numbodylessfuncs = WriteBodylessFuncs(h);
if (debugtarget)
{
progs.ofslinenums = SafeSeek (h, 0, SEEK_CUR);
if (progs.blockscompressed&64)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, numstatements*sizeof(int), 2, (char *)statement_linenums, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
{
progs.ofs_types = SafeSeek (h, 0, SEEK_CUR);
if (progs.blockscompressed&128)
- {
+ {
SafeWrite (h, &len, sizeof(int)); //save for later
len = QC_encode(progfuncs, sizeof(QCC_type_t)*numtypeinfos, 2, (char *)qcc_typeinfo, h); //write
i = SafeSeek (h, 0, SEEK_CUR);
}
else
SafeWrite (h, qcc_typeinfo, sizeof(QCC_type_t)*numtypeinfos);
- progs.numtypes = numtypeinfos;
+ progs.numtypes = numtypeinfos;
}
else
{
// qbyte swap the header and write it out
for (i=0 ; i<sizeof(progs)/4 ; i++)
- ((int *)&progs)[i] = PRLittleLong ( ((int *)&progs)[i] );
+ ((int *)&progs)[i] = PRLittleLong ( ((int *)&progs)[i] );
+
-
SafeSeek (h, 0, SEEK_SET);
SafeWrite (h, &progs, sizeof(progs));
SafeClose (h);
{
static char buf[80];
char *s;
-
+
s = buf;
*s++ = '"';
while (string && *string)
QCC_def_t *QCC_PR_DefForFieldOfs (gofs_t ofs)
{
QCC_def_t *d;
-
+
for (d=pr.def_head.next ; d ; d=d->next)
{
if (d->type->type != ev_field)
static char line[256];
QCC_def_t *def;
QCC_dfunction_t *f;
-
+
switch (type)
{
case ev_string:
sprintf (line, "%s", QCC_PR_String(strings + *(int *)val));
break;
- case ev_entity:
+ case ev_entity:
sprintf (line, "entity %i", *(int *)val);
break;
case ev_function:
sprintf (line, "bad type %i", type);
break;
}
-
+
return line;
}
QCC_def_t *def;
void *val;
static char line[128];
-
+
val = (void *)&qcc_pr_globals[ofs];
def = pr_global_defs[ofs];
if (!def)
sprintf (line,"%i(?""?""?)", ofs);
else
sprintf (line,"%i(%s)", ofs, def->name);
-
+
i = strlen(line);
for ( ; i<16 ; i++)
strcat (line," ");
strcat (line," ");
-
+
return line;
}
QCC_def_t *def;
void *val;
static char line[128];
-
+
val = (void *)&qcc_pr_globals[ofs];
def = pr_global_defs[ofs];
if (!def)
}
else
sprintf (line,"%i(%s)", ofs, def->name);
-
+
i = strlen(line);
for ( ; i<16 ; i++)
strcat (line," ");
strcat (line," ");
-
+
return line;
}*/
/*void QCC_PR_PrintStatement (QCC_dstatement_t *s)
{
int i;
-
+
printf ("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s-statements], pr_opcodes[s->op].opname);
i = strlen(pr_opcodes[s->op].opname);
for ( ; i<10 ; i++)
printf (" ");
-
+
if (s->op == OP_IF || s->op == OP_IFNOT)
printf ("%sbranch %i",QCC_PR_GlobalString(s->a),s->b);
else if (s->op == OP_GOTO)
/*void QCC_PR_PrintDefs (void)
{
QCC_def_t *d;
-
+
for (d=pr.def_head.next ; d ; d=d->next)
QCC_PR_PrintOfs (d->ofs);
}*/
qcc_typeinfo[numtypeinfos].name = name;
qcc_typeinfo[numtypeinfos].num_parms = 0;
qcc_typeinfo[numtypeinfos].param = NULL;
- qcc_typeinfo[numtypeinfos].size = type_size[basictype];
+ qcc_typeinfo[numtypeinfos].size = type_size[basictype];
numtypeinfos++;
extern struct freeoffset_s *freeofs;
int i;
char name[16];
-
+
pr.memory = memory;
pr.max_memory = memsize;
QCC_PR_ResetErrorScope();
pr_scope = NULL;
-/* numpr_globals = RESERVED_OFS;
-
+/* numpr_globals = RESERVED_OFS;
+
for (i=0 ; i<RESERVED_OFS ; i++)
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_field = QCC_PR_NewType("field", ev_field);
type_function = QCC_PR_NewType("function", ev_function);
- type_pointer = QCC_PR_NewType("pointer", ev_pointer);
+ 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_integer = QCC_PR_NewType("integer", ev_integer);
if (keyword_int)
type_integer = QCC_PR_NewType("int", ev_integer);
-
+
if (output_parms)
{
QCC_def_t *d;
int errors;
-
+
errors = false;
-
+
// check to make sure all functions prototyped have code
for (d=pr.def_head.next ; d ; d=d->next)
{
// if (!f || (!f->code && !f->builtin) )
if (d->initialized==0)
{
+ s_file = d->s_file;
if (!strncmp(d->name, "ArrayGet*", 9))
{
QCC_PR_EmitArrayGetFunction(d, d->name+9);
bodylessfuncs = true;
errors = true;
}
+ s_file = NULL;
// errors = true;
}
else if (d->initialized==2)
{
char *s;
for(s=p;*s;s++)
- QCC_CRC_ProcessByte(crc, *s);
+ QCC_CRC_ProcessByte(crc, *s);
}
#define ADD3(p) Add3(p, &crc, file)
file[0] = '\0';
QCC_CRC_Init (&crc);
-
+
// print global vars until the first field is defined
//ADD: crc and dump
ADD2("File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects.");
ADD(" */\n\ntypedef struct");
ADD2(" globalvars_s");
- ADD(qcva("\n{"));
+ ADD(qcva("\n{"));
ADD2("\tint pad;\n"
"\tint ofs_return[3];\n" //makes it easier with the get globals func
"\tint ofs_parm0[3];\n"
break;
if (d->ofs<RESERVED_OFS)
continue;
-
+
switch (d->type->type)
{
case ev_float:
{
if (!strcmp (d->name, "end_sys_fields"))
break;
-
+
if (d->type->type != ev_field)
continue;
-
+
switch (d->type->aux_type->type)
{
case ev_float:
if (d->type->type != ev_field)
continue;
if (f)
- ADD2(",\n");
+ ADD2(",\n");
ADD2(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name));
f = 1;
}
int i;
QCC_dstatement_t *ds;
QCC_dfunction_t *df;
-
+
for (i=0 ; i<numfunctions ; i++)
if (!strcmp (name, strings + functions[i].s_name))
break;
if (i==numfunctions)
QCC_Error (ERR_NOFUNC, "No function named \"%s\"", name);
- df = functions + i;
-
+ df = functions + i;
+
printf ("Statements for function %s:\n", name);
ds = statements + df->first_statement;
while (1)
{
/*
char *ofs;
-
+
for (ofs = path+1 ; *ofs ; ofs++)
{
if (*ofs == '/')
#if 1
char *f;
#else
- int in;
+ int in;
int count;
char buf[4096];
#endif
-
+
if ( (qbyte *)pf - (qbyte *)pfiles > sizeof(pfiles) )
QCC_Error (ERR_TOOMANYPAKFILES, "Too many files in pak file");
printf ("%64s : %7i\n", pf->name, remaining);
packbytes += remaining;
-
+
while (remaining)
{
if (remaining < sizeof(buf))
int in, out;
int remaining, count;
char buf[4096];
-
+
print ("%s to %s\n", src, dest);
in = SafeOpenRead (src);
remaining = filelength (in);
-
+
QCC_CreatePath (dest);
out = SafeOpenWrite (dest, remaining+10);
-
+
while (remaining)
{
if (remaining < sizeof(buf))
}
close (in);
- SafeClose (out);
+ SafeClose (out);
*/
}
for (i=0 ; i<numsounds ; i++)
{
if (precache_sounds_block[i] != blocknum)
- continue;
+ continue;
sprintf (srcfile,"%s%s",srcdir, precache_sounds[i]);
sprintf (destfile,"%s%s",destdir, precache_sounds[i]);
if (copytype == 1)
else
QCC_PackFile (srcfile, precache_files[i]);
}
-
+
if (copytype == 2)
{
header.id[0] = 'P';
dirlen = (qbyte *)pf - (qbyte *)pfiles;
header.dirofs = PRLittleLong(SafeSeek (packhandle, 0, SEEK_CUR));
header.dirlen = PRLittleLong(dirlen);
-
+
SafeWrite (packhandle, pfiles, dirlen);
-
+
SafeSeek (packhandle, 0, SEEK_SET);
SafeWrite (packhandle, &header, sizeof(header));
- SafeClose (packhandle);
-
+ SafeClose (packhandle);
+
// do a crc of the file
QCC_CRC_Init (&crc);
for (i=0 ; i<dirlen ; i++)
QCC_CRC_ProcessByte (&crc, ((qbyte *)pfiles)[i]);
-
+
i = pf - pfiles;
printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
}
{
char *s;
char srcdir[1024], destdir[1024];
- int p;
+ int p;
if (verbose)
{
for ( p = 0; p < 5; p++)
{
- s = QCC_Packname[p];
+ s = QCC_Packname[p];
if (!*s)
continue;
strcpy(destdir, s);
strcat (srcdir, "/");
DefaultExtension (destdir, ".pak");
-
+
copytype = 2;
_QCC_CopyFiles(blocknum, copytype, srcdir, destdir);
cnst = QCC_PR_DefineName(name);
if (val)
{
- if (strlen(val)+1 >= sizeof(cnst->value))
- QCC_Error(ERR_PRECOMPILERCONSTANTTOOLONG, "Compiler constant value is too long\n");
- strncpy(cnst->value, val, sizeof(cnst->value)-1);
- cnst->value[sizeof(cnst->value)-1] = '\0';
+ cnst->value = qccHunkAlloc(strlen(val)+1);
+ memcpy(cnst->value, val, strlen(val)+1);
}
}
if (!optimisations[p].enabled)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]);
}
-
+
else if ( !strnicmp(myargv[i], "-K", 2) || !strnicmp(myargv[i], "/K", 2) )
{
p = 0;
MAX_REGS = 65536;
MAX_STRINGS = 1000000;
- MAX_GLOBALS = 32768;
+ MAX_GLOBALS = 65535;
MAX_FIELDS = 2048;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;
MAX_FUNCTIONS = atoi(qcc_token);
} else if (!strcmp(qcc_token, "MAX_TYPES")) {
s = QCC_COM_Parse(s);
- maxtypeinfos = atoi(qcc_token);
+ maxtypeinfos = atoi(qcc_token);
} else if (!strcmp(qcc_token, "MAX_TEMPS")) {
s = QCC_COM_Parse(s);
- max_temps = atoi(qcc_token);
+ max_temps = atoi(qcc_token);
} else if (!strcmp(qcc_token, "CONSTANTS")) {
s = QCC_COM_Parse(s);
MAX_CONSTANTS = atoi(qcc_token);
numtemps = 0;
- functemps=NULL;
+ QCC_PurgeTemps();
strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
strofs = 1;
Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
dotranslate=0;
dotranslate_count=0;
-
+
// pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);
qcc_globals = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_GLOBALS);
- numglobaldefs=0;
+ numglobaldefs=0;
fields = (void *)qccHunkAlloc(sizeof(QCC_ddef_t) * MAX_FIELDS);
numfielddefs=0;
#ifdef MAX_EXTRA_PARMS
memset(&extra_parms, 0, sizeof(extra_parms));
#endif
-
+
if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
{
printf ("qcc looks for progs.src in the current directory.\n");
printf ("-Wall to give a stupid number of warnings\n");
printf ("-Ttarget to set a output format\n");
printf ("-Fautoproto to enable automatic prototyping\n");
- printf ("-Fsubscope to enable subscopes\n");
+ printf ("-Fsubscope to make locals specific to their subscope\n");
qcc_compileactive = false;
return;
if (opt_locals_marshalling)
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nLocals marshalling might be buggy. Use with caution\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
-
+
p = QCC_CheckParm ("-src");
if (p && p < argc-1 )
{
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]);
+ sprintf (qccmprogsdat, "%s", argv[p+1]);
else
{ //look for a preprogs.src... :o)
- sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir);
+ sprintf (qccmprogsdat, "preprogs.src");
if (externs->FileSize(qccmprogsdat) <= 0)
- sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir);
+ sprintf (qccmprogsdat, "progs.src");
}
numsourcefiles = 0;
if (currentsourcefile)
printf("-------------------------------------\n");
- strcpy(qccmprogsdat, sourcefileslist[currentsourcefile++]);
-
+ sprintf (qccmprogsdat, "%s%s", qccmsourcedir, sourcefileslist[currentsourcefile++]);
printf ("Source file: %s\n", qccmprogsdat);
if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1)
- {
+ {
return;
}
}
}
if (*qcc_token == '#')
- {
+ {
void StartNewStyleCompile(void);
newstyle:
newstylesource = true;
#ifndef QCCONLY
p=0;
- s2 = strcpy(destfile2, destfile);
+ s2 = strcpy(destfile2, destfile);
if (!strncmp(s2, "./", 2))
s2+=2;
else
}
#endif
+ if (flag_filetimes)
+ {
+ struct stat s, os;
+ pbool modified = false;
+
+ if (stat(destfile, &os) != -1)
+ {
+ while ((pr_file_p=QCC_COM_Parse(pr_file_p)))
+ {
+ if (stat(qcc_token, &s) == -1 || s.st_mtime > os.st_mtime)
+ {
+ printf("%s changed\n", qcc_token);
+ modified = true;
+ break;
+ }
+ }
+ if (!modified)
+ {
+ printf("No changes\n");
+ qcc_compileactive = false;
+ return;
+ }
+ else
+ {
+ pr_file_p = qccmsrc;
+ }
+ }
+ }
+
printf ("outputfile: %s\n", destfile);
-
+
pr_dumpasm = false;
currentchunk = NULL;
strcpy (qccmfilename, qccmsourcedir);
while(1)
{
- if (!strncmp(s, "..\\", 3))
+ if (!strncmp(s, "..\\", 3) || !strncmp(s, "../", 3))
{
s2 = qccmfilename + strlen(qccmfilename)-2;
while (s2>=qccmfilename)
}
s2--;
}
- s+=3;
- continue;
+ if (s2>=qccmfilename)
+ {
+ s+=3;
+ continue;
+ }
}
- if (!strncmp(s, ".\\", 2))
+ if (!strncmp(s, ".\\", 2) || !strncmp(s, "./", 2))
{
s+=2;
continue;
QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
}
void QCC_FinishCompile(void)
-{
+{
pbool donesomething;
int crc;
// int p;
if (setjmp(pr_parse_abort))
QCC_Error(ERR_INTERNAL, "");
-
+
if (!QCC_PR_FinishCompilation ())
{
QCC_Error (ERR_PARSEERRORS, "compilation errors");
// write progdefs.h
crc = QCC_PR_WriteProgdefs ("progdefs.h");
-
+
// write data file
donesomething = QCC_WriteData (crc);
-
+
// regenerate bmodels if -bspmodels
QCC_BspModels ();
printf("optres_test1 %i\n", optres_test1);
if (optres_test2)
printf("optres_test2 %i\n", optres_test2);
-
+
printf("numtemps %i\n", numtemps);
}
if (!flag_msvcstyle)
}
pr_scope = NULL; // outside all functions
-
+
QCC_PR_ParseDefs (NULL);
}
QCC_PR_ClearGrabMacros (); // clear the frame macros
compilingfile = filename;
-
+
pr_file_p = qccmsrc2;
s_file = QCC_CopyString (filename);
pr_source_line = 0;
-
+
QCC_PR_NewLine ();
QCC_PR_Lex (); // read first token
return false;
QCC_PR_SkipToSemicolon ();
if (pr_token_type == tt_eof)
- return false;
+ return false;
}
pr_scope = NULL; // outside all functions
-
+
QCC_PR_ParseDefs ();
}
}
return (pr_error_count == 0);
-
+
}*/
#define ZEXPORT VARGS
#include "../libs/zlib.h"
+#ifdef _WIN64
+# pragma comment (lib, "../libs/zlib64.lib")
+#else
# pragma comment (lib, "../libs/zlib.lib")
+#endif
#else
#include <zlib.h>
#endif
#define MAX_PARMS 8
+// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
+#ifdef _WIN32
+ #if (_MSC_VER >= 1400)
+ //with MSVC 8, use MS extensions
+ #define snprintf linuxlike_snprintf_vc8
+ int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
+ #else
+ //msvc crap
+ #define snprintf linuxlike_snprintf
+ int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
+ #define vsnprintf linuxlike_vsnprintf
+ int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
+ #endif
+#endif
+
typedef struct QCC_type_s
{
etype_t type;
// function types are more complex
struct QCC_type_s *aux_type; // return type or field type
int num_parms; // -1 = variable args
-// struct QCC_type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
+// struct QCC_type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
int ofs; //inside a structure.
int size;
typen = current_progstate->types[def->type & ~DEF_SHARED].type;
else
typen = def->type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
-
+
evaluateimmediate:
// return PR_UglyValueString(def->type, (eval_t *)¤t_progstate->globals[def->ofs]);
switch(typen)
dstatement16_t *st;
if (ofsflags[ofs] & 8)
return false; //this is a global/local/pramater, not a temp
- if (!(ofsflags[ofs] & 3))
+ if (!(ofsflags[ofs] & 3))
return false; //this is a constant.
for (st = &((dstatement16_t*)progs->statements)[firstst]; ; st++,firstst++)
{ //if written, return false, if read, return true.
st = &((dstatement16_t*)progs->statements)[stnum];
switch(st->op)
{
- case OP_IFNOT:
+ case OP_IFNOT_I:
count = (signed short)st->b;
writes(file, "if (");
WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->a);
writes(file, "}\r\n");
}
break;
- case OP_IF:
+ case OP_IF_I:
longjmp(decompilestatementfailure, 1);
break;
case OP_GOTO:
def->s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
strcpy(def->s_name+progfuncs->stringtable, mem);
}
-
+
if (current_progstate->types)
writes(f, "%s %s", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
else
case ev_vector:
writes(f, "%s %s", "vector", progfuncs->stringtable+def->s_name);
break;
- default:
+ default:
writes(f, "%s %s", "randomtype", progfuncs->stringtable+def->s_name);
break;
}
writes(f, ";\r\n");
return;
}
-
+
fileofs = SafeSeek(f, 0, SEEK_CUR);
if (setjmp(decompilestatementfailure))
{
{
def = ED_GlobalAtOfs16(progfuncs, ofs);
if (def)
- {
+ {
v = (eval_t *)&((int *)progs->globals)[def->ofs];
if (current_progstate->types)
writes(f, "\tlocal %s %s;\r\n", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
case ev_vector:
if (v->_vector[0] || v->_vector[1] || v->_vector[2])
writes(f, "\tlocal vector %s = '%f %f %f';\r\n", progfuncs->stringtable+def->s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
- else
+ else
writes(f, "\tlocal %s %s;\r\n", "vector", progfuncs->stringtable+def->s_name);
ofs+=2; //skip floats;
break;
- default:
+ default:
writes(f, "\tlocal %s %s;\r\n", "randomtype", progfuncs->stringtable+def->s_name);
break;
}
st = &((dstatement16_t*)progs->statements)[stn];
if (!st->op) //end of function statement!
break;
- op = &pr_opcodes[st->op];
+ op = &pr_opcodes[st->op];
writes(f, "\t%s", op->opname);
if (op->priority==-1&&op->associative==ASSOC_RIGHT) //last param is a goto
writes(f, " %s", VarAtOfs(progfuncs, st->c));
}
}
-
+
writes(f, ";\r\n");
stn++;
{
def = ED_GlobalAtOfs16(progfuncs, ofs);
if (def)
- {
+ {
v = (eval_t *)&((int *)progs->globals)[def->ofs];
if (current_progstate->types)
writes(f, "\tlocal %s %s;\r\n", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
break;
case ev_vector:
if (v->_vector[0] || v->_vector[1] || v->_vector[2])
- writes(f, "\tlocal vector %s = '%f %f %f';\r\n", def->s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
- else
+ writes(f, "\tlocal vector %s = '%f %f %f';\r\n", progfuncs->stringtable+def->s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
+ else
writes(f, "\tlocal %s %s;\r\n", "vector",progfuncs->stringtable+def->s_name);
ofs+=2; //skip floats;
break;
- default:
+ default:
writes(f, "\tlocal %s %s;\r\n", "randomtype", progfuncs->stringtable+def->s_name);
break;
}
dstatement16_t *st;
int parmofs[8];
-
+
ofstype = realloc(ofstype, sizeof(*ofstype)*65535);
ofsflags = realloc(ofsflags, sizeof(*ofsflags)*65535);
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_field = QCC_PR_NewType("field", ev_field);
type_function = QCC_PR_NewType("function", ev_function);
- type_pointer = QCC_PR_NewType("pointer", ev_pointer);
+ type_pointer = QCC_PR_NewType("pointer", ev_pointer);
type_integer = QCC_PR_NewType("integer", ev_integer);
// type_variant = QCC_PR_NewType("__variant", ev_variant);
qccprogfuncs = progfuncs;
op=current_progstate;
-
+
if (!PR_ReallyLoadProgs(progfuncs, fname, -1, &progs, false))
{
return false;
if (v->string && *(pr_strings+v->_int))
writes(f, "string %s = \"%s\";\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name, pr_strings+v->_int);
else
- writes(f, "string %s;\r\n", pr_globaldefs16[i].s_name);
+ writes(f, "string %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
break;
case ev_float:
if (v->_float)
break;
case ev_function:
-//wierd
+//wierd
WriteAsmStatements(progfuncs, &progs, ((int *)progs.globals)[pr_globaldefs16[i].ofs], f, pr_globaldefs16[i].s_name+progfuncs->stringtable);
break;
-
+
case ev_pointer:
writes(f, "pointer %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
break;
case ev_struct:
writes(f, "struct %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
break;
- default:
+ default:
break;
-
+
}
}
CPPFLAGS_COMMON += -DWIN32 -D_WIN32 -D_inline=inline
CFLAGS_COMMON += -mms-bitfields
LDFLAGS_DLL = --dll -Wl,--add-stdcall-alias
- LIBS_COMMON = -lws2_32 -luser32 -lgdi32
+ LIBS_COMMON = -lws2_32 -luser32 -lgdi32 -lole32
EXE ?= exe
A = a
DLL = dll
tools/quake3/q3map2/vis.o \
tools/quake3/q3map2/writebsp.o \
libddslib.$(A) \
+ libfilematch.$(A) \
libjpeg6.$(A) \
libl_net.$(A) \
libmathlib.$(A) \
tools/quake3/q3data/q3data.o \
tools/quake3/q3data/stripper.o \
tools/quake3/q3data/video.o \
+ libfilematch.$(A) \
libl_net.$(A) \
libmathlib.$(A) \
$(if $(findstring $(OS),Win32),icons/q3data.o,) \
libxmllib.$(A) \
$(if $(findstring $(OS),Win32),icons/radiant.o,) \
+libfilematch.$(A): CPPFLAGS_EXTRA := -Ilibs
+libfilematch.$(A): \
+ libs/filematch.o \
+
libcmdlib.$(A): CPPFLAGS_EXTRA := -Ilibs
libcmdlib.$(A): \
libs/cmdlib/cmdlib.o \
plugins/vfspk3/archive.o \
plugins/vfspk3/vfs.o \
plugins/vfspk3/vfspk3.o \
+ libfilematch.$(A) \
$(INSTALLDIR)/plugins/bobtoolz.$(DLL): LIBS_EXTRA := $(LIBS_GLIB) $(LIBS_GTK)
$(INSTALLDIR)/plugins/bobtoolz.$(DLL): CPPFLAGS_EXTRA := $(CPPFLAGS_GLIB) $(CPPFLAGS_GTK) -Ilibs -Iinclude
#define AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_
#include <list>
+#include <stdlib.h>
typedef struct
{
#pragma once
#endif // _MSC_VER > 1000
+#include <stdlib.h>
#include "mathlib.h"
#include "DMap.h"
class DBrush;
pack DarkPlacesPack GPL svn https://zerowing.idsoftware.com/svn/radiant.gamepacks/DarkPlacesPack/branches/1.5/
pack NexuizPack GPL gitdir git://git.icculus.org/divverent/nexuiz.git misc/netradiant-NexuizPack master
pack OpenArenaPack unknown zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/OpenArenaPack.zip
+pack OsirionPack GPL zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/OsirionPack.zip
pack Q3Pack proprietary svn https://zerowing.idsoftware.com/svn/radiant.gamepacks/Q3Pack/trunk/ -r29
pack Quake2Pack proprietary zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/Quake2Pack.zip
pack Quake2WorldPack GPL svn svn://jdolan.dyndns.org/quake2world/trunk/gtkradiant
pack QuakePack proprietary zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/QuakePack.zip
pack TremulousPack proprietary zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/TremulousPack.zip
pack UFOAIPack proprietary svn https://zerowing.idsoftware.com/svn/radiant.gamepacks/UFOAIPack/branches/1.5/
-pack WarsowPack GPL svn https://svn.bountysource.com/wswpack/trunk/netradiant/games/WarsowPack/
+#pack WarsowPack GPL svn https://svn.bountysource.com/wswpack/trunk/netradiant/games/WarsowPack/
+pack WarsowPack GPL zip1 http://ingar.satgnu.net/files/gtkradiant/gamepacks/WarsowPack.zip
pack XonoticPack GPL git git://git.xonotic.org/xonotic/netradiant-xonoticpack.git
finkgetdeps "$INSTALLDIR/radiant.$EXE"
echo Warning: this only works if only ONE version of gtk-2.0 and pango is installed
-for LIB in "$MACLIBDIR"/gtk-2.0/*/loaders/libpixbufloader-bmp.so; do
+LAST=
+for LIB in "$MACLIBDIR"/gtk-2.0/*/loaders/libpixbufloader-bmp.so "$MACLIBDIR"/gdk-pixbuf-2.0/*/loaders/libpixbufloader-bmp.so; do
+ [ -f "$LIB" ] || continue
LAST=$LIB
done
cp -L "$LAST" "$INSTALLDIR"
finkgetdeps "$LAST"
+LAST=
for LIB in "$MACLIBDIR"/pango/*/modules/pango-basic-fc.so; do
+ [ -f "$LIB" ] || continue
LAST=$LIB
done
cp -L "$LAST" "$INSTALLDIR"
finkgetdeps "$LAST"
+LAST=
for LIB in "$MACLIBDIR"/pango/*/modules/pango-basic-x.so; do
+ [ -f "$LIB" ] || continue
LAST=$LIB
done
cp -L "$LAST" "$INSTALLDIR"
pack="$pack/tools"
fi
for GAMEFILE in "$pack/games"/*.game; do
- $CP "$GAMEFILE" "$dest/games/"
+ if [ x"$GAMEFILE" != x"$pack/games/*.game" ]; then
+ $CP "$GAMEFILE" "$dest/games/"
+ fi
done
for GAMEDIR in "$pack"/*.game; do
- $CP_R "$GAMEDIR" "$dest/"
+ if [ x"$GAMEDIR" != x"$pack/*.game" ]; then
+ $CP_R "$GAMEDIR" "$dest/"
+ fi
done
#define INCLUDED_MEMORY_ALLOCATOR_H
#include <memory>
+#include <stddef.h>
#if 0
void PicoSetSurfaceData( picoSurface_t *surface, void *data );
void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type );
-void PicoSetSurfaceName( picoSurface_t *surface, char *name );
+void PicoSetSurfaceName( picoSurface_t *surface, const char *name );
void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader );
void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz );
void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
int PicoRemapModel( picoModel_t *model, char *remapFile );
-void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors, picoShader_t* shader, picoIndex_t* smoothingGroup);
+void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors, picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup);
/* end marker */
#ifdef __cplusplus
int lwValidateObject( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
{
- unsigned int id, formsize, type;
+ unsigned int id, type;
/* open the file */
set_flen( 0 );
id = getU4( fp );
- formsize = getU4( fp );
+ /* formsize = */ getU4( fp );
type = getU4( fp );
if ( 12 != get_flen() ) {
return PICO_PMV_ERROR_SIZE;
int lwValidateObject5( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
{
- unsigned int id, formsize, type;
+ unsigned int id, type;
/* open the file */
set_flen( 0 );
id = getU4( fp );
- formsize = getU4( fp );
+ /* formsize = */ getU4( fp );
type = getU4( fp );
if ( 12 != get_flen() ) {
return PICO_PMV_ERROR_SIZE;
-void PicoSetSurfaceName( picoSurface_t *surface, char *name )
+void PicoSetSurfaceName( picoSurface_t *surface, const char *name )
{
if( surface == NULL || name == NULL )
return;
void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
- picoShader_t* shader, picoIndex_t* smoothingGroup )
+ picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup )
{
int i,j;
int vertDataIndex;
for ( i = 0 ; i < model->numSurfaces ; i++ )
{
workSurface = model->surface[i];
+ if ( !name || !strcmp(workSurface->name, name) )
if ( workSurface->shader == shader )
{
break;
/* do surface setup */
PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
- PicoSetSurfaceName( workSurface, shader->name );
+ PicoSetSurfaceName( workSurface, name ? name : shader->name );
PicoSetSurfaceShader( workSurface, shader );
}
#endif
-static void _ase_submit_triangles( picoModel_t* model , aseMaterial_t* materials , aseVertex_t* vertices, aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces )
+static void _ase_submit_triangles( picoModel_t* model , aseMaterial_t* materials , aseVertex_t* vertices, aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces, const char *name )
{
aseFacesIter_t i = faces, end = faces + numFaces;
for(; i != end; ++i)
}
/* submit the triangle to the model */
- PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader, smooth );
+ PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader, name, smooth );
}
}
}
else if (!_pico_stricmp(p->token,"*mesh"))
{
/* finish existing surface */
- _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
+ _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces, lastNodeName);
_pico_free(faces);
_pico_free(vertices);
_pico_free(texcoords);
}
/* ydnar: finish existing surface */
- _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
+ _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces, lastNodeName);
_pico_free(faces);
_pico_free(vertices);
_pico_free(texcoords);
{
int i, j, dups, dup_index;
int fm_file_pos;
- short tot_numVerts;
index_LUT_t *p_index_LUT, *p_index_LUT2, *p_index_LUT3;
index_DUP_LUT_t *p_index_LUT_DUPS;
}
// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
- tot_numVerts = fm_head->numXYZ;
dups = 0;
triangle = tri_verts;
static picoModel_t *_md2_load( PM_PARAMS_LOAD )
{
int i, j, dups, dup_index;
- short tot_numVerts;
index_LUT_t *p_index_LUT, *p_index_LUT2, *p_index_LUT3;
index_DUP_LUT_t *p_index_LUT_DUPS;
md2Triangle_t *p_md2Triangle;
}
// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
- tot_numVerts = md2->numXYZ;
dups = 0;
for(i=0; i<md2->numTris; i++)
{
if(curSurface == NULL)
{
- _pico_printf( PICO_ERROR,"No group defined for faces, so creating an autoSurface in OBJ, line %d.",p->curLine);
+ _pico_printf( PICO_WARNING,"No group defined for faces, so creating an autoSurface in OBJ, line %d.",p->curLine);
AUTO_GROUPNAME(autoGroupNameBuf);
NEW_SURFACE(autoGroupNameBuf);
}
if(curFace != 0 || curSurface == NULL)
{
- _pico_printf( PICO_ERROR,"No group defined for usemtl, so creating an autoSurface in OBJ, line %d.",p->curLine);
+ _pico_printf( PICO_WARNING,"No group defined for usemtl, so creating an autoSurface in OBJ, line %d.",p->curLine);
AUTO_GROUPNAME(autoGroupNameBuf);
NEW_SURFACE(autoGroupNameBuf);
}
shader = PicoFindShader( model, name, 1 );
if (shader == NULL)
{
- _pico_printf( PICO_ERROR,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine);
+ _pico_printf( PICO_WARNING,"Undefined material name in OBJ, line %d. Making a default shader.",p->curLine);
/* create a new pico shader */
shader = PicoNewShader( model );
#include <list>
+#include <vector>
#include "generic/callback.h"
#include "generic/static.h"
#include "stream/stringstream.h"
#include "os/path.h"
#include "moduleobservers.h"
+#include "filematch.h"
#define VFS_MAXDIRS 64
for(j = 0; j < g_numForbiddenDirs; ++j)
{
- if(!string_compare_nocase_upper(directory, g_strForbiddenDirs[j])
- || (string_length(directory) > string_length(g_strForbiddenDirs[j]) && directory[string_length(directory) - string_length(g_strForbiddenDirs[j]) - 1] == '/' && !string_compare_nocase_upper(directory + string_length(directory) - string_length(g_strForbiddenDirs[j]), g_strForbiddenDirs[j])))
+ char* dbuf = g_strdup(directory);
+ if(*dbuf && dbuf[strlen(dbuf)-1] == '/')
+ dbuf[strlen(dbuf)-1] = 0;
+ const char *p = strrchr(dbuf, '/');
+ p = (p ? (p+1) : dbuf);
+ if(matchpattern(p, g_strForbiddenDirs[j], TRUE))
+ {
+ g_free(dbuf);
break;
+ }
+ g_free(dbuf);
}
if(j < g_numForbiddenDirs)
{
if(name == 0)
break;
- for(j = 0; j < g_numForbiddenDirs; ++j)
- if(!string_compare_nocase_upper(name, g_strForbiddenDirs[j]))
- break;
+ for(j = 0; j < g_numForbiddenDirs; ++j)
+ {
+ const char *p = strrchr(name, '/');
+ p = (p ? (p+1) : name);
+ if(matchpattern(p, g_strForbiddenDirs[j], TRUE))
+ break;
+ }
if(j < g_numForbiddenDirs)
continue;
{
g_showAlternativeTextureProjectionOption = true;
+ const char *value = g_pGameDescription->getKeyValue("brush_primit");
+ if(!string_empty(value))
+ g_useAlternativeTextureProjection.m_latched = atoi(value);
+
GlobalPreferenceSystem().registerPreference(
"AlternativeTextureProjection",
BoolImportStringCaller(g_useAlternativeTextureProjection.m_latched),
for(brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i)
{
++m_after;
- NodeSmartReference node((new BrushNode())->node());
(*i)->removeEmptyFaces();
- ASSERT_MESSAGE(!(*i)->empty(), "brush left with no faces after subtract");
- Node_getBrush(node)->copy(*(*i));
- delete (*i);
- Node_getTraversable(path.parent())->insert(node);
+ if(!(*i)->empty())
+ {
+ NodeSmartReference node((new BrushNode())->node());
+ Node_getBrush(node)->copy(*(*i));
+ delete (*i);
+ Node_getTraversable(path.parent())->insert(node);
+ }
+ else
+ delete (*i);
}
Path_deleteTop(path);
}
#include "entity.h"
#include "mainframe.h"
#include "textureentry.h"
+#include "groupdialog.h"
GtkEntry* numeric_entry_new()
{
GlobalEntityClassManager().detach(g_EntityInspector);
}
+const char *EntityInspector_getCurrentKey()
+{
+ if(!GroupDialog_isShown())
+ return 0;
+ if(GroupDialog_getPage() != g_page_entity)
+ return 0;
+ return gtk_entry_get_text(g_entityKeyEntry);
+}
GtkWidget* EntityInspector_constructWindow(GtkWindow* parent);
void EntityInspector_construct();
void EntityInspector_destroy();
+const char *EntityInspector_getCurrentKey();
#endif
void GroupDialog_showPage(GtkWidget* page);
void GroupDialog_updatePageTitle(GtkWidget* page);
+bool GroupDialog_isShown();
+GtkWidget* GroupDialog_getPage();
#endif
// Home Paths
+#ifdef WIN32
+#include <shlobj.h>
+#include <objbase.h>
+const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}};
+#define qREFKNOWNFOLDERID GUID
+#define qKF_FLAG_CREATE 0x8000
+#define qKF_FLAG_NO_ALIAS 0x1000
+typedef HRESULT (WINAPI qSHGetKnownFolderPath_t) (qREFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
+static qSHGetKnownFolderPath_t *qSHGetKnownFolderPath;
+#endif
void HomePaths_Realise()
{
-#if defined(POSIX)
- const char* prefix = g_pGameDescription->getKeyValue("prefix");
- if(!string_empty(prefix))
+ do
{
- StringOutputStream path(256);
- path << DirectoryCleaned(g_get_home_dir()) << prefix << "/";
- g_qeglobals.m_userEnginePath = path.c_str();
- Q_mkdir(g_qeglobals.m_userEnginePath.c_str());
- }
- else
+ const char* prefix = g_pGameDescription->getKeyValue("prefix");
+ if(!string_empty(prefix))
+ {
+ StringOutputStream path(256);
+
+#if defined(__APPLE__)
+ path.clear();
+ path << DirectoryCleaned(g_get_home_dir()) << "Library/Application Support" << (prefix+1) << "/";
+ if(file_is_directory(path.c_str()))
+ {
+ g_qeglobals.m_userEnginePath = path.c_str();
+ break;
+ }
#endif
- {
+
+#if defined(WIN32)
+ TCHAR mydocsdir[MAX_PATH + 1];
+ wchar_t *mydocsdirw;
+ HMODULE shfolder = LoadLibrary("shfolder.dll");
+ if(shfolder)
+ qSHGetKnownFolderPath = (qSHGetKnownFolderPath_t *) GetProcAddress(shfolder, "SHGetKnownFolderPath");
+ else
+ qSHGetKnownFolderPath = NULL;
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ if(qSHGetKnownFolderPath && qSHGetKnownFolderPath(qFOLDERID_SavedGames, qKF_FLAG_CREATE | qKF_FLAG_NO_ALIAS, NULL, &mydocsdirw) == S_OK)
+ {
+ memset(mydocsdir, 0, sizeof(mydocsdir));
+ wcstombs(mydocsdir, mydocsdirw, sizeof(mydocsdir)-1);
+ CoTaskMemFree(mydocsdirw);
+ path.clear();
+ path << DirectoryCleaned(mydocsdir) << (prefix+1) << "/";
+ if(file_is_directory(path.c_str()))
+ {
+ g_qeglobals.m_userEnginePath = path.c_str();
+ CoUninitialize();
+ FreeLibrary(shfolder);
+ break;
+ }
+ }
+ CoUninitialize();
+ if(shfolder)
+ FreeLibrary(shfolder);
+ if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, mydocsdir))
+ {
+ path.clear();
+ path << DirectoryCleaned(mydocsdir) << "My Games/" << (prefix+1) << "/";
+ // win32: only add it if it already exists
+ if(file_is_directory(path.c_str()))
+ {
+ g_qeglobals.m_userEnginePath = path.c_str();
+ break;
+ }
+ }
+#endif
+
+#if defined(POSIX)
+ path.clear();
+ path << DirectoryCleaned(g_get_home_dir()) << prefix << "/";
+ g_qeglobals.m_userEnginePath = path.c_str();
+ break;
+#endif
+ }
+
g_qeglobals.m_userEnginePath = EnginePath_get();
}
+ while(0);
+
+ Q_mkdir(g_qeglobals.m_userEnginePath.c_str());
{
StringOutputStream path(256);
MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler& handler);
void XYWindowMouseDown_disconnect(MouseEventHandlerId id);
+extern GtkWidget* g_page_entity;
+
#endif
output.push_string((type && *type) ? type : "quake3");
output.push_string(" -fs_basepath \"");
output.push_string(EnginePath_get());
+ output.push_string(" -fs_homepath \"");
+ output.push_string(g_qeglobals.m_userEnginePath.c_str());
output.push_string("\" -fs_game ");
output.push_string(gamename_get());
output.push_string(" -convert -format ");
const char* gamename = gamename_get();
const char* basegame = basegame_get();
-#if defined(POSIX)
const char* userRoot = g_qeglobals.m_userEnginePath.c_str();
-#endif
const char* globalRoot = EnginePath_get();
// if we have a mod dir
if(!string_equal(gamename, basegame))
{
-#if defined(POSIX)
// ~/.<gameprefix>/<fs_game>
+ if(userRoot)
{
StringOutputStream userGamePath(256);
userGamePath << userRoot << gamename << '/';
GlobalFileSystem().initDirectory(userGamePath.c_str());
}
-#endif
// <fs_basepath>/<fs_game>
{
}
}
-#if defined(POSIX)
// ~/.<gameprefix>/<fs_main>
+ if(userRoot)
{
StringOutputStream userBasePath(256);
userBasePath << userRoot << basegame << '/';
GlobalFileSystem().initDirectory(userBasePath.c_str());
}
-#endif
// <fs_basepath>/<fs_main>
{
build_set_variable("RadiantPath", AppPath_get());
build_set_variable("ExecutableType", RADIANT_EXECUTABLE);
build_set_variable("EnginePath", EnginePath_get());
+ build_set_variable("UserEnginePath", g_qeglobals.m_userEnginePath.c_str());
build_set_variable("MonitorAddress", (g_WatchBSP_Enabled) ? "127.0.0.1:39000" : "");
build_set_variable("GameName", gamename_get());
#include "mainframe.h"
#include "grid.h"
#include "map.h"
+#include "entityinspector.h"
class InvertSelectionWalker : public scene::Graph::Walker
{
SelectionSystem::EMode m_mode;
- mutable Selectable* m_selectable;
public:
InvertSelectionWalker(SelectionSystem::EMode mode)
- : m_mode(mode), m_selectable(0)
+ : m_mode(mode)
{
}
bool pre(const scene::Path& path, scene::Instance& instance) const
+ {
+ return true;
+ }
+ void post(const scene::Path& path, scene::Instance& instance) const
{
Selectable* selectable = Instance_getSelectable(instance);
if(selectable)
{
case SelectionSystem::eEntity:
if(Node_isEntity(path.top()) != 0)
- {
- m_selectable = path.top().get().visible() ? selectable : 0;
- }
+ if(path.top().get().visible())
+ selectable->setSelected(!selectable->isSelected());
break;
case SelectionSystem::ePrimitive:
- m_selectable = path.top().get().visible() ? selectable : 0;
+ if(path.top().get().visible())
+ selectable->setSelected(!selectable->isSelected());
break;
case SelectionSystem::eComponent:
break;
}
}
- return true;
- }
- void post(const scene::Path& path, scene::Instance& instance) const
- {
- if(m_selectable != 0)
- {
- m_selectable->setSelected(!m_selectable->isSelected());
- m_selectable = 0;
- }
}
};
}
}
-typedef std::vector<const char*> Classnames;
+typedef std::vector<const char*> PropertyValues;
-bool classnames_match_entity(const Classnames& classnames, Entity* entity)
+bool propertyvalues_contain(const PropertyValues& propertyvalues, const char *str)
{
- for(Classnames::const_iterator i = classnames.begin(); i != classnames.end(); ++i)
+ for(PropertyValues::const_iterator i = propertyvalues.begin(); i != propertyvalues.end(); ++i)
{
- if(string_equal(entity->getKeyValue("classname"), *i))
+ if(string_equal(str, *i))
{
return true;
}
return false;
}
-class EntityFindByClassnameWalker : public scene::Graph::Walker
+class EntityFindByPropertyValueWalker : public scene::Graph::Walker
{
- const Classnames& m_classnames;
+ const PropertyValues& m_propertyvalues;
+ const char *m_prop;
public:
- EntityFindByClassnameWalker(const Classnames& classnames)
- : m_classnames(classnames)
+ EntityFindByPropertyValueWalker(const char *prop, const PropertyValues& propertyvalues)
+ : m_propertyvalues(propertyvalues), m_prop(prop)
{
}
bool pre(const scene::Path& path, scene::Instance& instance) const
{
Entity* entity = Node_getEntity(path.top());
if(entity != 0
- && classnames_match_entity(m_classnames, entity))
+ && propertyvalues_contain(m_propertyvalues, entity->getKeyValue(m_prop)))
{
Instance_getSelectable(instance)->setSelected(true);
}
}
};
-void Scene_EntitySelectByClassnames(scene::Graph& graph, const Classnames& classnames)
+void Scene_EntitySelectByPropertyValues(scene::Graph& graph, const char *prop, const PropertyValues& propertyvalues)
{
- graph.traverse(EntityFindByClassnameWalker(classnames));
+ graph.traverse(EntityFindByPropertyValueWalker(prop, propertyvalues));
}
-class EntityGetSelectedClassnamesWalker : public scene::Graph::Walker
+class EntityGetSelectedPropertyValuesWalker : public scene::Graph::Walker
{
- Classnames& m_classnames;
+ PropertyValues& m_propertyvalues;
+ const char *m_prop;
public:
- EntityGetSelectedClassnamesWalker(Classnames& classnames)
- : m_classnames(classnames)
+ EntityGetSelectedPropertyValuesWalker(const char *prop, PropertyValues& propertyvalues)
+ : m_propertyvalues(propertyvalues), m_prop(prop)
{
}
bool pre(const scene::Path& path, scene::Instance& instance) const
Entity* entity = Node_getEntity(path.top());
if(entity != 0)
{
- m_classnames.push_back(entity->getKeyValue("classname"));
+ if(!propertyvalues_contain(m_propertyvalues, entity->getKeyValue(m_prop)))
+ m_propertyvalues.push_back(entity->getKeyValue(m_prop));
}
}
return true;
}
};
-void Scene_EntityGetClassnames(scene::Graph& graph, Classnames& classnames)
+void Scene_EntityGetPropertyValues(scene::Graph& graph, const char *prop, PropertyValues& propertyvalues)
{
- graph.traverse(EntityGetSelectedClassnamesWalker(classnames));
+ graph.traverse(EntityGetSelectedPropertyValuesWalker(prop, propertyvalues));
}
void Select_AllOfType()
}
else
{
- Classnames classnames;
- Scene_EntityGetClassnames(GlobalSceneGraph(), classnames);
+ PropertyValues propertyvalues;
+ const char *prop = EntityInspector_getCurrentKey();
+ if(!prop || !*prop)
+ prop = "classname";
+ Scene_EntityGetPropertyValues(GlobalSceneGraph(), prop, propertyvalues);
GlobalSelectionSystem().setSelectedAll(false);
- if(!classnames.empty())
+ if(!propertyvalues.empty())
{
- Scene_EntitySelectByClassnames(GlobalSceneGraph(), classnames);
+ Scene_EntitySelectByPropertyValues(GlobalSceneGraph(), prop, propertyvalues);
}
else
{
const ModifierFlags c_modifier_replace_face = c_modifier_replace | c_modifier_face;
const ButtonIdentifier c_button_texture = c_buttonMiddle;
-const ModifierFlags c_modifier_apply_texture = c_modifierControl | c_modifierShift;
+const ModifierFlags c_modifier_apply_texture1 = c_modifierControl | c_modifierShift;
+const ModifierFlags c_modifier_apply_texture2 = c_modifierControl;
+const ModifierFlags c_modifier_apply_texture3 = c_modifierShift;
const ModifierFlags c_modifier_copy_texture = c_modifierNone;
class Selector_
ConstructSelectionTest(scissored, SelectionBoxForPoint(&devicePosition[0], &m_selector.m_epsilon[0]));
SelectionVolume volume(scissored);
- if(modifiers == c_modifier_apply_texture)
+ if(modifiers == c_modifier_apply_texture1 || modifiers == c_modifier_apply_texture2 || modifiers == c_modifier_apply_texture3)
{
Scene_applyClosestTexture(volume);
}
{
byte *out;
int i;
- int bfSize;
int bfOffBits;
int structSize;
int bcWidth;
Error ("%s is not a bmp file", filename);
}
- bfSize = bufLittleLong (in, len, &pos);
+ /* bfSize = */ bufLittleLong (in, len, &pos);
bufLittleShort(in, len, &pos);
bufLittleShort(in, len, &pos);
bfOffBits = bufLittleLong (in, len, &pos);
==============
*/
qboolean TokenAvailable (void) {
- int oldLine, oldScriptLine;
+ int oldLine;
qboolean r;
/* save */
oldLine = scriptline;
- oldScriptLine = script->line;
/* test */
r = GetToken( qtrue );
#include <sys/stat.h>
#include "cmdlib.h"
+#include "filematch.h"
#include "mathlib.h"
#include "inout.h"
#include "vfs.h"
for(j = 0; j < g_numForbiddenDirs; ++j)
{
- if(!Q_stricmp(path, g_strForbiddenDirs[j])
- || (strlen(path) > strlen(g_strForbiddenDirs[j]) && path[strlen(path) - strlen(g_strForbiddenDirs[j]) - 1] == '/' && !Q_stricmp(path + strlen(path) - strlen(g_strForbiddenDirs[j]), g_strForbiddenDirs[j])))
+ char* dbuf = g_strdup(path);
+ if(*dbuf && dbuf[strlen(dbuf)-1] == '/')
+ dbuf[strlen(dbuf)-1] = 0;
+ const char *p = strrchr(dbuf, '/');
+ p = (p ? (p+1) : dbuf);
+ if(matchpattern(p, g_strForbiddenDirs[j], TRUE))
+ {
+ g_free(dbuf);
break;
+ }
+ g_free(dbuf);
}
if(j < g_numForbiddenDirs)
return;
break;
for(j = 0; j < g_numForbiddenDirs; ++j)
- if(!Q_stricmp(name, g_strForbiddenDirs[j]))
+ {
+ const char *p = strrchr(name, '/');
+ p = (p ? (p+1) : name);
+ if(matchpattern(p, g_strForbiddenDirs[j], TRUE))
break;
+ }
if(j < g_numForbiddenDirs)
continue;
fprintf( f, "\t*PROP_RECVSHADOW\t1\r\n" );
if(lightmapsAsTexcoord)
{
- if(ds->lightmapNum[0] >= 0 && ds->lightmapNum[0] + deluxemap < numLightmapsASE)
+ if(ds->lightmapNum[0] >= 0 && ds->lightmapNum[0] + (int)deluxemap < numLightmapsASE)
fprintf( f, "\t*MATERIAL_REF\t%d\r\n", ds->lightmapNum[0] + deluxemap );
else
Sys_Printf( "WARNING: lightmap %d out of range, not exporting\n", ds->lightmapNum[0] + deluxemap );
side_t *buildSide;
bspShader_t *shader;
char *texture;
- bspPlane_t *plane;
plane_t *buildPlane;
vec3_t pts[ 3 ];
bspDrawVert_t *vert[3];
- int valid;
/* start brush */
//if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
// continue;
- /* get plane */
- plane = &bspPlanes[ side->planeNum ];
-
/* add build side */
buildSide = &buildBrush->sides[ buildBrush->numsides ];
buildBrush->numsides++;
// - (triangles)
// - find the triangle that has most in common with our side
GetBestSurfaceTriangleMatchForBrushside(buildSide, vert);
- valid = 0;
/* get texture name */
if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
);
VectorSet(buildSide->texMat[i], D0 / D, D1 / D, D2 / D);
}
- valid = 1;
}
else
fprintf(stderr, "degenerate triangle found when solving texMat equations for\n(%f %f %f) (%f %f %f) (%f %f %f)\n( %f %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n",
buildSide->texMat[0][0], buildSide->texMat[0][1], FRAC(buildSide->texMat[0][2]),
buildSide->texMat[1][0], buildSide->texMat[1][1], FRAC(buildSide->texMat[1][2]),
texture,
- // DEBUG: valid ? 0 : C_DETAIL
0
);
}
);
VectorSet(sts[i], D0 / D, D1 / D, D2 / D);
}
- valid = 1;
}
else
fprintf(stderr, "degenerate triangle found when solving texDef equations\n"); // FIXME add stuff here
pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
texture,
shift[0], shift[1], rotate, scale[0], scale[1],
- // DEBUG: valid ? 0 : C_DETAIL
0
);
}
1.0f/16.0f, 0.0f, 0.0f,
0.0f, 1.0f/16.0f, 0.0f,
texture,
- // DEBUG: valid ? 0 : C_DETAIL
0
);
}
pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
texture,
0.0f, 0.0f, 0.0f, 0.25f, 0.25f,
- // DEBUG: valid ? 0 : C_DETAIL
0
);
}
int objLastShaderNum = -1;
static void ConvertSurfaceToOBJ( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin )
{
- int i, v, face, a, b, c;
+ int i, v, a, b, c;
bspDrawVert_t *dv;
/* ignore patches for now */
fprintf(f, "usemtl lm_%04d\r\n", ds->lightmapNum[0] + deluxemap);
objLastShaderNum = ds->lightmapNum[0] + deluxemap;
}
- if(ds->lightmapNum[0] + deluxemap < firstLightmap)
+ if(ds->lightmapNum[0] + (int)deluxemap < firstLightmap)
{
Sys_Printf( "WARNING: lightmap %d out of range (exporting anyway)\n", ds->lightmapNum[0] + deluxemap );
firstLightmap = ds->lightmapNum[0] + deluxemap;
/* export faces */
for( i = 0; i < ds->numIndexes; i += 3 )
{
- face = (i / 3);
a = bspDrawIndexes[ i + ds->firstIndex ];
c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
static void ConvertShaderToMTL( FILE *f, bspShader_t *shader, int shaderNum )
{
shaderInfo_t *si;
- char *c, filename[ 1024 ];
+ char filename[ 1024 ];
/* get shader */
winding_t *frontWinding, *backWinding;
int i;
int splitPlaneNum, compileFlags;
+#if 0
qboolean isstruct = qfalse;
+#endif
/* count faces left */
continue;
}
+#if 0
if(!(split->compileFlags & C_DETAIL))
isstruct = 1;
+#endif
/* determine which side the face falls on */
side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
png_struct *png;
png_info *info, *end;
pngBuffer_t pb;
- int bitDepth, colorType, channels;
+ int bitDepth, colorType;
png_uint_32 w, h, i;
byte **rowPointers;
png_get_IHDR( png, info,
&w, &h, &bitDepth, &colorType, NULL, NULL, NULL );
- /* read number of channels */
- channels = png_get_channels( png, info );
-
/* the following will probably bork on certain types of png images, but hey... */
/* force indexed/gray/trans chunk to rgb */
int angleSteps, elevationSteps;
float angle, elevation;
float angleStep, elevationStep;
- float step, start;
sun_t sun;
if( value <= 0.0f || iterations < 2 )
return;
- /* calculate some stuff */
- step = 2.0f / (iterations - 1);
- start = -1.0f;
-
/* basic sun setup */
VectorCopy( color, sun.color );
sun.deviance = 0.0f;
{
int i, j, k, v;
bspDrawSurface_t *ds;
- surfaceInfo_t *info;
float *radVertexLuxel;
radWinding_t rw;
/* get surface */
ds = &bspDrawSurfaces[ num ];
- info = &surfaceInfos[ num ];
/* each triangle is a potential emitter */
rw.numVerts = 3;
/* external model */
default:
- frame = IntForKey( e, "_frame" );
+ frame = 0;
+ if(strcmp("", ValueForKey( e, "_frame")))
+ frame = IntForKey(e, "_frame");
+ else if(strcmp("", ValueForKey( e, "frame")))
+ frame = IntForKey(e, "frame");
model = LoadModel( value, frame );
if( model == NULL )
continue;
vec3_t deluxel[ 3 ];
vec3_t origin[ 4 ], normal[ 4 ];
float biasDirs[ 4 ][ 2 ] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 1.0f }, { 1.0f, 1.0f } };
- vec3_t color, direction, total;
+ vec3_t color, direction = { 0, 0, 0 }, total;
/* limit check */
qboolean ClusterVisible( int a, int b )
{
- int portalClusters, leafBytes;
+ int leafBytes;
byte *pvs;
return qtrue;
/* get pvs data */
- portalClusters = ((int *) bspVisBytes)[ 0 ];
+ /* portalClusters = ((int *) bspVisBytes)[ 0 ]; */
leafBytes = ((int*) bspVisBytes)[ 1 ];
pvs = bspVisBytes + VIS_HEADER_SIZE + (a * leafBytes);
v5=floodlightIntensity;
v6=floodlightDirectionScale;
- sscanf( value, "%lf %lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
+ sscanf( value, "%lf %lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5, &v6);
floodlightRGB[0]=v1;
floodlightRGB[1]=v2;
qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm )
{
bspDrawSurface_t *ds, *ds2;
- surfaceInfo_t *info, *info2;
+ surfaceInfo_t *info;
int num2, n, i, axisNum;
float s, t, d, len, sampleSize;
- vec3_t mins, maxs, origin, faxis, size, exactSize, delta, normalized, vecs[ 2 ];
+ vec3_t mins, maxs, origin, faxis, size, delta, normalized, vecs[ 2 ];
vec4_t plane;
bspDrawVert_t *verts;
/* round to the lightmap resolution */
for( i = 0; i < 3; i++ )
{
- exactSize[ i ] = lm->maxs[ i ] - lm->mins[ i ];
mins[ i ] = sampleSize * floor( lm->mins[ i ] / sampleSize );
maxs[ i ] = sampleSize * ceil( lm->maxs[ i ] / sampleSize );
size[ i ] = (maxs[ i ] - mins[ i ]) / sampleSize + 1.0f;
/* get surface */
num2 = lightSurfaces[ lm->firstLightSurface + n ];
ds2 = &bspDrawSurfaces[ num2 ];
- info2 = &surfaceInfos[ num2 ];
verts = &yDrawVerts[ ds2->firstVert ];
/* set the lightmap texture coordinates in yDrawVerts in [0, superSample * lm->customWidth] space */
/* get first drawsurface */
num2 = lightSurfaces[ lm->firstLightSurface ];
ds2 = &bspDrawSurfaces[ num2 ];
- info2 = &surfaceInfos[ num2 ];
verts = &yDrawVerts[ ds2->firstVert ];
/* calculate lightmap origin */
int i, j, k, s,num, num2;
bspModel_t *model;
bspLeaf_t *leaf;
- bspDrawSurface_t *ds, *ds2;
+ bspDrawSurface_t *ds;
surfaceInfo_t *info, *info2;
rawLightmap_t *lm;
qboolean added;
{
/* get info and attempt early out */
num2 = sortSurfaces[ j ];
- ds2 = &bspDrawSurfaces[ num2 ];
info2 = &surfaceInfos[ num2 ];
if( info2->hasLightmap == qfalse || info2->lm != NULL )
continue;
numStitched, numCandidates, numLuxels, f, fOld, start;
rawLightmap_t *lm, *a, *b, *c[ MAX_STITCH_CANDIDATES ];
float *luxel, *luxel2, *origin, *origin2, *normal, *normal2,
- sampleSize, average[ 3 ], totalColor, ootc, *luxels[ MAX_STITCH_LUXELS ];
+ sampleSize, average[ 3 ], totalColor, ootc;
/* disabled for now */
/* add luxel */
//% VectorSet( luxel2, 255, 0, 255 );
- luxels[ numLuxels++ ] = luxel2;
VectorAdd( average, luxel2, average );
totalColor += luxel2[ 3 ];
}
#define LIGHTMAP_RESERVE_COUNT 1
static void FindOutLightmaps( rawLightmap_t *lm )
{
- int i, j, k, lightmapNum, xMax, yMax, x, y, sx, sy, ox, oy, offset;
+ int i, j, k, lightmapNum, xMax, yMax, x = -1, y = -1, sx, sy, ox, oy, offset;
outLightmap_t *olm;
surfaceInfo_t *info;
float *luxel, *deluxel;
lump = (byte*) header + offset;
lumpInt = LittleLong( (int) *((int*) lump) );
lumpFloat = LittleFloat( (float) *((float*) lump) );
- memcpy( lumpString, (char*) lump, (length < sizeof(lumpString) ? length : sizeof(lumpString)-1) );
+ memcpy( lumpString, (char*) lump, ((size_t)length < sizeof(lumpString) ? (size_t)length : sizeof(lumpString)-1) );
lumpString[ sizeof(lumpString)-1 ] = '\0';
/* print basic lump info */
int contentFlags, compileFlags;
side_t *s;
int i;
- qboolean mixed;
+ //% qboolean mixed;
/* get initial compile flags from first side */
contentFlags = s->contentFlags;
compileFlags = s->compileFlags;
b->contentShader = s->shaderInfo;
- mixed = qfalse;
+ //% mixed = qfalse;
/* get the content/compile flags for every side in the brush */
for( i = 1; i < b->numsides; i++, s++ )
s = &b->sides[ i ];
if( s->shaderInfo == NULL )
continue;
- if( s->contentFlags != contentFlags || s->compileFlags != compileFlags )
- mixed = qtrue;
+ //% if( s->contentFlags != contentFlags || s->compileFlags != compileFlags )
+ //% mixed = qtrue;
contentFlags |= s->contentFlags;
compileFlags |= s->compileFlags;
static void ParseBrush( qboolean onlyLights, qboolean noCollapseGroups )
{
- brush_t *b;
-
-
/* parse the brush out of the map */
ParseRawBrush( onlyLights );
}
/* finish the brush */
- b = FinishBrush(noCollapseGroups);
+ FinishBrush(noCollapseGroups);
}
void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle )
{
- int i, j, k, s, numSurfaces;
+ int i, j, s, numSurfaces;
m4x4_t identity, nTransform;
picoModel_t *model;
picoShader_t *shader;
if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
continue;
- /* allocate a surface (ydnar: gs mods) */
- ds = AllocDrawSurface( SURFACE_TRIANGLES );
- ds->entityNum = eNum;
- ds->castShadows = castShadows;
- ds->recvShadows = recvShadows;
-
/* get shader name */
shader = PicoGetSurfaceShader( surface );
if( shader == NULL )
else
si = ShaderInfoForShader( picoShaderName );
+ /* allocate a surface (ydnar: gs mods) */
+ ds = AllocDrawSurface( SURFACE_TRIANGLES );
+ ds->entityNum = eNum;
+ ds->castShadows = castShadows;
+ ds->recvShadows = recvShadows;
+
/* set shader */
ds->shaderInfo = si;
}
/* get model frame */
- frame = IntForKey( e2, "_frame" );
+ frame = 0;
+ if(strcmp("", ValueForKey( e2, "_frame")))
+ frame = IntForKey(e2, "_frame");
+ else if(strcmp("", ValueForKey( e2, "frame")))
+ frame = IntForKey(e2, "frame");
/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
if( e == entities )
if( shadeAngle > 0.0f )
Sys_Printf( "misc_model has shading angle of %.4f\n", shadeAngle );
- skin = IntForKey(e2, "skin");
+ skin = 0;
+ if(strcmp("", ValueForKey( e2, "_skin")))
+ skin = IntForKey(e2, "_skin");
+ else if(strcmp("", ValueForKey( e2, "skin")))
+ skin = IntForKey(e2, "skin");
/* insert the model */
InsertModel( model, skin, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale, lightmapSampleSize, shadeAngle );
GetToken(qtrue);
if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
{
- // NOTE: we leak that!
ep = ParseEPair();
+ free(ep->key);
+ free(ep->value);
+ free(ep);
}
else
UnGetToken();
gets the user's home dir (for ~/.q3a)
*/
-char *LokiGetHomeDir( void )
+char *LokiGetHomeDir(void)
{
#ifndef Q_UNIX
return NULL;
char *home;
uid_t id;
struct passwd *pwd;
+ static char homeBuf[MAX_OS_PATH];
/* get the home environment variable */
}
endpwent();
}
+
+ snprintf(homeBuf, sizeof(homeBuf), "%s/.", home);
/* return it */
- return home;
+ return homeBuf;
#endif
}
void LokiInitPaths( char *argv0 )
{
+ char *home;
+
+ if(!homePath)
+ {
+ /* get home dir */
+ home = LokiGetHomeDir();
+ if( home == NULL )
+ home = ".";
+
+ /* set home path */
+ homePath = home;
+ }
+ else
+ home = homePath;
+
#ifndef Q_UNIX
/* this is kinda crap, but hey */
strcpy( installPath, "../" );
#else
char temp[ MAX_OS_PATH ];
char last0[ 2 ];
- char *home;
char *path;
char *last;
qboolean found;
- /* get home dir */
- home = LokiGetHomeDir();
- if( home == NULL )
- home = ".";
-
/* do some path divining */
strcpy( temp, argv0 );
if( strrchr( argv0, '/' ) )
*(strrchr( installPath, '/' )) = '\0';
*(strrchr( installPath, '/' ) + 1) = '\0';
}
-
- /* set home path */
- homePath = home;
#endif
}
void AddHomeBasePath( char *path )
{
- #ifdef Q_UNIX
- int i;
- char temp[ MAX_OS_PATH ];
-
-
- /* dummy check */
- if( path == NULL || path[ 0 ] == '\0' )
- return;
+ int i;
+ char temp[ MAX_OS_PATH ];
+ int homePathLen;
+
+ if(!homePath)
+ return;
+
+ /* dummy check */
+ if( path == NULL || path[ 0 ] == '\0' )
+ return;
+
+ /* strip leading dot, if homePath does not end in /. */
+ homePathLen = strlen(homePath);
+ if(!strcmp(path, "."))
+ {
+ /* -fs_homebase . means that -fs_home is to be used as is */
+ strcpy(temp, homePath);
+ }
+ else if(homePathLen >= 2 && !strcmp(homePath + homePathLen - 2, "/."))
+ {
+ /* remove trailing /. of homePath */
+ homePathLen -= 2;
+
+ /* concatenate home dir and path */
+ sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
+ }
+ else
+ {
+ /* remove leading . of path */
+ if(path[0] == '.')
+ ++path;
- /* make a hole */
- for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
- basePaths[ i + 1 ] = basePaths[ i ];
-
/* concatenate home dir and path */
sprintf( temp, "%s/%s", homePath, path );
-
- /* add it to the list */
- basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
- strcpy( basePaths[ 0 ], temp );
- CleanPath( basePaths[ 0 ] );
- numBasePaths++;
- #endif
+ }
+
+ /* make a hole */
+ for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
+ basePaths[ i + 1 ] = basePaths[ i ];
+
+ /* add it to the list */
+ basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
+ strcpy( basePaths[ 0 ], temp );
+ CleanPath( basePaths[ 0 ] );
+ numBasePaths++;
}
argv[ i ] = NULL;
}
- /* -fs_nohomebase */
+ /* -fs_home */
+ else if( strcmp( argv[ i ], "-fs_home" ) == 0 )
+ {
+ if( ++i >= *argc )
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ argv[ i - 1 ] = NULL;
+ homePath = argv[i];
+ argv[ i ] = NULL;
+ }
+
+ /* -fs_homebase */
else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
{
if( ++i >= *argc )
homeBasePath = argv[i];
argv[ i ] = NULL;
}
+
+ /* -fs_homepath - sets both of them */
+ else if( strcmp( argv[ i ], "-fs_homepath" ) == 0 )
+ {
+ if( ++i >= *argc )
+ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+ argv[ i - 1 ] = NULL;
+ homePath = argv[i];
+ homeBasePath = ".";
+ argv[ i ] = NULL;
+ }
}
/* remove processed arguments */
{
int x, y;
float st[ 2 ], o[ 2 ], dist, bestDist;
- vec4_t color, bestColor, delta;
+ vec4_t color, delta;
/* don't double-dip */
dist = delta[ 0 ] * delta[ 0 ] + delta[ 1 ] * delta[ 1 ] + delta[ 2 ] * delta[ 2 ] + delta[ 3 ] * delta[ 3 ];
if( dist < bestDist )
{
- VectorCopy( color, bestColor );
- bestColor[ 3 ] = color[ 3 ];
si->stFlat[ 0 ] = st[ 0 ];
si->stFlat[ 1 ] = st[ 1 ];
}
static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
{
- int x, y, refs;
+ int x, y, refs = 0;
for(y = 0; y + 2 < ds->patchHeight; y += 2)
for(x = 0; x + 2 < ds->patchWidth; x += 2)
/* roll the dice (model's odds scaled by vertex alpha) */
odds = model->odds * (tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ]) / 765.0f;
r = Random();
- if( r > model->odds )
+ if( r > odds )
return 0;
/* calculate scale */
int i, score, coincident, ai, bi, ci, oldTexRange[ 2 ];
float lmMax;
vec3_t mins, maxs;
- qboolean inTexRange, es, et;
+ qboolean inTexRange;
mapDrawSurface_t old;
oldTexRange[ 1 ] = ds->texRange[ 1 ];
inTexRange = CalcSurfaceTextureRange( ds );
- es = (ds->texRange[ 0 ] > oldTexRange[ 0 ]) ? qtrue : qfalse;
- et = (ds->texRange[ 1 ] > oldTexRange[ 1 ]) ? qtrue : qfalse;
-
if( inTexRange == qfalse && ds->numIndexes > 0 )
{
memcpy( ds, &old, sizeof( *ds ) );
int i, j, k;
edgeLine_t *e;
edgePoint_t *p;
- int originalVerts;
int counts[MAX_SURFACE_VERTS];
int originals[MAX_SURFACE_VERTS];
- int firstVert[MAX_SURFACE_VERTS];
bspDrawVert_t verts[MAX_SURFACE_VERTS], *v1, *v2;
int numVerts;
float start, end, frac, c;
vec3_t delta;
- originalVerts = ds->numVerts;
-
numVerts = 0;
for ( i = 0 ; i < ds->numVerts ; i++ )
{
counts[i] = 0;
- firstVert[i] = numVerts;
// copy first vert
if ( numVerts == MAX_SURFACE_VERTS ) {