From a2fbc53631da53b14bbac643f526ce41de7cf12a Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 26 Mar 2010 03:44:22 +0000 Subject: [PATCH] Migrated QCLib stuff over from WIP branch. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3525 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/cmdlib.h | 11 ++- engine/qclib/execloop.h | 10 +- engine/qclib/initlib.c | 8 +- engine/qclib/pr_edict.c | 21 +++-- engine/qclib/pr_x86.c | 62 +++++++++++-- engine/qclib/progsint.h | 18 ++-- engine/qclib/progslib.h | 31 +++++-- engine/qclib/qcc.h | 1 + engine/qclib/qcc_pr_comp.c | 52 ++++------- engine/qclib/qcc_pr_lex.c | 38 ++++++-- engine/qclib/qccmain.c | 186 +++++++++++++++++++++---------------- 11 files changed, 281 insertions(+), 157 deletions(-) diff --git a/engine/qclib/cmdlib.h b/engine/qclib/cmdlib.h index 2da377959..768d899a1 100644 --- a/engine/qclib/cmdlib.h +++ b/engine/qclib/cmdlib.h @@ -43,9 +43,18 @@ int QC_strcasecmp (const char *s1, const char *s2); #define QC_vsnprintf vsnprintf #endif +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) + #ifndef LIKEPRINTF + #define LIKEPRINTF(x) __attribute__((format(printf,x,x+1))) + #endif +#endif +#ifndef LIKEPRINTF +#define LIKEPRINTF(x) +#endif + double I_FloatTime (void); -void VARGS QCC_Error (int errortype, const char *error, ...); +void VARGS QCC_Error (int errortype, const char *error, ...) LIKEPRINTF(2); int CheckParm (char *check); diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index ad40f0e5b..365c93a49 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -431,7 +431,7 @@ reeval: st--; goto cont; #else - PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); #endif } ed = PROG_TO_EDICT(progfuncs, OPA->edict); @@ -448,7 +448,13 @@ reeval: st--; goto cont; #else - PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + { + ddef16_t *d16; + fdef_t *f; + d16 = ED_GlobalAtOfs16(progfuncs, st->a); + f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->fieldadjust); + PR_RunError (progfuncs, "assignment to read-only entity in %s (%s.%s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), PR_StringToNative(progfuncs, d16->s_name), f?f->name:NULL); + } #endif } diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index ca44b7813..1ca5728b3 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -95,9 +95,12 @@ int PR_InitEnts(progfuncs_t *progfuncs, int max_ents) sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize); prinst->edicttable[0] = sv_edicts; ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableAlloc(progfuncs, max_fields_size); - ED_ClearEdict(progfuncs, (edictrun_t *)sv_edicts); + QC_ClearEdict(progfuncs, sv_edicts); sv_num_edicts = 1; + if (externs->entspawn) + externs->entspawn((struct edict_s *)sv_edicts, false); + return max_fields_size; } edictrun_t tempedict; //used as a safty buffer @@ -643,7 +646,8 @@ progfuncs_t deffuncs = { PR_StringToProgs, PR_StringToNative, 0, - PR_QueryField + PR_QueryField, + QC_ClearEdict }; #undef printf diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 6ee3963e9..d6c211998 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -45,13 +45,14 @@ static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; /* ================= -ED_ClearEdict +QC_ClearEdict Sets everything to NULL ================= */ -void ED_ClearEdict (progfuncs_t *progfuncs, edictrun_t *e) +void QC_ClearEdict (progfuncs_t *progfuncs, struct edict_s *ed) { + edictrun_t *e = (edictrun_t *)ed; int num = e->entnum; memset (e->fields, 0, fields_size); e->isfree = false; @@ -66,7 +67,7 @@ edictrun_t *ED_AllocIntoTable (progfuncs_t *progfuncs, int num) memset(e, 0, externs->edictsize); e->fields = PRAddressableAlloc(progfuncs, fields_size); e->entnum = num; - ED_ClearEdict(progfuncs, e); + QC_ClearEdict(progfuncs, (struct edict_s*)e); return e; } @@ -97,7 +98,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) if (!e) e = ED_AllocIntoTable(progfuncs, i); else - ED_ClearEdict (progfuncs, e); + QC_ClearEdict (progfuncs, (struct edict_s*)e); if (externs->entspawn) externs->entspawn((struct edict_s *) e, false); @@ -117,7 +118,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) if (!e) e = ED_AllocIntoTable(progfuncs, i); else - ED_ClearEdict (progfuncs, e); + QC_ClearEdict (progfuncs, (struct edict_s*)e); if (externs->entspawn) externs->entspawn((struct edict_s *) e, false); @@ -146,7 +147,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) if (!e) e = ED_AllocIntoTable(progfuncs, i); else - ED_ClearEdict (progfuncs, e); + QC_ClearEdict (progfuncs, (struct edict_s*)e); if (externs->entspawn) externs->entspawn((struct edict_s *) e, false); @@ -1165,7 +1166,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) break; if (!data) { - printf ("ED_ParseEntity: EOF without closing brace"); + printf ("ED_ParseEntity: EOF without closing brace\n"); return NULL; } @@ -1184,13 +1185,13 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) data = QCC_COM_Parse (data); if (!data) { - printf ("ED_ParseEntity: EOF without closing brace"); + printf ("ED_ParseEntity: EOF without closing brace\n"); return NULL; } if (qcc_token[0] == '}') { - printf ("ED_ParseEntity: closing brace without data"); + printf ("ED_ParseEntity: closing brace without data\n"); return NULL; } @@ -3112,6 +3113,6 @@ unsigned int NUM_FOR_EDICT(progfuncs_t *progfuncs, struct edict_s *e) { edictrun_t *er = (edictrun_t*)e; if (er->entnum >= maxedicts) - Sys_Error ("QCLIB: NUM_FOR_EDICT: bad pointer (%i)", e); + Sys_Error ("QCLIB: NUM_FOR_EDICT: bad pointer (%p)", e); return er->entnum; } diff --git a/engine/qclib/pr_x86.c b/engine/qclib/pr_x86.c index acd0a1f44..4ebfdda20 100644 --- a/engine/qclib/pr_x86.c +++ b/engine/qclib/pr_x86.c @@ -119,7 +119,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) int *glob = (int*)current_progstate->globals; if (current_progstate->numbuiltins) - return; + return false; jitstatements = numstatements; @@ -259,7 +259,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) //remember to change the je above //err... exit depth? no idea - EmitByte(0xcd);EmitByte(op[i].op); + EmitByte(0xcd);EmitByte(op[i].op); //int $X //ret @@ -560,7 +560,7 @@ EmitByte(0xcc); //jmp 10 EmitByte(0xeb);EmitByte(0x0a); //mov 1.0f,glob[C] - EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].a);EmitFloat(1.0f); + EmitByte(0xc7);EmitByte(0x05); EmitAdr(glob + op[i].c);EmitFloat(1.0f); break; case OP_BITOR: //floats... @@ -972,7 +972,55 @@ EmitByte(0xcc); //add $12,%esp EmitByte(0x83); EmitByte(0xc4); EmitByte(0x0c); break; -/* +#if 0 + case OP_NOT_V: + //flds 0 + //flds glob[A+0] + //fcomip %st(1),%st + //jne _true + //flds glob[A+1] + //fcomip %st(1),%st + //jne _true + //flds glob[A+1] + //fcomip %st(1),%st + //jne _true + //mov 1,C + //jmp done + //_true: + //mov 0,C + //done: + break; + + case OP_EQ_V: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+0); + //flds glob[B] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b+0); + //fcomip %st(1),%st + EmitByte(0xdf);EmitByte(0xe9); + //fstp %st(0) (aka: pop) + EmitByte(0xdd);EmitByte(0xd8); + + //jncc _true + if (op[i].op == OP_NE_V) + EmitByte(0x74); //je + else + EmitByte(0x75); //jne + EmitByte(0x0c); +//_false0: + //mov 0.0f,c + EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f); + //jmp done + EmitByte(0xeb); EmitByte(0x0a); + + +//_true: + //mov 1.0f,c + EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f); +//_done: + break; + + case OP_EQ_V: EmitByte(0xcd);EmitByte(op[i].op); printf("QCJIT: instruction %i is not implemented\n", op[i].op); @@ -987,7 +1035,7 @@ EmitByte(0xcc); EmitByte(0xcd);EmitByte(op[i].op); printf("QCJIT: instruction %i is not implemented\n", op[i].op); break; -*/ +#endif default: printf("QCJIT: Extended instruction set %i is not supported, not using jit.\n", op[i].op); @@ -1021,7 +1069,7 @@ void PR_EnterJIT(progfuncs_t *progfuncs, int statement) { #ifdef __GNUC__ //call, it clobbers pretty much everything. - asm("call %0" :: "r"(statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx"); + asm("call *%0" :: "r"(statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx"); #elif defined(_MSC_VER) void *entry = statementoffsets[statement+1]; void *edicttable = prinst->edicttable; @@ -1036,4 +1084,4 @@ void PR_EnterJIT(progfuncs_t *progfuncs, int statement) #error "Sorry, no idea how to enter assembler safely for your compiler" #endif } -#endif \ No newline at end of file +#endif diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index e73d7afdd..39c316e50 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -1,4 +1,4 @@ -#ifdef WIN32 +#ifdef _WIN32 #ifndef AVAIL_ZLIB #ifdef _MSC_VER @@ -89,8 +89,13 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark); void *PRHunkAlloc(progfuncs_t *progfuncs, int size); void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount); +#ifdef printf +#undef LIKEPRINTF +#define LIKEPRINTF(x) +#endif + //void *HunkAlloc (int size); -char *VARGS qcva (char *text, ...); +char *VARGS qcva (char *text, ...) LIKEPRINTF(1); void QC_InitShares(progfuncs_t *progfuncs); void QC_StartShares(progfuncs_t *progfuncs); void QC_AddSharedVar(progfuncs_t *progfuncs, int num, int type); @@ -129,8 +134,6 @@ typedef union eval_s #endif */ - -#define MAX_ENT_LEAFS 16 typedef struct edictrun_s { pbool isfree; @@ -281,7 +284,7 @@ const extern unsigned int type_size[]; extern unsigned short pr_crc; -void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...); +void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...) LIKEPRINTF(2); void ED_PrintEdicts (progfuncs_t *progfuncs); void ED_PrintNum (progfuncs_t *progfuncs, int ent); @@ -447,7 +450,7 @@ func_t PR_FindFunc(progfuncs_t *progfncs, char *funcname, progsnum_t pnum); void PR_Configure (progfuncs_t *progfncs, int addressable_size, int max_progs); int PR_InitEnts(progfuncs_t *progfncs, int maxents); char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val); -void ED_ClearEdict (progfuncs_t *progfuncs, edictrun_t *e); +void QC_ClearEdict (progfuncs_t *progfuncs, struct edict_s *ed); void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount); void QC_FlushProgsOffsets(progfuncs_t *progfuncs); @@ -466,6 +469,9 @@ char *PR_GlobalStringNoContents (progfuncs_t *progfuncs, int ofs); pbool CompileFile(progfuncs_t *progfuncs, char *filename); +pbool PR_GenerateJit(progfuncs_t *progfuncs); +void PR_EnterJIT(progfuncs_t *progfuncs, int statement); + char *QCC_COM_Parse (char *data); extern char qcc_token[1024]; #endif diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 45aa91bf8..f3f4488a4 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -22,10 +22,16 @@ typedef char *string_t; */ #ifdef _MSC_VER -#define VARGS __cdecl + #define VARGS __cdecl +#endif +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) + #define LIKEPRINTF(x) __attribute__((format(printf,x,x+1))) +#endif +#ifndef LIKEPRINTF + #define LIKEPRINTF(x) #endif #ifndef VARGS -#define VARGS + #define VARGS #endif @@ -60,7 +66,7 @@ struct progfuncs_s { struct globalvars_s *(*globals) (progfuncs_t *prinst, progsnum_t num); //get the globals of a progs struct entvars_s *(*entvars) (progfuncs_t *prinst, struct edict_s *ent); //return a pointer to the entvars of an ent. can be achieved via the edict_t structure instead, so obsolete. - void (VARGS *RunError) (progfuncs_t *prinst, char *msg, ...); //builtins call this to say there was a problem + void (VARGS *RunError) (progfuncs_t *prinst, char *msg, ...) LIKEPRINTF(2); //builtins call this to say there was a problem void (*PrintEdict) (progfuncs_t *prinst, struct edict_s *ed); //get a listing of all vars on an edict (sent back via 'print') struct edict_s *(*EntAlloc) (progfuncs_t *prinst); @@ -137,7 +143,9 @@ struct progfuncs_s { char *(*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 + 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); }; typedef struct progexterns_s { @@ -146,9 +154,9 @@ typedef struct progexterns_s { 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); - int (VARGS *printf) (const char *, ...); - void (VARGS *Sys_Error) (const char *, ...); - void (VARGS *Abort) (char *, ...); + int (VARGS *printf) (const char *, ...) LIKEPRINTF(1); + void (VARGS *Sys_Error) (const char *, ...) LIKEPRINTF(1); + void (VARGS *Abort) (char *, ...) LIKEPRINTF(1); int edictsize; //size of edict_t 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 @@ -183,7 +191,9 @@ typedef struct progexterns_s { //FIXMEs void QC_AddSharedVar(progfuncs_t *progfuncs, int start, int size); void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *relstringtable); -void ED_Print (progfuncs_t *progfuncs, struct edict_s *ed); +void ED_Print(progfuncs_t *progfuncs, struct edict_s *ed); +char *PR_RemoveProgsString(progfuncs_t *progfuncs, string_t str); +int PR_GetFuncArgCount(progfuncs_t *progfuncs, func_t func); #if defined(QCLIBDLL_EXPORTS) __declspec(dllexport) @@ -218,7 +228,7 @@ typedef union eval_s #define PR_LoadProgs(pf, s, headercrc, builtins, numb) (*pf->LoadProgs) (pf, s, headercrc, builtins, numb) #define PR_InitEnts(pf, maxents) (*pf->InitEnts) (pf, maxents) #define PR_ExecuteProgram(pf, fnum) (*pf->ExecuteProgram) (pf, fnum) -#define PR_SwitchProgs(pf, num) (*pf->SwitchProgs) (pf, num); +#define PR_SwitchProgs(pf, num) (*pf->SwitchProgs) (pf, num) #define PR_globals(pf, num) (*pf->globals) (pf, num) #define PR_entvars(pf, ent) (*pf->entvars) (pf, ent) @@ -226,6 +236,7 @@ typedef union eval_s #define ED_Alloc(pf) (*pf->EntAlloc) (pf) #define ED_Free(pf, ed) (*pf->EntFree) (pf, ed) +#define ED_Clear(pf, ed) (*pf->EntClear) (pf, ed) #define PR_LoadEnts(pf, s, kf) (*pf->load_ents) (pf, s, kf) #define PR_SaveEnts(pf, buf, size, mode) (*pf->save_ents) (pf, buf, size, mode) @@ -251,7 +262,7 @@ typedef union eval_s #define PR_Alloc(pf,size) (*pf->Tempmem) (pf, size) #define PROG_TO_EDICT(pf, ed) (*pf->ProgsToEdict) (pf, ed) -#define EDICT_TO_PROG(pf, ed) (*pf->EdictToProgs) (pf, ed) +#define EDICT_TO_PROG(pf, ed) (*pf->EdictToProgs) (pf, (struct edict_s*)ed) #define PR_RegisterBuiltin(pf, name, func) (*pf->RegisterBuiltin) (pf, name, func) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 75b2b378c..65b360baf 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -477,6 +477,7 @@ extern pbool flag_laxcasts; extern pbool flag_hashonly; extern pbool flag_fasttrackarrays; extern pbool flag_assume_integer; +extern pbool flag_msvcstyle; extern pbool opt_overlaptemps; extern pbool opt_shortenifnots; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index fa2fcf59e..a76f2701e 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -74,6 +74,7 @@ pbool flag_caseinsensative; //symbols will be matched to an insensative case if pbool flag_laxcasts; //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code. pbool flag_hashonly; //Allows use of only #constant for precompiler constants, allows certain preqcc using mods to compile 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 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) @@ -1381,12 +1382,7 @@ static void QCC_LockActiveTemps(void) t->scope = pr_scope; t = t->next; } -} - -static void QCC_LockTemp(QCC_def_t *d) -{ - if (d->temp && d->temp->used) - d->temp->scope = pr_scope; + } static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement) @@ -2239,26 +2235,19 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //don't chain these... this expansion is not the same. { int st; - int need_lock = false; + for (st = numstatements-2; st>=0; st--) { if (statements[st].op == OP_ADDRESS) 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) - 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 statement_linenums[statement-statements] = statement_linenums[st]; statement->op = OP_ADDRESS; @@ -2363,7 +2352,6 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var op = &pr_opcodes[OP_STOREP_F]; QCC_FreeTemp(var_c); - var_c = NULL; QCC_FreeTemp(var_b); @@ -2380,24 +2368,18 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //don't chain these... this expansion is not the same. { int st; - int need_lock = false; for (st = numstatements-2; st>=0; st--) { if (statements[st].op == OP_ADDRESS) 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) - need_lock = true; - 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_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 statement_linenums[statement-statements] = statement_linenums[st]; statement->op = OP_ADDRESS; @@ -3448,6 +3430,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could { //t = (a/%1) / (nextent(world)/%1) //a/%1 does a (int)entity to float conversion type thing + func->initialized = 1; e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); QCC_PR_Expect(")"); @@ -4069,7 +4052,7 @@ PR_ParseValue Returns the global ofs for the current token ============ */ -QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass) +QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) { QCC_def_t *ao=NULL; //arrayoffset QCC_def_t *d, *nd, *od; @@ -4369,7 +4352,7 @@ reloop: if (d->scope) QCC_PR_ParseError(0, "Scoped array without specific engine support"); - if (QCC_PR_CheckToken("=")) + if (allowarrayassign && QCC_PR_CheckToken("=")) { QCC_def_t *args[2]; @@ -4662,7 +4645,7 @@ reloop: QCC_PR_Expect(")"); } else - field = QCC_PR_ParseValue(d->type); + field = QCC_PR_ParseValue(d->type, false); if (field->type->type == ev_field) { if (!field->type->aux_type) @@ -4997,7 +4980,7 @@ QCC_def_t *QCC_PR_Term (void) return e; } } - return QCC_PR_ParseValue (pr_classtype); + return QCC_PR_ParseValue (pr_classtype, true); } @@ -6546,7 +6529,7 @@ void QCC_PR_ParseAsm(void) { patch1 = &statements[numstatements]; - a = QCC_PR_ParseValue(pr_classtype); + a = QCC_PR_ParseValue(pr_classtype, false); QCC_PR_Statement3(&pr_opcodes[op], a, NULL, NULL, true); if (pr_token_type == tt_name) @@ -6565,8 +6548,8 @@ void QCC_PR_ParseAsm(void) { patch1 = &statements[numstatements]; - a = QCC_PR_ParseValue(pr_classtype); - b = QCC_PR_ParseValue(pr_classtype); + a = QCC_PR_ParseValue(pr_classtype, false); + b = QCC_PR_ParseValue(pr_classtype, false); QCC_PR_Statement3(&pr_opcodes[op], a, b, NULL, true); if (pr_token_type == tt_name) @@ -6585,15 +6568,15 @@ void QCC_PR_ParseAsm(void) else { if (pr_opcodes[op].type_a != &type_void) - a = QCC_PR_ParseValue(pr_classtype); + a = QCC_PR_ParseValue(pr_classtype, false); else a=NULL; if (pr_opcodes[op].type_b != &type_void) - b = QCC_PR_ParseValue(pr_classtype); + b = QCC_PR_ParseValue(pr_classtype, false); else b=NULL; if (pr_opcodes[op].associative==ASSOC_LEFT && pr_opcodes[op].type_c != &type_void) - c = QCC_PR_ParseValue(pr_classtype); + c = QCC_PR_ParseValue(pr_classtype, false); else c=NULL; @@ -9151,8 +9134,13 @@ void QCC_PR_ParseDefs (char *classname) i = 0; do { - if (QCC_PR_CheckImmediate("0")) + if (pr_token_type == tt_immediate && ( + (pr_immediate_type == type_integer && pr_immediate._int == 0) || + (pr_immediate_type == type_float && pr_immediate._float == 0))) + { + QCC_PR_Lex(); G_FUNCTION(def->ofs+i) = 0; + } else { name = QCC_PR_ParseName (); diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 6b442bca8..286da96f6 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -1401,7 +1401,7 @@ void QCC_PR_LexNumber (void) pr_file_p++; } pr_token[tokenlen++] = 0; - pr_immediate._float = atof(pr_token); + pr_immediate._float = (float)atof(pr_token); return; } else if (c == 'i') @@ -2419,7 +2419,7 @@ int QCC_PR_CheakCompConst(void) if (!strncmp(pr_file_p, "__NULL__", 8)) { static char retbuf[256]; - sprintf(retbuf, "~0"); + sprintf(retbuf, "0i"); pr_file_p = retbuf; QCC_PR_Lex(); //translate the macro's value pr_file_p = oldpr_file_p+8; @@ -2599,7 +2599,12 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def) if (qccwarningdisabled[type]) return; if (def->s_file) - printf ("%s:%i: %s is defined here\n", strings + def->s_file, def->s_line, def->name); + { + if (flag_msvcstyle) + printf ("%s(%i) : %s is defined here\n", strings + def->s_file, def->s_line, def->name); + else + printf ("%s:%i: %s is defined here\n", strings + def->s_file, def->s_line, def->name); + } } void *errorscope; void QCC_PR_PrintScope (void) @@ -2645,7 +2650,10 @@ void VARGS QCC_PR_ParseError (int errortype, char *error, ...) #endif QCC_PR_PrintScope(); - printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string); + if (flag_msvcstyle) + 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); } @@ -2662,7 +2670,10 @@ void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, char *error editbadfile(strings+s_file, pr_source_line); #endif QCC_PR_PrintScope(); - printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string); + if (flag_msvcstyle) + 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); QCC_PR_ParsePrintDef(WARN_ERROR, def); @@ -2683,12 +2694,18 @@ void VARGS QCC_PR_ParseWarning (int type, char *error, ...) QCC_PR_PrintScope(); if (type >= ERR_PARSEERRORS) { - printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string); + if (flag_msvcstyle) + 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); pr_error_count++; } else { - printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string); + if (flag_msvcstyle) + printf ("%s(%i) : warning: %s\n", strings + s_file, pr_source_line, string); + else + printf ("%s:%i: warning: %s\n", strings + s_file, pr_source_line, string); pr_warning_count++; } } @@ -2707,7 +2724,12 @@ void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...) QCC_PR_PrintScope(); if (file) - printf ("%s:%i: warning: %s\n", file, line, string); + { + if (flag_msvcstyle) + printf ("%s(%i) : warning: %s\n", file, line, string); + else + printf ("%s:%i: warning: %s\n", file, line, string); + } else printf ("warning: %s\n", string); pr_warning_count++; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 48d1994e0..770fb44ea 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -15,6 +15,7 @@ extern int optres_test2; int writeasm; static pbool pr_werror; +pbool verbose; pbool QCC_PR_SimpleGetToken (void); @@ -230,6 +231,7 @@ compiler_flag_t compiler_flag[] = { {&flag_laxcasts, FLAG_MIDCOMPILE,"lax", "Lax type checks", "Disables many errors (generating warnings instead) when function calls or operations refer to two normally incompatible types. This is required for reacc support, and can also allow certain (evil) mods to compile that were originally written for frikqcc."}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code. {&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_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."}, {NULL} @@ -634,10 +636,13 @@ pbool QCC_WriteData (int crc) //include a type block? types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES"); //useful for debugging and saving (maybe, anyway...). - if (qcc_targetformat == QCF_DARKPLACES) - printf("DarkPlaces or FTE will be required\n"); - else - printf("An FTE executor will be required\n"); + if (verbose) + { + if (qcc_targetformat == QCF_DARKPLACES) + printf("DarkPlaces or FTE will be required\n"); + else + printf("An FTE executor will be required\n"); + } break; case QCF_KK7: if (bodylessfuncs) @@ -845,16 +850,20 @@ pbool QCC_WriteData (int crc) //PrintGlobals (); strofs = (strofs+3)&~3; - printf ("%6i strofs (of %i)\n", strofs, MAX_STRINGS); - printf ("%6i numstatements (of %i)\n", numstatements, MAX_STATEMENTS); - printf ("%6i numfunctions (of %i)\n", numfunctions, MAX_FUNCTIONS); - printf ("%6i numglobaldefs (of %i)\n", numglobaldefs, MAX_GLOBALS); - 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 (verbose) + { + printf ("%6i strofs (of %i)\n", strofs, MAX_STRINGS); + printf ("%6i numstatements (of %i)\n", numstatements, MAX_STATEMENTS); + printf ("%6i numfunctions (of %i)\n", numfunctions, MAX_FUNCTIONS); + printf ("%6i numglobaldefs (of %i)\n", numglobaldefs, MAX_GLOBALS); + 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"); - printf("Writing %s\n", destfile); + if (verbose) + printf("Writing %s\n", destfile); h = SafeOpenWrite (destfile, 2*1024*1024); SafeWrite (h, &progs, sizeof(progs)); SafeWrite (h, "\r\n\r\n", 4); @@ -1187,7 +1196,8 @@ strofs = (strofs+3)&~3; break; } - printf ("%6i TOTAL SIZE\n", (int)SafeSeek (h, 0, SEEK_CUR)); + if (verbose) + printf ("%6i TOTAL SIZE\n", (int)SafeSeek (h, 0, SEEK_CUR)); progs.entityfields = pr.size_fields; @@ -1215,7 +1225,8 @@ strofs = (strofs+3)&~3; unsigned int version = 1; StripExtension(destfile); strcat(destfile, ".lno"); - printf("Writing %s\n", destfile); + if (verbose) + printf("Writing %s for debugging\n", destfile); h = SafeOpenWrite (destfile, 2*1024*1024); SafeWrite (h, &lnotype, sizeof(int)); SafeWrite (h, &version, sizeof(int)); @@ -1608,8 +1619,9 @@ int QCC_PR_FinishCompilation (void) } else { - QCC_PR_Warning(WARN_NOTDEFINED, strings + d->s_file, d->s_line, "function %s was not defined",d->name); + QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name); bodylessfuncs = true; + errors = true; } // errors = true; } @@ -1887,28 +1899,35 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) case 12923: //#pragma sourcefile usage break; case 54730: - printf("Recognised progs as QuakeWorld\n"); + if (verbose) + printf("Recognised progs as QuakeWorld\n"); break; case 5927: - printf("Recognised progs as NetQuake server gamecode\n"); + if (verbose) + printf("Recognised progs as NetQuake server gamecode\n"); break; case 26940: - printf("Recognised progs as Quake pre-release...\n"); + if (verbose) + printf("Recognised progs as Quake pre-release...\n"); break; case 38488: - printf("Recognised progs as original Hexen2\n"); + if (verbose) + printf("Recognised progs as original Hexen2\n"); break; case 26905: - printf("Recognised progs as Hexen2 Mission Pack\n"); + if (verbose) + printf("Recognised progs as Hexen2 Mission Pack\n"); break; case 14046: - printf("Recognised progs as Hexen2 (demo)\n"); + if (verbose) + printf("Recognised progs as Hexen2 (demo)\n"); break; case 22390: //EXT_CSQC_1 - printf("Recognised progs as a CSQC module\n"); + if (verbose) + printf("Recognised progs as an EXT_CSQC_1 module\n"); break; case 17105: case 32199: //outdated ext_csqc @@ -1918,7 +1937,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) printf("Recognised progs as outdated CSQC module\n"); break; case 10020: - printf("Recognised progs as a DP/FTE Menu module\n"); + if (verbose) + printf("Recognised progs as a DP/FTE Menu module\n"); break; case 32401: @@ -2274,14 +2294,17 @@ void QCC_CopyFiles (void) char srcdir[1024], destdir[1024]; int p; - if (numsounds > 0) - printf ("%3i unique precache_sounds\n", numsounds); - if (nummodels > 0) - printf ("%3i unique precache_models\n", nummodels); - if (numtextures > 0) - printf ("%3i unique precache_textures\n", numtextures); - if (numfiles > 0) - printf ("%3i unique precache_files\n", numfiles); + if (verbose) + { + if (numsounds > 0) + printf ("%3i unique precache_sounds\n", numsounds); + if (nummodels > 0) + printf ("%3i unique precache_models\n", nummodels); + if (numtextures > 0) + printf ("%3i unique precache_textures\n", numtextures); + if (numfiles > 0) + printf ("%3i unique precache_files\n", numfiles); + } p = QCC_CheckParm ("-copy"); if (p && p < myargc-2) @@ -3157,7 +3180,9 @@ void QCC_ContinueCompile(void) if (autoprototype) printf ("prototyping %s\n", qccmfilename); else + { printf ("compiling %s\n", qccmfilename); + } QCC_LoadFile (qccmfilename, (void *)&qccmsrc2); if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) ) @@ -3217,58 +3242,61 @@ void QCC_FinishCompile(void) if (donesomething) { - printf ("Compile Complete\n\n"); + if (verbose) + { + printf ("Compile Complete\n\n"); - if (optres_shortenifnots) - printf("optres_shortenifnots %i\n", optres_shortenifnots); - if (optres_overlaptemps) - printf("optres_overlaptemps %i\n", optres_overlaptemps); - if (optres_noduplicatestrings) - printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings); - if (optres_constantarithmatic) - printf("optres_constantarithmatic %i\n", optres_constantarithmatic); - if (optres_nonvec_parms) - printf("optres_nonvec_parms %i\n", optres_nonvec_parms); - if (optres_constant_names) - printf("optres_constant_names %i\n", optres_constant_names); - if (optres_constant_names_strings) - printf("optres_constant_names_strings %i\n", optres_constant_names_strings); - if (optres_precache_file) - printf("optres_precache_file %i\n", optres_precache_file); - if (optres_filenames) - printf("optres_filenames %i\n", optres_filenames); - if (optres_assignments) - printf("optres_assignments %i\n", optres_assignments); - if (optres_unreferenced) - printf("optres_unreferenced %i\n", optres_unreferenced); - if (optres_locals) - printf("optres_locals %i\n", optres_locals); - if (optres_function_names) - printf("optres_function_names %i\n", optres_function_names); - if (optres_dupconstdefs) - printf("optres_dupconstdefs %i\n", optres_dupconstdefs); - if (optres_return_only) - printf("optres_return_only %i\n", optres_return_only); - if (optres_compound_jumps) - printf("optres_compound_jumps %i\n", optres_compound_jumps); - // if (optres_comexprremoval) - // printf("optres_comexprremoval %i\n", optres_comexprremoval); - if (optres_stripfunctions) - printf("optres_stripfunctions %i\n", optres_stripfunctions); - if (optres_locals_marshalling) - printf("optres_locals_marshalling %i\n", optres_locals_marshalling); - if (optres_logicops) - printf("optres_logicops %i\n", optres_logicops); + if (optres_shortenifnots) + printf("optres_shortenifnots %i\n", optres_shortenifnots); + if (optres_overlaptemps) + printf("optres_overlaptemps %i\n", optres_overlaptemps); + if (optres_noduplicatestrings) + printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings); + if (optres_constantarithmatic) + printf("optres_constantarithmatic %i\n", optres_constantarithmatic); + if (optres_nonvec_parms) + printf("optres_nonvec_parms %i\n", optres_nonvec_parms); + if (optres_constant_names) + printf("optres_constant_names %i\n", optres_constant_names); + if (optres_constant_names_strings) + printf("optres_constant_names_strings %i\n", optres_constant_names_strings); + if (optres_precache_file) + printf("optres_precache_file %i\n", optres_precache_file); + if (optres_filenames) + printf("optres_filenames %i\n", optres_filenames); + if (optres_assignments) + printf("optres_assignments %i\n", optres_assignments); + if (optres_unreferenced) + printf("optres_unreferenced %i\n", optres_unreferenced); + if (optres_locals) + printf("optres_locals %i\n", optres_locals); + if (optres_function_names) + printf("optres_function_names %i\n", optres_function_names); + if (optres_dupconstdefs) + printf("optres_dupconstdefs %i\n", optres_dupconstdefs); + if (optres_return_only) + printf("optres_return_only %i\n", optres_return_only); + if (optres_compound_jumps) + printf("optres_compound_jumps %i\n", optres_compound_jumps); + // if (optres_comexprremoval) + // printf("optres_comexprremoval %i\n", optres_comexprremoval); + if (optres_stripfunctions) + printf("optres_stripfunctions %i\n", optres_stripfunctions); + if (optres_locals_marshalling) + printf("optres_locals_marshalling %i\n", optres_locals_marshalling); + if (optres_logicops) + printf("optres_logicops %i\n", optres_logicops); - if (optres_test1) - printf("optres_test1 %i\n", optres_test1); - if (optres_test2) - printf("optres_test2 %i\n", optres_test2); - - printf("numtemps %i\n", numtemps); - - printf("%i warnings\n", pr_warning_count); + if (optres_test1) + 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) + printf("%i warnings\n", pr_warning_count); } qcc_compileactive = false;