From 18f4ed71fc20c416452c18210b0594f6efd3fd02 Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Sun, 18 Mar 2012 22:39:29 +0200 Subject: [PATCH] Update fteqcc source --- misc/source/fteqcc-src/Makefile | 3 +- misc/source/fteqcc-src/comprout.c | 2 +- misc/source/fteqcc-src/dotnet2008/qcc.sln | 26 + misc/source/fteqcc-src/dotnet2008/qcc.vcproj | 814 +++++ misc/source/fteqcc-src/dotnet2010/qcc.sln | 26 + misc/source/fteqcc-src/dotnet2010/qcc.vcxproj | 343 ++ misc/source/fteqcc-src/execloop.h | 195 +- misc/source/fteqcc-src/gui.h | 6 +- misc/source/fteqcc-src/initlib.c | 145 +- misc/source/fteqcc-src/pr_comp.h | 18 +- misc/source/fteqcc-src/pr_edict.c | 151 +- misc/source/fteqcc-src/pr_exec.c | 25 +- misc/source/fteqcc-src/pr_multi.c | 64 +- misc/source/fteqcc-src/pr_x86.c | 150 +- misc/source/fteqcc-src/progsint.h | 21 +- misc/source/fteqcc-src/progslib.h | 12 +- misc/source/fteqcc-src/qcc.h | 78 +- misc/source/fteqcc-src/qcc_cmdlib.c | 16 +- misc/source/fteqcc-src/qcc_pr_comp.c | 3096 ++++++++--------- misc/source/fteqcc-src/qcc_pr_lex.c | 351 +- misc/source/fteqcc-src/qccgui.c | 202 +- misc/source/fteqcc-src/qccmain.c | 152 +- misc/source/fteqcc-src/qcdecomp.c | 26 +- misc/source/fteqcc-src/{ => vc6}/qcc.dsp | 40 +- misc/source/fteqcc-src/vc6/qcc.dsw | 29 + 25 files changed, 3763 insertions(+), 2228 deletions(-) create mode 100644 misc/source/fteqcc-src/dotnet2008/qcc.sln create mode 100644 misc/source/fteqcc-src/dotnet2008/qcc.vcproj create mode 100644 misc/source/fteqcc-src/dotnet2010/qcc.sln create mode 100644 misc/source/fteqcc-src/dotnet2010/qcc.vcxproj rename misc/source/fteqcc-src/{ => vc6}/qcc.dsp (69%) create mode 100644 misc/source/fteqcc-src/vc6/qcc.dsw diff --git a/misc/source/fteqcc-src/Makefile b/misc/source/fteqcc-src/Makefile index 40a721c6..786d22e3 100644 --- a/misc/source/fteqcc-src/Makefile +++ b/misc/source/fteqcc-src/Makefile @@ -6,7 +6,8 @@ WIN32GUI_OBJS=qccgui.o qccguistuff.o TUI_OBJS=qcctui.o LIB_OBJS= -CC=gcc -Wall +CC?=gcc +CFLAGS?=-Wall all: qcc diff --git a/misc/source/fteqcc-src/comprout.c b/misc/source/fteqcc-src/comprout.c index 2a2f9615..a2a7a3bd 100644 --- a/misc/source/fteqcc-src/comprout.c +++ b/misc/source/fteqcc-src/comprout.c @@ -61,7 +61,7 @@ pbool PreCompile(void) qccClearHunk(); strcpy(qcc_gamedir, ""); - qcchunk = malloc(qcchunksize=256*1024*1024); + qcchunk = malloc(qcchunksize=128*1024*1024); while(!qcchunk && qcchunksize > 8*1024*1024) { qcchunksize /= 2; diff --git a/misc/source/fteqcc-src/dotnet2008/qcc.sln b/misc/source/fteqcc-src/dotnet2008/qcc.sln new file mode 100644 index 00000000..a50d9b37 --- /dev/null +++ b/misc/source/fteqcc-src/dotnet2008/qcc.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qcc", "qcc.vcproj", "{B9F10DBD-C3E7-4312-B357-0FEFB360979A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + GUIDebug|Win32 = GUIDebug|Win32 + GUIRelease|Win32 = GUIRelease|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Debug|Win32.ActiveCfg = Debug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Debug|Win32.Build.0 = Debug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIDebug|Win32.ActiveCfg = GUIDebug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIDebug|Win32.Build.0 = GUIDebug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIRelease|Win32.ActiveCfg = GUIRelease|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIRelease|Win32.Build.0 = GUIRelease|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Release|Win32.ActiveCfg = Release|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/misc/source/fteqcc-src/dotnet2008/qcc.vcproj b/misc/source/fteqcc-src/dotnet2008/qcc.vcproj new file mode 100644 index 00000000..040d9ea5 --- /dev/null +++ b/misc/source/fteqcc-src/dotnet2008/qcc.vcproj @@ -0,0 +1,814 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/misc/source/fteqcc-src/dotnet2010/qcc.sln b/misc/source/fteqcc-src/dotnet2010/qcc.sln new file mode 100644 index 00000000..4d85f4a3 --- /dev/null +++ b/misc/source/fteqcc-src/dotnet2010/qcc.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qcc", "qcc.vcxproj", "{B9F10DBD-C3E7-4312-B357-0FEFB360979A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + GUIDebug|Win32 = GUIDebug|Win32 + GUIRelease|Win32 = GUIRelease|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Debug|Win32.ActiveCfg = Debug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Debug|Win32.Build.0 = Debug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIDebug|Win32.ActiveCfg = GUIDebug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIDebug|Win32.Build.0 = GUIDebug|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIRelease|Win32.ActiveCfg = GUIRelease|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.GUIRelease|Win32.Build.0 = GUIRelease|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Release|Win32.ActiveCfg = Release|Win32 + {B9F10DBD-C3E7-4312-B357-0FEFB360979A}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/misc/source/fteqcc-src/dotnet2010/qcc.vcxproj b/misc/source/fteqcc-src/dotnet2010/qcc.vcxproj new file mode 100644 index 00000000..abcd564d --- /dev/null +++ b/misc/source/fteqcc-src/dotnet2010/qcc.vcxproj @@ -0,0 +1,343 @@ + + + + + Debug + Win32 + + + GUIDebug + Win32 + + + GUIRelease + Win32 + + + Release + Win32 + + + + {B9F10DBD-C3E7-4312-B357-0FEFB360979A} + + + + Application + false + MultiByte + + + Application + false + MultiByte + + + Application + false + MultiByte + + + Application + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\qcc___Win32_GUIDebug\ + .\qcc___Win32_GUIDebug\ + true + .\qcc___Win32_GUIRelease0\ + .\qcc___Win32_GUIRelease0\ + false + .\Release\ + .\Release\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + .\Debug/qcc.tlb + + + + + Disabled + %(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + .\Debug/qcc.pch + .\Debug/ + .\Debug/ + .\Debug/ + true + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + ../../libs/zlib.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ../../fteqcc_dbg.exe + true + true + .\Debug/fteqcc_dbg.pdb + Console + false + + + MachineX86 + + + true + .\Debug/qcc.bsc + + + + + .\qcc___Win32_GUIDebug/qcc.tlb + + + + + Disabled + %(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + .\qcc___Win32_GUIDebug/qcc.pch + .\qcc___Win32_GUIDebug/ + .\qcc___Win32_GUIDebug/ + .\qcc___Win32_GUIDebug/ + true + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + ../../libs/zlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies) + ..\..\fteqcc.exe + true + true + .\qcc___Win32_GUIDebug/fteqcc.pdb + Windows + false + + + MachineX86 + + + true + .\qcc___Win32_GUIDebug/qcc.bsc + + + + + .\qcc___Win32_GUIRelease0/qcc.tlb + + + + + MaxSpeed + OnlyExplicitInline + %(PreprocessorDefinitions) + true + MultiThreaded + true + .\qcc___Win32_GUIRelease0/qcc.pch + .\qcc___Win32_GUIRelease0/ + .\qcc___Win32_GUIRelease0/ + .\qcc___Win32_GUIRelease0/ + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + ../../libs/zlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies) + ../../fteqccgui.exe + true + .\qcc___Win32_GUIRelease0/fteqccgui.pdb + Windows + false + + + MachineX86 + + + true + .\qcc___Win32_GUIRelease0/qcc.bsc + + + + + .\Release/qcc.tlb + + + + + MaxSpeed + OnlyExplicitInline + %(PreprocessorDefinitions) + true + MultiThreaded + true + .\Release/qcc.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + ../../libs/zlib.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ../../fteqcc.exe + true + .\Release/fteqcc.pdb + Console + false + + + MachineX86 + + + true + .\Release/qcc.bsc + + + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + true + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + true + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + + + true + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + true + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + + + + + + + + \ No newline at end of file diff --git a/misc/source/fteqcc-src/execloop.h b/misc/source/fteqcc-src/execloop.h index 08d0ce9f..f6aa4eb5 100644 --- a/misc/source/fteqcc-src/execloop.h +++ b/misc/source/fteqcc-src/execloop.h @@ -35,6 +35,12 @@ #error Bad cont size #endif +#ifdef DEBUGABLE +#define OPCODE (st->op & ~0x8000) +#else +#define OPCODE (st->op) +#endif + #define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable) #define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable) #define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable) @@ -49,11 +55,10 @@ cont: //last statement may have been a breakpoint st = pr_statements + s; reeval: - switch (st->op & ~0x8000) #else st++; - switch (st->op) #endif + switch (OPCODE) { case OP_ADD_F: OPC->_float = OPA->_float + OPB->_float; @@ -292,7 +297,7 @@ reeval: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); ptr->_float = (float)OPA->_int; @@ -301,38 +306,45 @@ reeval: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); ptr->_int = (int)OPA->_float; break; case OP_STOREP_I: + case OP_GSTOREP_I: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); ptr->_int = OPA->_int; break; case OP_STOREP_F: + case OP_GSTOREP_F: case OP_STOREP_ENT: + case OP_GSTOREP_ENT: case OP_STOREP_FLD: // integers + case OP_GSTOREP_FLD: case OP_STOREP_S: + case OP_GSTOREP_S: case OP_STOREP_FNC: // pointers + case OP_GSTOREP_FNC: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(progfuncs, pr_xfunction->s_name), OPB->_int, addressableused); } ptr = QCPOINTER(OPB); ptr->_int = OPA->_int; break; case OP_STOREP_V: + case OP_GSTOREP_V: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); ptr->_vector[0] = OPA->_vector[0]; @@ -344,7 +356,7 @@ reeval: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); *(unsigned char *)ptr = (char)OPA->_float; @@ -353,7 +365,7 @@ reeval: case OP_MULSTORE_F: // f *= f OPB->_float *= OPA->_float; break; - case OP_MULSTORE_V: // v *= f + case OP_MULSTORE_VF: // v *= f OPB->_vector[0] *= OPA->_float; OPB->_vector[1] *= OPA->_float; OPB->_vector[2] *= OPA->_float; @@ -362,12 +374,17 @@ reeval: if ((unsigned int)OPB->_int >= addressableused) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); } ptr = QCPOINTER(OPB); OPC->_float = (ptr->_float *= OPA->_float); break; - case OP_MULSTOREP_V: // e.v *= f + case OP_MULSTOREP_VF: // e.v *= f + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float); OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float); @@ -378,6 +395,11 @@ reeval: OPB->_float /= OPA->_float; break; case OP_DIVSTOREP_F: // e.f /= f + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_float = (ptr->_float /= OPA->_float); break; @@ -391,10 +413,20 @@ reeval: OPB->_vector[2] += OPA->_vector[2]; break; case OP_ADDSTOREP_F: // e.f += f + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_float = (ptr->_float += OPA->_float); break; case OP_ADDSTOREP_V: // e.v += v + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]); OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]); @@ -410,10 +442,20 @@ reeval: OPB->_vector[2] -= OPA->_vector[2]; break; case OP_SUBSTOREP_F: // e.f -= f + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_float = (ptr->_float -= OPA->_float); break; case OP_SUBSTOREP_V: // e.v -= v + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]); OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]); @@ -427,7 +469,7 @@ reeval: { #ifndef DEBUGABLE pr_trace++; - printf("OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + printf("OP_ADDRESS references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); st--; goto cont; #else @@ -444,7 +486,7 @@ reeval: #ifndef DEBUGABLE //boot it over to the debugger pr_trace++; - printf("assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + printf("assignment to read-only entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); st--; goto cont; #else @@ -453,7 +495,7 @@ reeval: 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); + printf ("assignment to read-only entity in %s (%s.%s)\n", PR_StringToNative(progfuncs, pr_xfunction->s_name), d16?PR_StringToNative(progfuncs, d16->s_name):NULL, f?f->name:NULL); } #endif } @@ -462,7 +504,7 @@ reeval: // if (ed->isfree) // { // pr_xstatement = st-pr_statements; -// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); +// PR_RunError (progfuncs, "assignment to free entitiy in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); // } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; @@ -475,7 +517,7 @@ reeval: case OP_LOAD_S: case OP_LOAD_FNC: if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); ed = PROG_TO_EDICT(progfuncs, OPA->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range @@ -486,7 +528,7 @@ reeval: case OP_LOAD_V: if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); ed = PROG_TO_EDICT(progfuncs, OPA->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range @@ -567,15 +609,14 @@ reeval: RUNAWAYCHECK(); pr_xstatement = st-pr_statements; - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); + if (OPCODE > OP_CALL8) + pr_argc = OPCODE - (OP_CALL1H-1); else - pr_argc = st->op - OP_CALL0; + pr_argc = OPCODE - OP_CALL0; fnum = OPA->function; if ((fnum & ~0xff000000)==0) { - PR_RunError(progfuncs, "NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name); + PR_RunError(progfuncs, "NULL function from qc (%s).\n", PR_StringToNative(progfuncs, pr_xfunction->s_name)); #ifndef DEBUGABLE goto cont; #endif @@ -588,24 +629,24 @@ reeval: progfuncs->save_ents(progfuncs, buffer, &size, 0); }*/ - - p=pr_typecurrent; + { + int callerprogs=pr_typecurrent; //about to switch. needs caching. //if it's an external call, switch now (before any function pointers are used) - PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p); + PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, callerprogs); PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24); newf = &pr_functions[fnum & ~0xff000000]; if (newf->first_statement < 0) { // negative statements are built in functions - -if (pr_typecurrent != 0) -{ - PR_MoveParms(progfuncs, 0, pr_typecurrent); - PR_SwitchProgs(progfuncs, 0); -} + /*calling a builtin in another progs may affect that other progs' globals instead, is the theory anyway, so args and stuff need to move over*/ + if (pr_typecurrent != 0) + { + PR_MoveParms(progfuncs, 0, pr_typecurrent); + PR_SwitchProgs(progfuncs, 0); + } i = -newf->first_statement; // p = pr_typecurrent; progfuncs->lastcalledbuiltinnumber = i; @@ -633,9 +674,9 @@ if (pr_typecurrent != 0) else current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals); } - PR_MoveParms(progfuncs, p, pr_typecurrent); + PR_MoveParms(progfuncs, callerprogs, pr_typecurrent); // memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t)); - PR_SwitchProgs(progfuncs, (progsnum_t)p); + PR_SwitchProgs(progfuncs, (progsnum_t)callerprogs); //#ifndef DEBUGABLE //decide weather non debugger wants to start debugging. s = st-pr_statements; @@ -645,8 +686,9 @@ if (pr_typecurrent != 0) } // PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent); // PR_SwitchProgs((OPA->function & 0xff000000)>>24); - s = PR_EnterFunction (progfuncs, newf, p); + s = PR_EnterFunction (progfuncs, newf, callerprogs); st = &pr_statements[s]; + } goto restart; // break; @@ -743,7 +785,7 @@ if (pr_typecurrent != 0) //array/structure reading/writing. case OP_GLOBALADDRESS: - OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); + OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); /*pointer arithmatic*/ break; case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) OPC->_int = OPA->_int + OPB->_int*4; @@ -755,7 +797,7 @@ if (pr_typecurrent != 0) case OP_LOADA_ENT: case OP_LOADA_S: case OP_LOADA_FNC: - ptr = (eval_t *)(&OPA->_int + OPB->_int); + ptr = (eval_t *)(&OPA->_int + OPB->_int); /*pointer arithmatic*/ OPC->_int = ptr->_int; break; @@ -775,7 +817,20 @@ if (pr_typecurrent != 0) OPC->_int = OPA->_int - OPB->_int; break; case OP_LOADP_C: //load character from a string - ptr = QCPOINTERM(OPA->_int + (int)OPB->_float); + i = (unsigned int)OPA->_int + (unsigned int)OPB->_float; + if ((unsigned int)i >= addressableused) + { + i = (unsigned int)OPB->_float; + ptr = (eval_t*)PR_StringToNative(progfuncs, OPA->_int); + if ((size_t)i > strlen((char*)ptr)) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), i, ptr); + } + ptr = (eval_t*)((char*)ptr + i); + } + else + ptr = QCPOINTERM(i); OPC->_float = *(unsigned char *)ptr; break; case OP_LOADP_I: @@ -784,12 +839,24 @@ if (pr_typecurrent != 0) case OP_LOADP_ENT: case OP_LOADP_S: case OP_LOADP_FNC: - ptr = QCPOINTERM(OPA->_int + OPB->_int); + i = OPA->_int + OPB->_int*4; + if ((unsigned int)i >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } + ptr = QCPOINTERM(OPA->_int + OPB->_int*4); OPC->_int = ptr->_int; break; case OP_LOADP_V: - ptr = QCPOINTERM(OPA->_int + OPB->_int); + i = OPA->_int + OPB->_int*4; + if ((unsigned int)i >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } + ptr = QCPOINTERM(i); OPC->_vector[0] = ptr->_vector[0]; OPC->_vector[1] = ptr->_vector[1]; OPC->_vector[2] = ptr->_vector[2]; @@ -813,7 +880,7 @@ if (pr_typecurrent != 0) i = (int)OPB->_float; if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); + PR_RunError(progfuncs, "array index out of bounds: %s[%d] (max %d)", PR_GlobalStringNoContents(progfuncs, st->a), i, ((eval_t *)&glob[st->a-1])->_int); } t = (eval_t *)&pr_globals[(uofs)st->a + i]; OPC->_int = t->_int; @@ -847,6 +914,11 @@ if (pr_typecurrent != 0) OPB->_float = (float)((int)OPB->_float | (int)OPA->_float); break; case OP_BITSETP: // .b (+) a + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); ptr->_float = (float)((int)ptr->_float | (int)OPA->_float); break; @@ -854,49 +926,54 @@ if (pr_typecurrent != 0) OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float)); break; case OP_BITCLRP: // .b (-) a + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name)); + } ptr = QCPOINTER(OPB); ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float)); break; case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); + OPC->_float = (rand()&0x7fff)/((float)0x7fff); break; case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; + OPC->_float = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; break; case OP_RAND2: if(OPA->_float < OPB->_float) { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) + OPC->_float = OPA->_float+((rand()&0x7fff)/((float)0x7fff) *(OPB->_float-OPA->_float)); } else { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) + OPC->_float = OPB->_float+((rand()&0x7fff)/((float)0x7fff) *(OPA->_float-OPB->_float)); } break; case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff); break; case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; + OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; + OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; + OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; break; case OP_RANDV2: for(i = 0; i < 3; i++) { if(OPA->_vector[i] < OPB->_vector[i]) { - G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) + OPC->_vector[i] = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) *(OPB->_vector[i]-OPA->_vector[i])); } else { - G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) + OPC->_vector[i] = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) *(OPA->_vector[i]-OPB->_vector[i])); } } @@ -909,7 +986,7 @@ if (pr_typecurrent != 0) case OP_SWITCH_E: case OP_SWITCH_FNC: swtch = OPA; - swtchtype = st->op; + swtchtype = OPCODE; RUNAWAYCHECK(); st += (sofs)st->b - 1; // offset the st++ break; @@ -1050,13 +1127,6 @@ if (pr_typecurrent != 0) OPC->_int = (OPA->_float != OPB->_int); break; - case OP_GSTOREP_I: - case OP_GSTOREP_F: - case OP_GSTOREP_ENT: - case OP_GSTOREP_FLD: // integers - case OP_GSTOREP_S: - case OP_GSTOREP_FNC: // pointers - case OP_GSTOREP_V: case OP_GADDRESS: case OP_GLOAD_I: case OP_GLOAD_F: @@ -1072,7 +1142,7 @@ if (pr_typecurrent != 0) if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b) { pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int); + PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i. Must be between %u and %u", OPA->_int, st->c, st->b); } break; /* case OP_PUSH: @@ -1100,7 +1170,7 @@ if (pr_typecurrent != 0) { pr_xstatement = s = st-pr_statements; - printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable); + printf("Break point hit in %s.\n", PR_StringToNative(progfuncs, pr_xfunction->s_name)); if (pr_trace<1) pr_trace=1; //this is what it's for @@ -1124,6 +1194,7 @@ if (pr_typecurrent != 0) #undef dstatement_t #undef sofs #undef uofs +#undef OPCODE #undef ENGINEPOINTER #undef QCPOINTER diff --git a/misc/source/fteqcc-src/gui.h b/misc/source/fteqcc-src/gui.h index 66ad9c56..341aedb4 100644 --- a/misc/source/fteqcc-src/gui.h +++ b/misc/source/fteqcc-src/gui.h @@ -4,9 +4,9 @@ void EditFile(char *name, int line); void GUI_SetDefaultOpts(void); int GUI_BuildParms(char *args, char **argv); -unsigned char *QCC_ReadFile (char *fname, void *buffer, int len); -int QCC_FileSize (char *fname); -pbool QCC_WriteFile (char *name, void *data, int len); +unsigned char *QCC_ReadFile (const char *fname, void *buffer, int len); +int QCC_FileSize (const char *fname); +pbool QCC_WriteFile (const char *name, void *data, int len); void GUI_DialogPrint(char *title, char *text); extern char parameters[16384]; diff --git a/misc/source/fteqcc-src/initlib.c b/misc/source/fteqcc-src/initlib.c index 8ee0f99a..e630395a 100644 --- a/misc/source/fteqcc-src/initlib.c +++ b/misc/source/fteqcc-src/initlib.c @@ -41,6 +41,38 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark) return; } +/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/ +void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen) +{ + unsigned int i; + edictrun_t *e; + for (i=0 ; iedicttable[i]); + if (e && (char*)e->fields >= oldb && (char*)e->fields < oldb+oldlen) + e->fields = ((char*)e->fields - oldb) + newb; + } + + if (progfuncs->stringtable >= oldb && progfuncs->stringtable < oldb+oldlen) + progfuncs->stringtable = (progfuncs->stringtable - oldb) + newb; + + for (i=0; i < maxprogs; i++) + { + if ((char*)prinst->progstate[i].globals >= oldb && (char*)prinst->progstate[i].globals < oldb+oldlen) + prinst->progstate[i].globals = (float*)(((char*)prinst->progstate[i].globals - oldb) + newb); + if (prinst->progstate[i].strings >= oldb && prinst->progstate[i].strings < oldb+oldlen) + prinst->progstate[i].strings = (prinst->progstate[i].strings - oldb) + newb; + } + + for (i = 0; i < numfields; i++) + { + if (field[i].name >= oldb && field[i].name < oldb+oldlen) + field[i].name = (field[i].name - oldb) + newb; + } + + externs->addressablerelocated(progfuncs, oldb, newb, oldlen); +} + //for 64bit systems. :) //addressable memory is memory available to the vm itself for writing. //once allocated, it cannot be freed for the lifetime of the VM. @@ -48,7 +80,46 @@ void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount) { ammount = (ammount + 4)&~3; //round up to 4 if (addressableused + ammount > addressablesize) - Sys_Error("Not enough addressable memory for progs VM"); + { + /*only do this if the caller states that it can cope with addressable-block relocations/resizes*/ + if (externs->addressablerelocated) + { +#ifdef _WIN32 + char *newblock; + #if 0//def _DEBUG + int oldtot = addressablesize; + #endif + int newsize = (addressableused + ammount + 4096) & ~(4096-1); + newblock = VirtualAlloc (NULL, addressablesize, MEM_RESERVE, PAGE_NOACCESS); + if (newblock) + { + VirtualAlloc (newblock, addressableused, MEM_COMMIT, PAGE_READWRITE); + memcpy(newblock, addressablehunk, addressableused); + #if 0//def _DEBUG + VirtualAlloc (addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS); + #else + VirtualFree (addressablehunk, 0, MEM_RELEASE); + #endif + PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused); + addressablehunk = newblock; + addressablesize = newsize; + } +#else + char *newblock; + int newsize = (addressableused + ammount + 1024*1024) & ~(1024*1024-1); + newblock = realloc(newblock, addressablesize); + if (newblock) + { + PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused); + addressablehunk = newblock; + addressablesize = newsize; + } +#endif + } + + if (addressableused + ammount > addressablesize) + Sys_Error("Not enough addressable memory for progs VM"); + } addressableused += ammount; @@ -69,12 +140,17 @@ void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount) // return; } - if (addressablehunk) #ifdef _WIN32 - VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p - addressablehunk = VirtualAlloc (NULL, totalammount, MEM_RESERVE, PAGE_NOACCESS); + if (addressablehunk && addressablesize != totalammount) + { + VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p + addressablehunk = NULL; + } + if (!addressablehunk) + addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS); #else - free(addressablehunk); + if (addressablehunk) + free(addressablehunk); addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy. // memset(addressablehunk, 0xff, totalammount); #endif @@ -160,7 +236,10 @@ struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum) if (pnum < 0) { if (!current_progstate) - return NULL; //err.. you've not loaded one yet. + { + static float fallback[RESERVED_OFS]; + return (struct globalvars_s *)fallback; //err.. you've not loaded one yet. + } return (struct globalvars_s *)current_progstate->globals; } return (struct globalvars_s *)pr_progstate[pnum].globals; @@ -426,8 +505,8 @@ string_t PR_StringToProgs (progfuncs_t *progfuncs, char *str) if (!str) return 0; -// if (str-progfuncs->stringtable < progfuncs->stringtablesize) -// return str - progfuncs->stringtable; + if (str >= progfuncs->stringtable && str < progfuncs->stringtable + addressableused) + return str - progfuncs->stringtable; for (i = prinst->numallocedstrings-1; i >= 0; i--) { @@ -507,6 +586,8 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) int i = str & ~0x80000000; if (i >= prinst->numallocedstrings) { + printf("invalid string %x\n", str); + PR_StackTrace(progfuncs); pr_trace = 1; return ""; } @@ -514,6 +595,8 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) return prinst->allocedstrings[i]; else { + printf("invalid string %x\n", str); + PR_StackTrace(progfuncs); pr_trace = 1; return ""; //urm, was freed... } @@ -523,6 +606,8 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) int i = str & ~0x40000000; if (i >= prinst->numtempstrings) { + printf("invalid temp string %x\n", str); + PR_StackTrace(progfuncs); pr_trace = 1; return ""; } @@ -530,8 +615,10 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) } } - if (str >= progfuncs->stringtablesize) + if (str >= addressableused) { + printf("invalid string offset %x\n", str); + PR_StackTrace(progfuncs); pr_trace = 1; return ""; } @@ -571,6 +658,38 @@ string_t PR_AllocTempString (progfuncs_t *progfuncs, char *str) return (string_t)((unsigned int)i | 0x40000000); } +string_t PR_AllocTempStringLen (progfuncs_t *progfuncs, char **str, unsigned int len) +{ + char **ntable; + int newmax; + int i; + + if (!str) + return 0; + + if (prinst->numtempstrings == prinst->maxtempstrings) + { + newmax = prinst->maxtempstrings += 1024; + prinst->maxtempstrings += 1024; + ntable = memalloc(sizeof(char*) * newmax); + memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings); + prinst->maxtempstrings = newmax; + if (prinst->tempstrings) + memfree(prinst->tempstrings); + prinst->tempstrings = ntable; + } + + i = prinst->numtempstrings; + if (i == 0x10000000) + return 0; + + prinst->numtempstrings++; + + prinst->tempstrings[i] = memalloc(len); + *str = prinst->tempstrings[i]; + + return (string_t)((unsigned int)i | 0x40000000); +} void PR_FreeTemps (progfuncs_t *progfuncs, int depth) { @@ -683,7 +802,9 @@ progfuncs_t deffuncs = { 0, PR_QueryField, QC_ClearEdict, - QC_FindPrefixedGlobals + QC_FindPrefixedGlobals, + PRAddressableAlloc, + PR_AllocTempStringLen }; #undef printf @@ -774,8 +895,8 @@ void CloseProgs(progfuncs_t *inst) #endif if (inst->prinst->allocedstrings) - f(inst->prinst->allocedstrings); - inst->prinst->allocedstrings = NULL; + f(inst->prinst->allocedstrings); + inst->prinst->allocedstrings = NULL; if (inst->prinst->tempstrings) f(inst->prinst->tempstrings); inst->prinst->tempstrings = NULL; diff --git a/misc/source/fteqcc-src/pr_comp.h b/misc/source/fteqcc-src/pr_comp.h index d6c34a96..35590863 100644 --- a/misc/source/fteqcc-src/pr_comp.h +++ b/misc/source/fteqcc-src/pr_comp.h @@ -112,9 +112,9 @@ enum qcop_e { //these following ones are Hexen 2 constants. OP_MULSTORE_F, - OP_MULSTORE_V, + OP_MULSTORE_VF, OP_MULSTOREP_F, - OP_MULSTOREP_V, + OP_MULSTOREP_VF, OP_DIVSTORE_F, //70 OP_DIVSTOREP_F, @@ -260,8 +260,8 @@ enum qcop_e { //------------------------------------- //string manipulation. - OP_ADD_SF, //(char*)c = (char*)a + (float)b - OP_SUB_S, //(float)c = (char*)a - (char*)b + OP_ADD_SF, //(char*)c = (char*)a + (float)b add_fi->i + OP_SUB_S, //(float)c = (char*)a - (char*)b sub_ii->f OP_STOREP_C,//(float)c = *(char*)b = (float)a OP_LOADP_C, //(float)c = *(char*) //------------------------------------- @@ -304,7 +304,7 @@ enum qcop_e { OP_BOUNDCHECK, //back to ones that we do use. - OP_STOREP_P, + OP_UNUSED, //used to be OP_STOREP_P, which is now emulated with OP_STOREP_I, fteqcc nor fte generated it OP_PUSH, //push 4octets onto the local-stack (which is ALWAYS poped on function return). Returns a pointer. OP_POP, //pop those ones that were pushed (don't over do it). Needs assembler. @@ -350,7 +350,13 @@ enum qcop_e { OP_SUBSTORE_FI, OP_SUBSTOREP_FI, - OP_NUMOPS //246 + OP_MULSTORE_VI, + OP_MULSTOREP_VI, + + OP_LOADA_STRUCT, + OP_STOREP_P, + + OP_NUMOPS }; #define MAX_PARMS 8 diff --git a/misc/source/fteqcc-src/pr_edict.c b/misc/source/fteqcc-src/pr_edict.c index a67b3685..468aea45 100644 --- a/misc/source/fteqcc-src/pr_edict.c +++ b/misc/source/fteqcc-src/pr_edict.c @@ -5,11 +5,6 @@ struct edict_s; #include "progsint.h" //#include "crc.h" -/*int maxedicts; - -evalc_t spawnflagscache; -*/ - #ifdef _WIN32 //this is windows all files are written with this endian standard. we do this to try to get a little more speed. #define NOENDIAN @@ -18,30 +13,8 @@ evalc_t spawnflagscache; vec3_t vec3_origin; -//edictrun_t *sv_edicts; -//int sv_num_edicts; - -//int pr_edict_size; // in bytes -//int pr_max_edict_size; - -//unsigned short pr_crc; - fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); -pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits); - - - -/* -#define MAX_FIELD_LEN 64 -#define GEFV_CACHESIZE 5 - -typedef struct { - ddef_t *pcache; - char field[MAX_FIELD_LEN]; -} gefv_cache; - -static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; -*/ +pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int fldtype, char *s); /* ================= @@ -487,7 +460,7 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) type &= ~DEF_SAVEGLOBAL; #endif - if (pr_types) + if (current_progstate && pr_types) type = pr_types[type].type; switch (type) @@ -600,8 +573,8 @@ char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) type &= ~DEF_SAVEGLOBAL; #endif - if (pr_types) - type = pr_types[type].type; +// if (pr_types) +// type = pr_types[type].type; switch (type) { @@ -1052,54 +1025,30 @@ Can parse either fields or globals returns false if error ============= */ -pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int structtype) +pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int fldtype, char *s) { int i; char string[128]; fdef_t *def; char *v, *w; - void *d; string_t st; dfunction_t *func; - - int type = 0; // warning about beign used without initializing it - - switch(structtype) - { - case PST_DEFAULT: - d = (void *)((int *)base + ((ddef16_t*)key)->ofs); - - if (pr_types) - type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type; - else - type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL; - break; - case PST_FTE32: - d = (void *)((int *)base + ((ddef32_t*)key)->ofs); - - if (pr_types) - type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type; - else - type = ((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL; - break; - default: - Sys_Error("Bad struct type in ED_ParseEpair"); - d = 0; - } + int type = fldtype & ~DEF_SAVEGLOBAL; + qcptr += fldofs*sizeof(int); switch (type) { case ev_string: st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0)); - *(string_t *)d = st; + *(string_t *)(progfuncs->stringtable + qcptr) = st; break; case ev_float: - *(float *)d = (float)atof (s); + *(float *)(progfuncs->stringtable + qcptr) = (float)atof (s); break; case ev_integer: - *(int *)d = atoi (s); + *(int *)(progfuncs->stringtable + qcptr) = atoi (s); break; case ev_vector: @@ -1112,20 +1061,20 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, v++; if (!*v) { - ((float *)d)[i] = (float)atof (w); + ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w); w = v; } else { *v = 0; - ((float *)d)[i] = (float)atof (w); + ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w); w = v = v+1; } } break; case ev_entity: - *(int *)d = atoi (s); + *(int *)(progfuncs->stringtable + qcptr) = atoi (s); break; case ev_field: @@ -1135,13 +1084,13 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, printf ("Can't find field %s\n", s); return false; } - *(int *)d = def->ofs; + *(int *)(progfuncs->stringtable + qcptr) = def->ofs; break; case ev_function: if (s[1]==':'&&s[2]=='\0') { - *(func_t *)d = 0; + *(func_t *)(progfuncs->stringtable + qcptr) = 0; return true; } func = ED_FindFunction (progfuncs, s, &i, -1); @@ -1150,7 +1099,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, printf ("Can't find function %s\n", s); return false; } - *(func_t *)d = (func - pr_progstate[i].functions) | (i<<24); + *(func_t *)(progfuncs->stringtable + qcptr) = (func - pr_progstate[i].functions) | (i<<24); break; default: @@ -1259,7 +1208,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) } cont: - if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, PST_FTE32)) + if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->stringtable, key->ofs, key->type, qcc_token)) { continue; // Sys_Error ("ED_ParseEdict: parse error on entities"); @@ -1690,6 +1639,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) eval_t *fulldata; //this is part of FTE_FULLSPAWNDATA char *datastart; + eval_t *selfvar = NULL; eval_t *var; char filename[128]; @@ -1699,6 +1649,8 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) ddef16_t *d16; ddef32_t *d32; func_t CheckSpawn=0; + void *oldglobals = NULL; + int oldglobalssize = 0; extern edictrun_t tempedict; @@ -1719,14 +1671,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) { isloadgame = false; - if (pr_typecurrent>=0) - num = ED_FindGlobalOfs(progfuncs, "__fullspawndata"); - else - num = 0; - if (num) - fulldata = (eval_t *)((int *)pr_globals + num); - else - fulldata = NULL; + fulldata = PR_FindGlobal(progfuncs, "__fullspawndata", PR_ANY, NULL); } while(1) @@ -1854,6 +1799,14 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) current_progstate->builtins = externs->builtinsfor(num, header_crc); current_progstate->numbuiltins = numbuiltins; } + + if (num == 0 && oldglobals) + { + if (pr_progstate[0].globals_size == oldglobalssize) + memcpy(pr_progstate[0].globals, oldglobals, pr_progstate[0].globals_size); + free(oldglobals); + oldglobals = NULL; + } } else if (!strcmp(qcc_token, "globals")) { @@ -1905,7 +1858,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d16->ofs, d16->type, qcc_token); } break; case PST_QTEST: @@ -1918,7 +1871,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d32->ofs, d32->type, qcc_token); } break; default: @@ -1963,6 +1916,21 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) Sys_Error("Bad key \"%s\" in general block", qcc_token); } + if (oldglobals) + free(oldglobals); + oldglobals = NULL; + if (pr_progstate[0].globals_size) + { + oldglobals = malloc(pr_progstate[0].globals_size); + if (oldglobals) + { + oldglobalssize = pr_progstate[0].globals_size; + memcpy(oldglobals, pr_progstate[0].globals, oldglobalssize); + } + else + printf("Unable to alloc %i bytes\n", pr_progstate[0].globals_size); + } + PRAddressableFlush(progfuncs, -1); resethunk=true; @@ -2004,7 +1972,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d16->ofs, d16->type, qcc_token); } break; case PST_QTEST: @@ -2017,7 +1985,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d32->ofs, d32->type, qcc_token); } break; default: @@ -2097,8 +2065,6 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) } else { - eval_t *selfvar; - //added by request of Mercury. if (fulldata) //this is a vital part of HL map support!!! { //essentually, it passes the ent's spawn info to the ent. @@ -2113,8 +2079,10 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) fulldata->string = PR_StringToProgs(progfuncs, spawndata); } - selfvar = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self")); - selfvar->edict = EDICT_TO_PROG(progfuncs, ed); + if (!selfvar) + selfvar = PR_FindGlobal(progfuncs, "self", PR_ANY, NULL); + if (selfvar) + selfvar->edict = EDICT_TO_PROG(progfuncs, ed); //DP_SV_SPAWNFUNC_PREFIX support eclassname = PR_StringToNative(progfuncs, var->string); @@ -2164,6 +2132,10 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) sv_num_edicts = numents; } + if (oldglobals) + free(oldglobals); + oldglobals = NULL; + if (resethunk) { return entsize; @@ -2505,6 +2477,7 @@ retry: current_progstate->statements = (void *)((qbyte *)pr_progs + pr_progs->ofs_statements); glob = pr_globals = (void *)((qbyte *)pr_progs + pr_progs->ofs_globals); + current_progstate->globals_size = pr_progs->numglobals*sizeof(*pr_globals); pr_linenums=NULL; pr_types=NULL; @@ -2929,6 +2902,9 @@ retry: { if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8) st16[i].op += OP_CALL1H - OP_CALL1; + if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) + if (!st16[i].c) + st16[i].c = OFS_RETURN; } } break; @@ -2958,6 +2934,9 @@ retry: { if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8) pr_statements32[i].op += OP_CALL1H - OP_CALL1; + if (pr_statements32[i].op >= OP_RAND0 && pr_statements32[i].op <= OP_RANDV2) + if (!pr_statements32[i].c) + pr_statements32[i].c = OFS_RETURN; } } break; @@ -3117,7 +3096,7 @@ retry: d16 = ED_FindGlobal16(progfuncs, s); if (!d16) { - printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped", filename, s); + printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped\n", filename, s); PRHunkFree(progfuncs, hmark); pr_progs=NULL; return false; @@ -3125,7 +3104,7 @@ retry: ((int *)glob)[d16->ofs] = PR_FindFunc(progfuncs, s, PR_ANY); if (!((int *)glob)[d16->ofs]) - printf("Warning: Runtime-linked function %s was not found in primary progs (loading %s)", s, filename); + printf("Warning: Runtime-linked function %s could not be found (loading %s)\n", s, filename); /* d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function); if (!d2) diff --git a/misc/source/fteqcc-src/pr_exec.c b/misc/source/fteqcc-src/pr_exec.c index 97956039..323c5660 100644 --- a/misc/source/fteqcc-src/pr_exec.c +++ b/misc/source/fteqcc-src/pr_exec.c @@ -346,6 +346,9 @@ ddef32_t *ED_FindLocalOrGlobal(progfuncs_t *progfuncs, char *name, eval_t **val) ddef16_t *def16; int i; + if (pr_typecurrent < 0) + return NULL; + switch (pr_progstate[pr_typecurrent].structtype) { case PST_DEFAULT: @@ -436,6 +439,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) int type; ddef32_t fakedef; eval_t fakeval; + edictrun_t *ed; assignment = strchr(key, '='); if (assignment) @@ -469,7 +473,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) c2 = c+1; c = strchr(c2, '.'); type = type &~DEF_SAVEGLOBAL; - if (current_progstate->types) + if (current_progstate && current_progstate->types) type = current_progstate->types[type].type; if (type != ev_entity) return "'.' without entity"; @@ -478,13 +482,18 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) if (c)*c = '.'; if (!fdef) return "(Bad string)"; - val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4); + ed = PROG_TO_EDICT(progfuncs, val->_int); + if (!ed) + return "(Invalid Entity)"; + val = (eval_t *) (((char *)ed->fields) + fdef->ofs*4); type = fdef->type; } if (assignment) { assignment++; + while(*assignment == ' ') + assignment++; switch (type&~DEF_SAVEGLOBAL) { case ev_string: @@ -492,7 +501,10 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) break; case ev_float: - *(float *)val = (float)atof (assignment); + if (assignment[0] == '0' && (assignment[1] == 'x' || assignment[1] == 'X')) + *(float*)val = strtoul(assignment, NULL, 0); + else + *(float *)val = (float)atof (assignment); break; case ev_integer: @@ -849,7 +861,6 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s) dfunction_t *newf; int runaway; int i; - int p; edictrun_t *ed; eval_t *ptr; @@ -859,9 +870,9 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s) prinst->continuestatement = -1; #ifdef QCJIT - if (prinst->jit) + if (current_progstate->jit) { - PR_EnterJIT(progfuncs, prinst->jit, s); + PR_EnterJIT(progfuncs, current_progstate->jit, s); return; } #endif @@ -875,7 +886,7 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s) { \ pr_xstatement = st-pr_statements; \ PR_StackTrace(progfuncs); \ - printf ("runaway loop error"); \ + printf ("runaway loop error\n"); \ while(pr_depth > prinst->exitdepth) \ PR_LeaveFunction(progfuncs); \ pr_spushed = 0; \ diff --git a/misc/source/fteqcc-src/pr_multi.c b/misc/source/fteqcc-src/pr_multi.c index b66b8b5e..334536ec 100644 --- a/misc/source/fteqcc-src/pr_multi.c +++ b/misc/source/fteqcc-src/pr_multi.c @@ -19,8 +19,16 @@ int maxshares; pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type) { if ((unsigned)type >= maxprogs) + { + if (type == -1) + { + pr_typecurrent = -1; + current_progstate = NULL; + return true; + } PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", type); // Sys_Error("Bad prog type - %i", type); + } if (pr_progstate[(unsigned)type].progs == NULL) //we havn't loaded it yet, for some reason return false; @@ -32,38 +40,38 @@ pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type) return true; } -void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t progs1, progsnum_t progs2) //from 2 to 1 +void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t newpr, progsnum_t oldpr) //from 2 to 1 { unsigned int a; - progstate_t *p1; - progstate_t *p2; + progstate_t *np; + progstate_t *op; - if (progs1 == progs2) + if (newpr == oldpr) return; //don't bother coping variables to themselves... - p1 = &pr_progstate[(int)progs1]; - p2 = &pr_progstate[(int)progs2]; + np = &pr_progstate[(int)newpr]; + op = &pr_progstate[(int)oldpr]; - if ((unsigned)progs1 >= maxprogs || !p1->globals) - Sys_Error("QCLIB: Bad prog type - %i", progs1); - if ((unsigned)progs2 >= maxprogs || !p2->globals) - Sys_Error("QCLIB: Bad prog type - %i", progs2); + if ((unsigned)newpr >= maxprogs || !np->globals) + PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", newpr); + if ((unsigned)oldpr >= maxprogs || !op->globals) + return; //copy parms. for (a = 0; a < MAX_PARMS;a++) { - *(int *)&p1->globals[OFS_PARM0+3*a ] = *(int *)&p2->globals[OFS_PARM0+3*a ]; - *(int *)&p1->globals[OFS_PARM0+3*a+1] = *(int *)&p2->globals[OFS_PARM0+3*a+1]; - *(int *)&p1->globals[OFS_PARM0+3*a+2] = *(int *)&p2->globals[OFS_PARM0+3*a+2]; + *(int *)&np->globals[OFS_PARM0+3*a ] = *(int *)&op->globals[OFS_PARM0+3*a ]; + *(int *)&np->globals[OFS_PARM0+3*a+1] = *(int *)&op->globals[OFS_PARM0+3*a+1]; + *(int *)&np->globals[OFS_PARM0+3*a+2] = *(int *)&op->globals[OFS_PARM0+3*a+2]; } - p1->globals[OFS_RETURN] = p2->globals[OFS_RETURN]; - p1->globals[OFS_RETURN+1] = p2->globals[OFS_RETURN+1]; - p1->globals[OFS_RETURN+2] = p2->globals[OFS_RETURN+2]; + np->globals[OFS_RETURN] = op->globals[OFS_RETURN]; + np->globals[OFS_RETURN+1] = op->globals[OFS_RETURN+1]; + np->globals[OFS_RETURN+2] = op->globals[OFS_RETURN+2]; //move the vars defined as shared. for (a = 0; a < numshares; a++)//fixme: make offset per progs { - memmove(&((int *)p1->globals)[shares[a].varofs], &((int *)p2->globals)[shares[a].varofs], shares[a].size*4); + memmove(&((int *)np->globals)[shares[a].varofs], &((int *)op->globals)[shares[a].varofs], shares[a].size*4); /* ((int *)p1->globals)[shares[a].varofs] = ((int *)p2->globals)[shares[a].varofs]; if (shares[a].size > 1) { @@ -94,14 +102,13 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_ progfuncs->numprogs = a+1; #ifdef QCJIT - prinst->jit = PR_GenerateJit(progfuncs); + current_progstate->jit = PR_GenerateJit(progfuncs); #endif - if (oldtype>=0) + if (oldtype != -1) PR_SwitchProgs(progfuncs, oldtype); return a; //we could load it. Yay! } - if (oldtype!=-1) - PR_SwitchProgs(progfuncs, oldtype); + PR_SwitchProgs(progfuncs, oldtype); return -1; // loading failed. } } @@ -122,6 +129,10 @@ void PR_Clear(progfuncs_t *progfuncs) unsigned int a; for (a = 0; a < maxprogs; a++) { +#ifdef QCJIT + if (pr_progstate[a].jit) + PR_CloseJit(pr_progstate[a].jit); +#endif pr_progstate[a].progs = NULL; } } @@ -232,8 +243,15 @@ int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, s { if (field[i].type != type) { - printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type); - continue; + /*Hexen2/DP compat hack: if the new type is a float and the original type is a vector, make the new def alias to the engine's _x field + this 'works around' the unused .vector color field used for rtlight colours vs the .float color used for particle colours (the float initialisers in map files will expand into the x slot safely). + qc/hc can work around this by just using .vector color/color_x instead, which is the same as this hack, but would resolve defs to allow rtlight colours. + */ + if (field[i].type != ev_vector || type != ev_float) + { + printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type); + continue; + } } if (!progfuncs->fieldadjust && engineofs>=0) if ((unsigned)engineofs/4 != field[i].ofs) diff --git a/misc/source/fteqcc-src/pr_x86.c b/misc/source/fteqcc-src/pr_x86.c index 9f217b33..9f1f1acc 100644 --- a/misc/source/fteqcc-src/pr_x86.c +++ b/misc/source/fteqcc-src/pr_x86.c @@ -42,6 +42,10 @@ optimisations: #ifdef QCJIT +#ifndef _WIN32 +#include +#endif + static float ta, tb, nullfloat=0; struct jitstate @@ -52,6 +56,10 @@ struct jitstate unsigned char *code; unsigned int codesize; unsigned int jitstatements; + + float *glob; + unsigned int cachedglobal; + unsigned int cachereg; }; static void EmitByte(struct jitstate *jit, unsigned char byte) @@ -108,7 +116,11 @@ enum REG_ESP, REG_EBP, REG_ESI, - REG_EDI + REG_EDI, + + /*I'm not going to list S1 here, as that makes things too awkward*/ + REG_S0, + REG_NONE }; #define XOR(sr,dr) EmitByte(0x31);EmitByte(0xc0 | (sr<<3) | dr); #define CLEARREG(reg) XOR(reg,reg) @@ -118,6 +130,117 @@ enum #define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i); #define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val); +#define ARGREGS(a,b,c) GCache_Load(jit, op[i].a, a, op[i].b, b, op[i].c, c) +#define RESULTREG(r) GCache_Store(jit, op[i].c, r) + +//for the purposes of the cache, 'temp' offsets are only read when they have been written only within the preceeding control block. +//if they were read at any other time, then we must write them out in full. +//this logic applies only to locals of a function. +//#define USECACHE + +static void GCache_Load(struct jitstate *jit, int ao, int ar, int bo, int br, int co, int cr) +{ +#if USECACHE + if (jit->cachedreg != REG_NONE) + { + /*something is cached, if its one of the input offsets then can chain the instruction*/ + + if (jit->cachedglobal === ao && ar != REG_NONE) + { + if (jit->cachedreg == ar) + ar = REG_NONE; + } + if (jit->cachedglobal === bo && br != REG_NONE) + { + if (jit->cachedreg == br) + br = REG_NONE; + } + if (jit->cachedglobal === co && cr != REG_NONE) + { + if (jit->cachedreg == cr) + cr = REG_NONE; + } + + if (!istemp(ao)) + { + /*purge the old cache*/ + switch(jit->cachedreg) + { + case REG_NONE: + break; + case REG_S0: + //fstps glob[C] + EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + jit->cachedglobal); + break; + default: + STOREREG(jit->cachedreg, jit->glob + jit->cachedglobal); + break; + } + jit->cachedglobal = -1; + jit->cachedreg = REG_NONE; + } + +#endif + switch(ar) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].a); + break; + default: + LOADREG(jit->glob + ao, ar); + break; + } + + switch(br) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].b); + break; + default: + LOADREG(jit->glob + bo, br); + break; + } + + switch(cr) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].c); + break; + default: + LOADREG(jit->glob + co, cr); + break; + } +} +static void GCache_Store(struct jitstate *jit, int ofs, int reg) +{ +#if USECACHE + jit->cachedglobal = ofs; + jit->cachedreg = reg; +#else + switch(reg) + { + case REG_NONE: + break; + case REG_S0: + //fstps glob[C] + EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + ofs); + break; + default: + STOREREG(reg, jit->glob + ofs); + break; + } +#endif +} + static void *LocalLoc(struct jitstate *jit) { return &jit->code[jit->codesize]; @@ -204,9 +327,17 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsn void PR_CloseJit(struct jitstate *jit) { - free(jit->statementjumps); - free(jit->statementoffsets); - free(jit->code); + if (jit) + { + free(jit->statementjumps); + free(jit->statementoffsets); +#ifndef _WIN32 + munmap(jit->code, jit->jitstatements * 500); +#else + free(jit->code); +#endif + free(jit) + } } #define EmitByte(v) EmitByte(jit, v) @@ -238,7 +369,11 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) jit->statementjumps = malloc(numstatements*12); jit->statementoffsets = malloc(numstatements*4); +#ifndef _WIN32 + jit->code = mmap(NULL, numstatements*500, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#else jit->code = malloc(numstatements*500); +#endif if (!jit->code) return NULL; @@ -343,6 +478,9 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) case OP_CALL6: case OP_CALL7: case OP_CALL8: + //FIXME: the size of this instruction is going to hurt cache performance if every single function call is expanded into this HUGE CHUNK of gibberish! + //FIXME: consider the feasability of just calling a C function and just jumping to the address it returns. + //save the state in place the rest of the engine can cope with //movl $i, pr_xstatement EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i); @@ -705,6 +843,7 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) case OP_AND_F: //test floats properly, so we don't get confused with -0.0 + //FIXME: is it feasable to grab the value as an int and test it against 0x7fffffff? //flds glob[A] EmitByte(0xd9); EmitByte(0x05); EmitAdr(glob + op[i].a); @@ -1256,6 +1395,7 @@ LOADREG(glob + op[i].b, REG_EDI); FixupJumps(jit); + /* most likely want executable memory calls somewhere else more common */ #ifdef _WIN32 { DWORD old; @@ -1264,6 +1404,8 @@ LOADREG(glob + op[i].b, REG_EDI); //this means that we must maintain read/write protection, or libc will crash us VirtualProtect(jit->code, jit->codesize, PAGE_EXECUTE_READWRITE, &old); } +#else + mprotect(jit->code, jit->codesize, PROT_READ|PROT_EXEC); #endif // externs->WriteFile("jit.x86", jit->code, jit->codesize); diff --git a/misc/source/fteqcc-src/progsint.h b/misc/source/fteqcc-src/progsint.h index e0d5cd46..795dcb5e 100644 --- a/misc/source/fteqcc-src/progsint.h +++ b/misc/source/fteqcc-src/progsint.h @@ -1,5 +1,7 @@ #ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS + #endif #define _CRT_NONSTDC_NO_WARNINGS #ifndef AVAIL_ZLIB #ifdef _MSC_VER @@ -34,10 +36,6 @@ typedef unsigned char qbyte; #define PROGSUSED #endif -extern int maxedicts; -extern int maxprogs; -extern int hunksize; - #include "progtype.h" #include "progslib.h" @@ -188,6 +186,7 @@ typedef struct progstate_s void *statements; // void *global_struct; float *globals; // same as pr_global_struct + int globals_size; // in bytes typeinfo_t *types; @@ -201,6 +200,10 @@ typedef struct progstate_s int *linenums; //debug versions only progstructtype_t structtype; + +#ifdef QCJIT + struct jitstate *jit; +#endif } progstate_t; typedef struct extensionbuiltin_s { @@ -279,7 +282,7 @@ unsigned int NUM_FOR_EDICT(progfuncs_t *progfuncs, struct edict_s *e); #define GQ_STRING(o) (*(QCC_string_t *)&pr_globals[o]) #define GQ_STRING2(o) ((char*)*(QCC_string_t *)&pr_globals[o]) #define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) -#define G_PROG(o) (*(progsnum_t *)&pr_globals[o]) //simply so it's nice and easy to change... +#define G_PROG(o) G_FLOAT(o) //simply so it's nice and easy to change... #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) @@ -343,9 +346,6 @@ void PR_SetBuiltins(int type); #define vars(type, name, size) type name[size] typedef struct prinst_s { -#ifdef QCJIT - struct jitstate *jit; -#endif char **tempstrings; int maxtempstrings; int numtempstrings; @@ -355,8 +355,8 @@ typedef struct prinst_s { int maxallocedstrings; int numallocedstrings; -var(progstate_t *, pr_progstate); -#define pr_progstate prinst->pr_progstate +var(progstate_t *, progstate); +#define pr_progstate prinst->progstate var(progsnum_t, pr_typecurrent); #define pr_typecurrent prinst->pr_typecurrent @@ -481,6 +481,7 @@ pbool CompileFile(progfuncs_t *progfuncs, char *filename); struct jitstate; struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs); void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jitstate, int statement); +void PR_CloseJit(struct jitstate *jit); char *QCC_COM_Parse (char *data); extern char qcc_token[1024]; diff --git a/misc/source/fteqcc-src/progslib.h b/misc/source/fteqcc-src/progslib.h index 1e9b6125..1160959b 100644 --- a/misc/source/fteqcc-src/progslib.h +++ b/misc/source/fteqcc-src/progslib.h @@ -138,6 +138,10 @@ struct progfuncs_s { 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) ); + + void *(*AddressableAlloc) (progfuncs_t *progfuncs, int ammount); /*returns memory within the qc block, use stringtoprogs to get a usable qc pointer/string*/ + + string_t (*AllocTempString) (progfuncs_t *prinst, char **str, unsigned int len); }; typedef struct progexterns_s { @@ -179,6 +183,9 @@ typedef struct progexterns_s { unsigned int *sv_num_edicts; //pointer to the engine's edict count. int (*useeditor) (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging. + void (*addressablerelocated) (progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen); //called when the progs memory was resized. you must fix up all pointers to globals, strings, fields, addressable blocks. + + void *user; /*contains the owner's world reference in FTE*/ } progparms_t, progexterns_t; //FIXMEs @@ -206,7 +213,7 @@ typedef union eval_s func_t function; int _int; int edict; - progsnum_t prog; //so it can easily be changed + float prog; //so it can easily be changed } eval_t; #endif @@ -252,7 +259,8 @@ typedef union eval_s #define PR_FindFunction(pf, name, num) (*pf->FindFunction) (pf, name, num) #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 PR_Alloc(pf,size,whatfor) (*pf->Tempmem) (pf, size, whatfor) +#define PR_AddressableAlloc(pf,size) (*pf->AddressableAlloc) (pf, size) #define PROG_TO_EDICT(pf, ed) (*pf->ProgsToEdict) (pf, ed) #define EDICT_TO_PROG(pf, ed) (*pf->EdictToProgs) (pf, (struct edict_s*)ed) diff --git a/misc/source/fteqcc-src/qcc.h b/misc/source/fteqcc-src/qcc.h index 5c2cd2ed..1ee2ac62 100644 --- a/misc/source/fteqcc-src/qcc.h +++ b/misc/source/fteqcc-src/qcc.h @@ -42,7 +42,7 @@ extern float (*PRLittleFloat) (float l); #define MAX_ERRORS 10 -#define MAX_NAME 128 // chars long +#define MAX_NAME 256 // chars long extern unsigned int MAX_REGS; @@ -59,7 +59,7 @@ extern int MAX_FUNCTIONS; #define MAX_DATA_PATH 64 extern int MAX_CONSTANTS; -#define MAXCONSTANTLENGTH 64 +#define MAXCONSTANTNAMELENGTH 64 #define MAXCONSTANTPARAMLENGTH 32 #define MAXCONSTANTPARAMS 32 @@ -281,7 +281,7 @@ extern hashtable_t globalstable, localstable; #endif #ifdef WRITEASM -FILE *asmfile; +extern FILE *asmfile; #endif //============================================================================= @@ -305,6 +305,8 @@ typedef struct QCC_type_s unsigned int ofs; //inside a structure. unsigned int size; + unsigned int arraysize; + pbool typedefed; char *name; } QCC_type_t; int typecmp(QCC_type_t *a, QCC_type_t *b); @@ -330,6 +332,7 @@ typedef struct QCC_def_s struct QCC_def_s *nextlocal; //provides a chain of local variables for the opt_locals_marshalling optimisation. gofs_t ofs; struct QCC_def_s *scope; // function the var was defined in, or NULL + struct QCC_def_s *deftail; // arrays and structs create multiple globaldef objects providing different types at the different parts of the single object (struct), or alternative names (vectors). this allows us to correctly set the const type based upon how its initialised. int initialized; // 1 when a declaration included "= immediate" int constant; // 1 says we can use the value over and over again @@ -340,10 +343,11 @@ typedef struct QCC_def_s int s_line; int arraysize; - pbool shared; - pbool saved; - pbool isstatic; - pbool subscoped_away; + pbool shared:1; + pbool saved:1; + pbool isstatic:1; + pbool subscoped_away:1; + pbool followptr:1; temp_t *temp; } QCC_def_t; @@ -371,7 +375,7 @@ typedef union QCC_eval_s const extern unsigned int type_size[]; //extern QCC_def_t *def_for_type[9]; -extern QCC_type_t *type_void, *type_string, *type_float, *type_vector, *type_entity, *type_field, *type_function, *type_pointer, *type_integer, *type_variant, *type_floatfield; +extern QCC_type_t *type_void, *type_string, *type_float, *type_vector, *type_entity, *type_field, *type_function, *type_pointer, *type_floatpointer, *type_intpointer, *type_integer, *type_variant, *type_floatfield; struct QCC_function_s { @@ -406,7 +410,7 @@ extern QCC_pr_info_t pr; typedef struct { - char name[MAXCONSTANTLENGTH]; + char name[MAXCONSTANTNAMELENGTH]; char *value; char params[MAXCONSTANTPARAMS][MAXCONSTANTPARAMLENGTH]; int numparams; @@ -440,6 +444,7 @@ extern pbool keyword_break; extern pbool keyword_case; extern pbool keyword_class; extern pbool keyword_const; +extern pbool keyword_optional; extern pbool keyword_continue; extern pbool keyword_default; extern pbool keyword_do; @@ -481,6 +486,7 @@ extern pbool flag_fasttrackarrays; extern pbool flag_assume_integer; extern pbool flag_msvcstyle; extern pbool flag_filetimes; +extern pbool flag_typeexplicit; extern pbool opt_overlaptemps; extern pbool opt_shortenifnots; @@ -532,8 +538,10 @@ void QCC_PR_PrintStatement (QCC_dstatement_t *s); void QCC_PR_Lex (void); // reads the next token into pr_token and classifies its type -QCC_type_t *QCC_PR_NewType (char *name, int basictype); -QCC_type_t *QCC_PR_ParseType (int newtype); extern pbool type_inlinefunction; +QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed); +QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type); +QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail); +extern pbool type_inlinefunction; QCC_type_t *QCC_TypeForName(char *name); QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype); QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype); @@ -542,6 +550,8 @@ CompilerConstant_t *QCC_PR_DefineName(char *name); void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin); +int QCC_PR_IntConstExpr(void); + #ifndef COMMONINLINES pbool QCC_PR_CheckImmediate (char *string); pbool QCC_PR_CheckToken (char *string); @@ -551,7 +561,7 @@ pbool QCC_PR_CheckKeyword(int keywordenabled, char *string); #endif 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, ...); +pbool 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, ...); @@ -614,6 +624,7 @@ enum { WARN_SAMENAMEASGLOBAL, WARN_CONSTANTCOMPARISON, WARN_UNSAFEFUNCTIONRETURNTYPE, + WARN_MISSINGOPTIONAL, ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called. @@ -846,23 +857,32 @@ extern int numtemps; typedef char PATHSTRING[MAX_DATA_PATH]; -PATHSTRING *precache_sounds; -int *precache_sounds_block; -int *precache_sounds_used; -int numsounds; - -PATHSTRING *precache_textures; -int *precache_textures_block; -int numtextures; - -PATHSTRING *precache_models; -int *precache_models_block; -int *precache_models_used; -int nummodels; - -PATHSTRING *precache_files; -int *precache_files_block; -int numfiles; +extern PATHSTRING *precache_sounds; +extern int *precache_sounds_block; +extern int *precache_sounds_used; +extern int numsounds; + +extern PATHSTRING *precache_textures; +extern int *precache_textures_block; +extern int numtextures; + +extern PATHSTRING *precache_models; +extern int *precache_models_block; +extern int *precache_models_used; +extern int nummodels; + +extern PATHSTRING *precache_files; +extern int *precache_files_block; +extern int numfiles; + +typedef struct qcc_includechunk_s { + struct qcc_includechunk_s *prev; + char *filename; + char *currentdatapoint; + int currentlinenumber; + CompilerConstant_t *cnst; +} qcc_includechunk_t; +extern qcc_includechunk_t *currentchunk; int QCC_CopyString (char *str); diff --git a/misc/source/fteqcc-src/qcc_cmdlib.c b/misc/source/fteqcc-src/qcc_cmdlib.c index f93e3e9c..b3c4b6b8 100644 --- a/misc/source/fteqcc-src/qcc_cmdlib.c +++ b/misc/source/fteqcc-src/qcc_cmdlib.c @@ -10,23 +10,15 @@ 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 +#ifdef _WIN64 + #ifdef _SDL #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); + void *__imp__vsnprintf = vsnprintf; #endif #endif -#endif // set these before calling CheckParm int myargc; @@ -44,7 +36,7 @@ const unsigned int type_size[12] = {1, //void sizeof(func_t)/4,//function 1, //pointer (its an int index) 1, //integer - 1, //fixme: how big should a variant be? + 3, //fixme: how big should a variant be? 0, //ev_struct. variable sized. 0 //ev_union. variable sized. }; diff --git a/misc/source/fteqcc-src/qcc_pr_comp.c b/misc/source/fteqcc-src/qcc_pr_comp.c index a2699877..badefcac 100644 --- a/misc/source/fteqcc-src/qcc_pr_comp.c +++ b/misc/source/fteqcc-src/qcc_pr_comp.c @@ -12,9 +12,6 @@ extern char *compilingfile; int conditional; -extern int dotranslate; -extern int dotranslate_count; - //standard qcc keywords #define keyword_do 1 #define keyword_return 1 @@ -28,6 +25,7 @@ pbool keyword_asm; pbool keyword_break; pbool keyword_case; pbool keyword_class; +pbool keyword_optional; pbool keyword_const; //fixme pbool keyword_continue; pbool keyword_default; @@ -80,6 +78,7 @@ pbool flag_fasttrackarrays; //Faster arrays, dynamically detected, activated onl 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 flag_typeexplicit; //no implicit type conversions, you must do the casts yourself. 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. @@ -134,7 +133,6 @@ 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); QCC_type_t *QCC_PR_FindType (QCC_type_t *type); QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto); QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto); @@ -192,7 +190,7 @@ int num_labels; QCC_def_t *extra_parms[MAX_EXTRA_PARMS]; -#define ASSOC_RIGHT_RESULT ASSOC_RIGHT +//#define ASSOC_RIGHT_RESULT ASSOC_RIGHT //======================================== @@ -295,9 +293,9 @@ QCC_opcode_t pr_opcodes[] = //these are hexen2 {7, "*=", "MULSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "*=", "MULSTORE_V", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector}, + {7, "*=", "MULSTORE_VF", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector}, {7, "*=", "MULSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, - {7, "*=", "MULSTOREP_V", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector}, + {7, "*=", "MULSTOREP_VF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector}, {7, "/=", "DIVSTORE_F", 6, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, {7, "/=", "DIVSTOREP_F", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, @@ -358,8 +356,8 @@ QCC_opcode_t pr_opcodes[] = {7, "", "CALL8H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector}, {7, "=", "STORE_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer}, - {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_integer}, - {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_float}, + {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_integer}, + {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_float}, {7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, {7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float}, @@ -400,7 +398,7 @@ QCC_opcode_t pr_opcodes[] = //var, offset return {7, "", "GET_POINTER", -1, ASSOC_LEFT, &type_float, &type_integer, &type_pointer}, - {7, "", "ARRAY_OFS", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, + {7, "", "MUL4ADD_I", -1, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, {7, "=", "LOADA_F", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float}, {7, "=", "LOADA_V", 6, ASSOC_LEFT, &type_vector, &type_integer, &type_vector}, @@ -494,9 +492,9 @@ QCC_opcode_t pr_opcodes[] = {7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_integer, NULL, NULL}, -{7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, +{7, "", "UNUSED", 6, ASSOC_RIGHT, &type_void, &type_void, &type_void}, {7, "", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, {7, "", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void}, @@ -524,23 +522,30 @@ QCC_opcode_t pr_opcodes[] = {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, - {7, "*=", "OP_MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "*=", "OP_MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "/=", "OP_DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "/=", "OP_DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "+=", "OP_ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "+=", "OP_ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "-=", "OP_SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - {7, "-=", "OP_SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, - - {7, "*=", "OP_MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "*=", "OP_MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "/=", "OP_DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "/=", "OP_DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "+=", "OP_ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "+=", "OP_ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "-=", "OP_SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, - {7, "-=", "OP_SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "*=", "MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, + {7, "*=", "MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, + {7, "/=", "DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, + {7, "/=", "DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, + {7, "+=", "ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, + {7, "+=", "ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, + {7, "-=", "SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, + {7, "-=", "SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, + + {7, "*=", "MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, + {7, "*=", "MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, + {7, "/=", "DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, + {7, "/=", "DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, + {7, "+=", "ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, + {7, "+=", "ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, + {7, "-=", "SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, + {7, "-=", "SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, + + {7, "*=", "MULSTORE_VI", 6, ASSOC_RIGHT_RESULT, &type_vector, &type_integer, &type_vector}, + {7, "*=", "MULSTOREP_VI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, + + {7, "=", "LOADA_STRUCT", 6, ASSOC_LEFT, &type_float, &type_integer, &type_float}, + + {7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer}, {0, NULL} }; @@ -595,6 +600,7 @@ pbool OpAssignsToB(unsigned int op) #undef ASSOC_RIGHT_RESULT #define TOP_PRIORITY 7 +#define FUNC_PRIORITY 1 #define UNARY_PRIORITY 1 #define NOT_PRIORITY 5 //conditional and/or @@ -657,11 +663,17 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_MUL_F], &pr_opcodes[OP_MUL_V], &pr_opcodes[OP_MUL_FV], + &pr_opcodes[OP_MUL_IV], &pr_opcodes[OP_MUL_VF], + &pr_opcodes[OP_MUL_VI], &pr_opcodes[OP_MUL_I], + &pr_opcodes[OP_MUL_FI], + &pr_opcodes[OP_MUL_IF], &pr_opcodes[OP_DIV_F], &pr_opcodes[OP_DIV_I], + &pr_opcodes[OP_DIV_FI], + &pr_opcodes[OP_DIV_IF], &pr_opcodes[OP_DIV_VF], &pr_opcodes[OP_BITAND_F], @@ -734,6 +746,8 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = NULL }, { //6 + &pr_opcodes[OP_STOREP_P], + &pr_opcodes[OP_STORE_F], &pr_opcodes[OP_STORE_V], &pr_opcodes[OP_STORE_S], @@ -754,7 +768,6 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_STOREP_I], &pr_opcodes[OP_STOREP_IF], &pr_opcodes[OP_STOREP_FI], - &pr_opcodes[OP_STOREP_P], &pr_opcodes[OP_DIVSTORE_F], &pr_opcodes[OP_DIVSTORE_I], @@ -765,12 +778,14 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_DIVSTOREP_IF], &pr_opcodes[OP_DIVSTOREP_FI], &pr_opcodes[OP_MULSTORE_F], - &pr_opcodes[OP_MULSTORE_V], + &pr_opcodes[OP_MULSTORE_VF], + &pr_opcodes[OP_MULSTORE_VI], &pr_opcodes[OP_MULSTORE_I], &pr_opcodes[OP_MULSTORE_IF], &pr_opcodes[OP_MULSTORE_FI], &pr_opcodes[OP_MULSTOREP_F], - &pr_opcodes[OP_MULSTOREP_V], + &pr_opcodes[OP_MULSTOREP_VF], + &pr_opcodes[OP_MULSTOREP_VI], &pr_opcodes[OP_MULSTOREP_I], &pr_opcodes[OP_MULSTOREP_IF], &pr_opcodes[OP_MULSTOREP_FI], @@ -913,7 +928,6 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op) //stores into a pointer (generated from 'ent.field=XXX') case OP_STOREP_I: //no worse than the other OP_STOREP_X functions - case OP_STOREP_P: //reads from an entity field case OP_LOAD_I: //no worse than the other OP_LOAD_X functions. case OP_LOAD_P: @@ -1011,9 +1025,9 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op) return false; //DPFIXME: dp's bounds check may give false positives with expected uses. case OP_MULSTORE_F: - case OP_MULSTORE_V: + case OP_MULSTORE_VF: case OP_MULSTOREP_F: - case OP_MULSTOREP_V: // e.v *= f + case OP_MULSTOREP_VF: // e.v *= f case OP_DIVSTORE_F: case OP_DIVSTOREP_F: case OP_STORE_IF: @@ -1097,8 +1111,14 @@ Emits a primitive statement, returning the var it places it's value in QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement); static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted) { + /*no conversion needed*/ + if (var->type->type == wanted) + return 0; if (var->type->type == ev_integer && wanted == ev_function) return 0; + if (var->type->type == ev_integer && wanted == ev_pointer) + return 0; + /*stuff needs converting*/ if (var->type->type == ev_pointer && var->type->aux_type) { if (var->type->aux_type->type == ev_float && wanted == ev_integer) @@ -1116,10 +1136,12 @@ static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted) return OP_CONV_ITOF; } + /*impossible*/ return -1; } -QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted) +QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal) { + extern char *basictypenames[]; int o; if (pr_classtype && var->type->type == ev_field && wanted != ev_field) @@ -1127,7 +1149,7 @@ QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted) if (pr_classtype) { //load self.var into a temp QCC_def_t *self; - self = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); + self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); switch(wanted) { case ev_float: @@ -1148,16 +1170,25 @@ QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted) o = QCC_ShouldConvert(var, wanted); - if (o <= 0) //no conversion + if (o == 0) //type already matches return var; - + if (flag_typeexplicit) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name); + if (o < 0) + { + if (fatal) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name); + else + return var; + } return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value } -QCC_def_t *QCC_MakeStringDef(char *value); -QCC_def_t *QCC_MakeFloatDef(float value); -QCC_def_t *QCC_MakeIntDef(int value); -QCC_def_t *QCC_MakeVectorDef(float a, float b, float c); +QCC_def_t *QCC_MakeTranslateStringConst(char *value); +QCC_def_t *QCC_MakeStringConst(char *value); +QCC_def_t *QCC_MakeFloatConst(float value); +QCC_def_t *QCC_MakeIntConst(int value); +QCC_def_t *QCC_MakeVectorConst(float a, float b, float c); typedef struct freeoffset_s { struct freeoffset_s *next; @@ -1363,10 +1394,8 @@ static void QCC_FreeTemps(void) while(t) { if (t->used && !pr_error_count) //don't print this after an error jump out. - { - QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used in %s", pr_scope->name); - t->used = false; - } + QCC_PR_ParseWarning(WARN_DEBUGGING, "Internal: temp(ofs %i) was not released in %s. This implies miscompilation.", t->ofs, pr_scope->name); + t->used = false; t = t->next; } } @@ -1399,6 +1428,13 @@ static void QCC_LockTemp(QCC_def_t *d) if (d->temp && d->temp->used) d->temp->scope = pr_scope; } +static void QCC_ForceLockTempForOffset(int ofs) +{ + temp_t *t; + for (t = functemps; t; t = t->next) + if(t->ofs == ofs /* && t->used */) + t->scope = pr_scope; +} static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement) { @@ -1501,14 +1537,17 @@ static void QCC_fprintfLocals(FILE *f, gofs_t paramstart, gofs_t paramend) { if (var->ofs >= paramstart && var->ofs < paramend) continue; - fprintf(f, "local %s %s; /* at %d */\n", TypeName(var->type), var->name, var->ofs); + if (var->arraysize) + fprintf(f, "local %s %s[%i];\n", TypeName(var->type), var->name, var->arraysize); + else + fprintf(f, "local %s %s;\n", TypeName(var->type), var->name); } for (t = functemps, i = 0; t; t = t->next, i++) { if (t->lastfunc == pr_scope) { - fprintf(f, "local %s temp_%i; /* at %d */\n", (t->size == 1)?"float":"vector", i, t->ofs); + fprintf(f, "local %s temp_%i;\n", (t->size == 1)?"float":"vector", i); } } } @@ -1528,9 +1567,9 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size) if (ofs >= t->ofs && ofs < t->ofs + t->size) { if (size < t->size) - sprintf(message, "temp_%i_%c", i, 'x' + (ofs-t->ofs)%3); + sprintf(message, "temp_%i_%c", t->ofs, 'x' + (ofs-t->ofs)%3); else - sprintf(message, "temp_%i", i); + sprintf(message, "temp_%i", t->ofs); return message; } } @@ -1615,36 +1654,28 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size) } #endif -QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement) +QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force); + +QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement) { QCC_dstatement_t *statement; QCC_def_t *var_c=NULL, *temp=NULL; if (outstatement == (QCC_dstatement_t **)0xffffffff) outstatement = NULL; - else if (op->priority != -1) + else if (op->priority != -1 && op->priority != CONDITION_PRIORITY) { if (op->associative!=ASSOC_LEFT) { - if (op->type_a == &type_pointer) - var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type); - else - var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type); + if (op->type_a != &type_pointer) + var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type, false); } else { if (var_a) - var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type); + var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type, false); if (var_b) - var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type); -// if (op->type_a == &def_pointer) -// var_a = QCC_SupplyConversion(var_a, (*op->type_b)->type); -// else -// var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type); -// } -// //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, false); } } @@ -1677,73 +1708,92 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //both are constants switch (op - pr_opcodes) //improve some of the maths. { + case OP_LOADA_F: + case OP_LOADA_V: + case OP_LOADA_S: + case OP_LOADA_ENT: + case OP_LOADA_FLD: + case OP_LOADA_FNC: + case OP_LOADA_I: + { + QCC_def_t *nd; + nd = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (nd, 0, sizeof(QCC_def_t)); + nd->type = var_a->type; + nd->ofs = var_a->ofs + G_INT(var_b->ofs); + nd->temp = var_a->temp; + nd->constant = true; + nd->name = var_a->name; + return nd; + } + break; case OP_BITOR_F: optres_constantarithmatic++; - return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs))); + return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs))); case OP_BITAND_F: optres_constantarithmatic++; - return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs))); + return QCC_MakeFloatConst((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs))); case OP_MUL_F: optres_constantarithmatic++; - return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs)); + return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs)); case OP_DIV_F: optres_constantarithmatic++; - return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs)); + return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) / G_FLOAT(var_b->ofs)); case OP_ADD_F: optres_constantarithmatic++; - return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs)); + return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) + G_FLOAT(var_b->ofs)); case OP_SUB_F: optres_constantarithmatic++; - return QCC_MakeFloatDef(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs)); + return QCC_MakeFloatConst(G_FLOAT(var_a->ofs) - G_FLOAT(var_b->ofs)); case OP_BITOR_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) | G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) | G_INT(var_b->ofs)); case OP_BITAND_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) & G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) & G_INT(var_b->ofs)); case OP_MUL_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) * G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) * G_INT(var_b->ofs)); case OP_DIV_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) / G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) / G_INT(var_b->ofs)); case OP_ADD_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) + G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) + G_INT(var_b->ofs)); case OP_SUB_I: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) - G_INT(var_b->ofs)); case OP_AND_F: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) && G_INT(var_b->ofs)); case OP_OR_F: optres_constantarithmatic++; - return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs)); + return QCC_MakeIntConst(G_INT(var_a->ofs) || G_INT(var_b->ofs)); case OP_MUL_V: //mul_f is actually a dot-product optres_constantarithmatic++; - return QCC_MakeFloatDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) + + return QCC_MakeFloatConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0) + G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1) + G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2)); case OP_MUL_FV: optres_constantarithmatic++; - return QCC_MakeVectorDef( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0), + return QCC_MakeVectorConst( G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+0), G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+1), G_FLOAT(var_a->ofs) * G_FLOAT(var_b->ofs+2)); case OP_MUL_VF: optres_constantarithmatic++; - return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs), + return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) * G_FLOAT(var_b->ofs), G_FLOAT(var_a->ofs+1) * G_FLOAT(var_b->ofs), G_FLOAT(var_a->ofs+2) * G_FLOAT(var_b->ofs)); case OP_ADD_V: optres_constantarithmatic++; - return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0), + return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) + G_FLOAT(var_b->ofs+0), G_FLOAT(var_a->ofs+1) + G_FLOAT(var_b->ofs+1), G_FLOAT(var_a->ofs+2) + G_FLOAT(var_b->ofs+2)); case OP_SUB_V: optres_constantarithmatic++; - return QCC_MakeVectorDef( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0), + return QCC_MakeVectorConst( G_FLOAT(var_a->ofs+0) - G_FLOAT(var_b->ofs+0), G_FLOAT(var_a->ofs+1) - G_FLOAT(var_b->ofs+1), G_FLOAT(var_a->ofs+2) - G_FLOAT(var_b->ofs+2)); } @@ -1753,6 +1803,12 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //a is const, b is not switch (op - pr_opcodes) { + case OP_CONV_FTOI: + optres_constantarithmatic++; + return QCC_MakeIntConst(G_FLOAT(var_a->ofs)); + case OP_CONV_ITOF: + optres_constantarithmatic++; + return QCC_MakeFloatConst(G_INT(var_a->ofs)); case OP_BITOR_F: case OP_OR_F: case OP_ADD_F: @@ -1816,6 +1872,25 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //b is const, a is not switch (op - pr_opcodes) { + case OP_LOADA_F: + case OP_LOADA_V: + case OP_LOADA_S: + case OP_LOADA_ENT: + case OP_LOADA_FLD: + case OP_LOADA_FNC: + case OP_LOADA_I: + { + QCC_def_t *nd; + nd = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (nd, 0, sizeof(QCC_def_t)); + nd->type = var_a->type; + nd->ofs = var_a->ofs + G_INT(var_b->ofs); + nd->temp = var_a->temp; + nd->constant = false; + nd->name = var_a->name; + return nd; + } + break; case OP_BITOR_F: case OP_OR_F: case OP_SUB_F: @@ -1874,7 +1949,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var return var_a; } case OP_AND_I: - if (G_INT(var_b->ofs) != 0) + if (G_INT(var_b->ofs) == 0) { optres_constantarithmatic++; QCC_UnFreeTemp(var_a); @@ -1887,6 +1962,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var switch (op - pr_opcodes) { + case OP_LOADA_F: + case OP_LOADA_V: + case OP_LOADA_S: + case OP_LOADA_ENT: + case OP_LOADA_FLD: + case OP_LOADA_FNC: + case OP_LOADA_I: + break; case OP_AND_F: if (var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same"); @@ -2035,8 +2118,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var { switch(op - pr_opcodes) { + case OP_LOADA_STRUCT: + /*emit this anyway. if it reaches runtime then you messed up. + this is valid only if you do &foo[0]*/ + break; + + case OP_IF_S: - var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false); + var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false); numstatements--; var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL); statement = &statements[numstatements]; @@ -2047,7 +2136,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var break; case OP_IFNOT_S: - var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 1, false); + var_c = QCC_PR_GetDef(type_string, "string_null", NULL, true, 0, false); numstatements--; var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_S], var_a, var_c, NULL); statement = &statements[numstatements]; @@ -2058,7 +2147,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var break; case OP_IF_F: - var_c = QCC_MakeFloatDef(0); + var_c = QCC_MakeFloatConst(0); numstatements--; var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL); statement = &statements[numstatements]; @@ -2069,7 +2158,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var break; case OP_IFNOT_F: - var_c = QCC_MakeFloatDef(0); + var_c = QCC_MakeFloatConst(0); numstatements--; var_a = QCC_PR_Statement(&pr_opcodes[OP_NE_F], var_a, var_c, NULL); statement = &statements[numstatements]; @@ -2086,6 +2175,13 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; var_c = var_a; break; + case OP_ADDSTORE_I: + op = &pr_opcodes[OP_ADD_I]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_ADDSTORE_FI: op = &pr_opcodes[OP_ADD_FI]; var_c = var_b; @@ -2183,13 +2279,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_c = var_a; break; - case OP_MULSTORE_V: + case OP_MULSTORE_VF: op = &pr_opcodes[OP_MUL_VF]; var_c = var_b; var_b = var_a; var_a = var_c; var_c = var_a; break; + case OP_MULSTORE_VI: + op = &pr_opcodes[OP_MUL_VI]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_BITSET_I: op = &pr_opcodes[OP_BITOR_I]; @@ -2206,6 +2309,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_c = var_a; break; + case OP_STOREP_P: + op = &pr_opcodes[OP_STOREP_I]; + break; + case OP_BITCLR: //b = var, a = bit field. @@ -2236,8 +2343,14 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_DIVSTOREP_FI: case OP_DIVSTOREP_IF: + case OP_MULSTOREP_VF: + case OP_MULSTOREP_VI: + case OP_SUBSTOREP_V: + case OP_ADDSTOREP_V: case OP_SUBSTOREP_F: + case OP_SUBSTOREP_I: + case OP_ADDSTOREP_I: case OP_ADDSTOREP_F: case OP_MULSTOREP_F: case OP_DIVSTOREP_F: @@ -2251,35 +2364,60 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var { int st; int need_lock = false; - for (st = numstatements-2; st>=0; st--) + if (var_b->temp) { - if (statements[st].op == OP_ADDRESS) - if (statements[st].c == var_b->ofs) - break; + 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].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 (statements[st].c == var_b->ofs) + { + st = -1; + break; + } + } } - if (st < 0) - QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement"); + else + st = -1; + var_c = QCC_GetTemp(*op->type_c); - if (need_lock) - QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/ + if (st < 0) + { + /*generate new OP_LOADP instruction*/ + statement->op = ((*op->type_c)->type==ev_vector)?OP_LOADP_V:OP_LOADP_F; + statement->a = var_b->ofs; + statement->b = var_c->ofs; + statement->c = 0; + } + else + { + /*it came from an OP_ADDRESS - st says the instruction*/ + if (need_lock) + { + QCC_ForceLockTempForOffset(statements[st].a); + QCC_ForceLockTempForOffset(statements[st].b); + QCC_LockTemp(var_c); /*that temp needs to be preserved over calls*/ + } - statement_linenums[statement-statements] = statement_linenums[st]; - statement->op = OP_ADDRESS; - statement->a = statements[st].a; - statement->b = statements[st].b; - statement->c = statements[st].c; + /*generate new OP_ADDRESS instruction - FIXME: the arguments may have changed since the original instruction*/ + statement_linenums[statement-statements] = statement_linenums[st]; + statement->op = OP_ADDRESS; + statement->a = statements[st].a; + statement->b = statements[st].b; + statement->c = statements[st].c; - statement_linenums[st] = pr_source_line; - statements[st].op = OP_LOAD_F; - statements[st].a = statements[st].a; - statements[st].b = statements[st].b; - statements[st].c = var_c->ofs; + /*convert old one to an OP_LOAD*/ + statement_linenums[st] = pr_source_line; + statements[st].op = ((*op->type_c)->type==ev_vector)?OP_LOAD_V:OP_LOAD_F; + statements[st].a = statements[st].a; + statements[st].b = statements[st].b; + statements[st].c = var_c->ofs; + } } statement = &statements[numstatements]; @@ -2288,9 +2426,24 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var statement_linenums[statement-statements] = pr_source_line; switch(op - pr_opcodes) { + case OP_SUBSTOREP_V: + statement->op = OP_SUB_V; + break; + case OP_ADDSTOREP_V: + statement->op = OP_ADD_V; + break; + case OP_MULSTOREP_VF: + statement->op = OP_MUL_VF; + break; + case OP_MULSTOREP_VI: + statement->op = OP_MUL_VI; + break; case OP_SUBSTOREP_F: statement->op = OP_SUB_F; break; + case OP_SUBSTOREP_I: + statement->op = OP_SUB_I; + break; case OP_SUBSTOREP_IF: statement->op = OP_SUB_IF; break; @@ -2318,6 +2471,9 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_ADDSTOREP_F: statement->op = OP_ADD_F; break; + case OP_ADDSTOREP_I: + statement->op = OP_ADD_I; + break; case OP_MULSTOREP_F: statement->op = OP_MUL_F; break; @@ -2370,7 +2526,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; //this is the value. } - op = &pr_opcodes[OP_STOREP_F]; + op = &pr_opcodes[((*op->type_c)->type==ev_vector)?OP_STOREP_V:OP_STOREP_F]; QCC_FreeTemp(var_c); var_c = NULL; QCC_FreeTemp(var_b); @@ -2379,86 +2535,6 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; break; - case OP_MULSTOREP_V: - case OP_SUBSTOREP_V: - case OP_ADDSTOREP_V: -// QCC_PR_ParseWarning(0, "XSTOREP_V emulation is still experimental"); - QCC_UnFreeTemp(var_a); - QCC_UnFreeTemp(var_b); - //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); /*that temp needs to be preserved over calls*/ - - statement_linenums[statement-statements] = statement_linenums[st]; - statement->op = OP_ADDRESS; - statement->a = statements[st].a; - statement->b = statements[st].b; - statement->c = statements[st].c; - - statement_linenums[st] = pr_source_line; - statements[st].op = OP_LOAD_V; - statements[st].a = statements[st].a; - statements[st].b = statements[st].b; - statements[st].c = var_c->ofs; - } - - statement = &statements[numstatements]; - numstatements++; - - statement_linenums[statement-statements] = pr_source_line; - switch(op - pr_opcodes) - { - case OP_SUBSTOREP_V: - statement->op = OP_SUB_V; - break; - case OP_ADDSTOREP_V: - statement->op = OP_ADD_V; - break; - case OP_MULSTOREP_V: - statement->op = OP_MUL_VF; - break; - default: //no way will this be hit... - QCC_PR_ParseError(ERR_INTERNAL, "opcode invalid 3 times %i", op - pr_opcodes); - } - statement->a = var_a ? var_a->ofs : 0; - statement->b = var_c ? var_c->ofs : 0; - QCC_FreeTemp(var_c); - var_c = QCC_GetTemp(*op->type_c); - statement->c = var_c ? var_c->ofs : 0; - - var_b = var_b; //this is the ptr. - QCC_FreeTemp(var_a); - var_a = var_c; //this is the value. - op = &pr_opcodes[OP_STOREP_V]; - - - - - QCC_FreeTemp(var_c); - var_c = NULL; - QCC_FreeTemp(var_b); - - statement = &statements[numstatements]; - numstatements++; - break; default: QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target", op->name, op->opname); break; @@ -2571,21 +2647,32 @@ QCC_def_t *QCC_PR_ParseImmediate (void) if (pr_immediate_type == type_float) { - cn = QCC_MakeFloatDef(pr_immediate._float); + cn = QCC_MakeFloatConst(pr_immediate._float); QCC_PR_Lex (); return cn; } if (pr_immediate_type == type_integer) { - cn = QCC_MakeIntDef(pr_immediate._int); + cn = QCC_MakeIntConst(pr_immediate._int); QCC_PR_Lex (); return cn; } if (pr_immediate_type == type_string) { - cn = QCC_MakeStringDef(pr_immediate_string); - QCC_PR_Lex (); + char tmp[8192]; + strcpy(tmp, pr_immediate_string); + + for(;;) + { + QCC_PR_Lex (); + if (pr_token_type == tt_immediate && pr_token_type == tt_immediate) + strcat(tmp, pr_immediate_string); + else + break; + } + + cn = QCC_MakeStringConst(tmp); return cn; } @@ -2876,7 +2963,7 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i //FIXME: problems could occur with hexen2 calling conventions when parm0/1 is 'self' //thiscall. copy the right ent into 'self' (if it's not the same offset) - d = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); + d = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); if (statements[laststatement-1].a != d->ofs) { oself = QCC_GetTemp(type_entity); @@ -2922,11 +3009,11 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i //first two args are passed in the call opcode, so don't need to be copied arglist[i]->references++; d->references++; - QCC_FreeTemp(arglist[i]); + /*don't free these temps yet, free them after the return check*/ continue; } - if (arglist[i]->type->size>1 || !opt_nonvec_parms) + if (arglist[i]->type->size == 3 || !opt_nonvec_parms) QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], arglist[i], d, (QCC_dstatement_t **)0xffffffff)); else { @@ -2938,12 +3025,28 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i //if the return value was in use, save it off now, so that it doesn't get clobbered if (def_ret.temp->used) - { oldret = QCC_GetTemp(def_ret.type); + else + oldret = NULL; + + /*can free temps used for arguments now*/ + if (callconvention == OP_CALL1H) + { + for (i = 0; i < argcount && i < 2; i++) + QCC_FreeTemp(arglist[i]); + } + + if (oldret && !def_ret.temp->used) + { + QCC_FreeTemp(oldret); + oldret = NULL; + } + else if (def_ret.temp->used) + { if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, (void*)0xffffffff)); else - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, (void*)0xffffffff)); QCC_UnFreeTemp(oldret); QCC_UnFreeTemp(&def_ret); QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); @@ -2983,35 +3086,29 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i if (oself) QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false); - for(; argcount; argcount--) - { - QCC_FreeTemp(arglist[argcount-1]); - } - if (oldret) { - // Make sure our def_ret backup temp wasn't freed above - QCC_UnFreeTemp(oldret); //this bug fix was brought to you by Blub, the character \ and the number 0. - + if (oldret->temp && !oldret->temp->used) + QCC_PR_ParseWarning(0, "Ret was freed\n"); //if we preserved the ofs_ret global, restore it here if (t->type == ev_variant) { d = QCC_GetTemp(type_variant); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff)); } else { d = QCC_GetTemp(t->aux_type); if (t->aux_type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, NULL)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, (void*)0xffffffff)); else - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, NULL)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff)); } if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, NULL)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, (void*)0xffffffff)); else - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, NULL)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, (void*)0xffffffff)); QCC_FreeTemp(oldret); QCC_UnFreeTemp(&def_ret); QCC_UnFreeTemp(d); @@ -3068,9 +3165,36 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if (!t->num_parms&&t->type != ev_variant) //intrinsics. These base functions have variable arguments. I would check for (...) args too, but that might be used for extended builtin functionality. (this code wouldn't compile otherwise) { + if (!strcmp(func->name, "sizeof")) + { + QCC_type_t *t; + if (!func->initialized) + func->initialized = 3; + func->references++; + t = QCC_PR_ParseType(false, false); + QCC_PR_Expect(")"); + return QCC_MakeIntConst(t->size * 4); + } + if (!strcmp(func->name, "_")) + { + if (!func->initialized) + func->initialized = 3; + func->references++; + if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string) + { + d = QCC_MakeTranslateStringConst(pr_immediate_string); + QCC_PR_Lex(); + } + else + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "_() intrinsic accepts only a string immediate", 1); + QCC_PR_Expect(")"); + return d; + } if (!strcmp(func->name, "random")) { old = NULL; + if (!func->initialized) + func->initialized = 3; func->references++; if (!QCC_PR_CheckToken(")")) { @@ -3094,12 +3218,24 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could d = NULL; } + out = &def_ret; if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0])) { - if(def_ret.temp->used) + if(qcc_targetformat != QCF_HEXEN2) out = QCC_GetTemp(type_float); + else if (out->temp->used) + { + old = QCC_GetTemp(out->type); + if (def_ret.type->size == 3) + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL)); + else + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL)); + QCC_UnFreeTemp(old); + QCC_UnFreeTemp(out); + QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); + } else - out = &def_ret; + old = NULL; if (e) { @@ -3113,15 +3249,15 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could } else { - if (def_ret.temp->used) + if (out->temp->used) { - old = QCC_GetTemp(def_ret.type); + old = QCC_GetTemp(out->type); if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL)); else - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL)); QCC_UnFreeTemp(old); - QCC_UnFreeTemp(&def_ret); + QCC_UnFreeTemp(out); QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); } else @@ -3191,16 +3327,21 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could return d; } - if (def_ret.temp->used) - QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid"); - def_ret.temp->used = true; - def_ret.type = type_float; - return &def_ret; + if (out == &def_ret) + { + if (out->temp->used) + QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid"); + out->temp->used = true; + out->type = type_float; + } + return out; } if (!strcmp(func->name, "randomv")) { out = NULL; + if (!func->initialized) + func->initialized = 3; func->references++; if (!QCC_PR_CheckToken(")")) { @@ -3428,7 +3569,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could { char genfunc[2048]; sprintf(genfunc, "Class*%s", rettype->name); - func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 1, false); + func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, false); func->references++; } QCC_PR_SimpleStatement(OP_CALL0, func->ofs, 0, 0, false); @@ -3455,39 +3596,32 @@ 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; + if (!func->initialized) + func->initialized = 3; + func->references++; e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); QCC_PR_Expect(")"); - e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff); + e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff); d = QCC_PR_GetDef(NULL, "nextent", NULL, false, 0, false); if (!d) QCC_PR_ParseError(0, "the nextent builtin is not defined"); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, &def_parms[0], (QCC_dstatement_t **)0xffffffff)); d = QCC_PR_Statement(&pr_opcodes[OP_CALL0], d, NULL, NULL); - d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntDef(1), (QCC_dstatement_t **)0xffffffff); + d = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), (QCC_dstatement_t **)0xffffffff); e = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], e, d, (QCC_dstatement_t **)0xffffffff); return e; } - else if (!strcmp(func->name, "_") && !QCC_PR_CheckToken(")")) - { - // return string as is, but set the dotranslate flag - ++dotranslate; - e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); - --dotranslate; - QCC_PR_Expect(")"); - return e; - } } //so it's not an intrinsic. if (opt_precache_file) //should we strip out all precache_file calls? { if (!strncmp(func->name,"precache_file", 13)) { - if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string) + if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string && pr_scope && !strcmp(pr_scope->name, "main")) { optres_precache_file += strlen(pr_immediate_string); QCC_PR_Lex(); @@ -3524,7 +3658,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS); else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS) QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS); - if (!extraparms && arg >= t->num_parms) + if (!extraparms && arg >= t->num_parms && !p) { QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters"); QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func); @@ -3539,12 +3673,13 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could e = &def_parms[arg]; e->ofs = OFS_PARM0+0; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[0]), e, (QCC_dstatement_t **)0xffffffff)); e->ofs = OFS_PARM0+1; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[1]), e, (QCC_dstatement_t **)0xffffffff)); e->ofs = OFS_PARM0+2; - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[2]), e, (QCC_dstatement_t **)0xffffffff)); e->ofs = OFS_PARM0; + e->type = type_vector; QCC_PR_Lex(); } @@ -3583,7 +3718,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if (pr_classtype && e->type->type == ev_field && p->type != ev_field) { //convert. - oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 1, false); + oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); switch(e->type->aux_type->type) { case ev_string: @@ -3620,11 +3755,11 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL); else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant? e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL); - else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs]) + else if ((p->type == ev_function && p->type == ev_string) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs]) { //you're allowed to use int 0 to pass a null function pointer //this is basically because __NULL__ is defined as ~0 (int 0) } - else if (p->type != ev_variant) //can cast to variant whatever happens + else if (p->type != ev_variant && e->type->type != ev_variant) //can cast to variant whatever happens { if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function)) { @@ -3674,7 +3809,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could int constchecks; int varchecks; int typechecks; -QCC_def_t *QCC_MakeIntDef(int value) +QCC_def_t *QCC_MakeIntConst(int value) { QCC_def_t *cn; @@ -3708,18 +3843,23 @@ QCC_def_t *QCC_MakeIntDef(int value) cn->constant = true; cn->initialized = 1; cn->scope = NULL; // always share immediates - cn->arraysize = 1; + cn->arraysize = 0; -// copy the immediate to the global area - cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]); + if (!value) + G_INT(cn->ofs) = 0; + else + { + // 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 *QCC_MakeVectorConst(float a, float b, float c) { QCC_def_t *cn; @@ -3755,7 +3895,7 @@ QCC_def_t *QCC_MakeVectorDef(float a, float b, float c) cn->constant = true; cn->initialized = 1; cn->scope = NULL; // always share immediates - cn->arraysize = 1; + cn->arraysize = 0; // copy the immediate to the global area cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_vector->type]); @@ -3767,8 +3907,8 @@ QCC_def_t *QCC_MakeVectorDef(float a, float b, float c) return cn; } -hashtable_t floatconstdefstable; -QCC_def_t *QCC_MakeFloatDef(float value) +extern hashtable_t floatconstdefstable; +QCC_def_t *QCC_MakeFloatConst(float value) { QCC_def_t *cn; @@ -3796,7 +3936,7 @@ QCC_def_t *QCC_MakeFloatDef(float value) cn->constant = true; cn->initialized = 1; cn->scope = NULL; // always share immediates - cn->arraysize = 1; + cn->arraysize = 0; // copy the immediate to the global area cn->ofs = QCC_GetFreeOffsetSpace (type_size[type_integer->type]); @@ -3809,56 +3949,66 @@ QCC_def_t *QCC_MakeFloatDef(float value) return cn; } -extern hashtable_t stringconstdefstable; -extern hashtable_t stringconstdefstable_dotranslate; -QCC_def_t *QCC_MakeStringDef(char *value) +extern hashtable_t stringconstdefstable, stringconstdefstable_trans; +int dotranslate_count; +static QCC_def_t *QCC_MakeStringConstInternal(char *value, pbool translate) { QCC_def_t *cn; int string; - hashtable_t *tbl = dotranslate ? &stringconstdefstable_dotranslate : &stringconstdefstable; - char buf[64]; - cn = pHash_Get(tbl, value); + cn = pHash_Get(translate?&stringconstdefstable_trans:&stringconstdefstable, value); if (cn) return cn; // allocate a new one - cn = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + if(translate) + { + char buf[64]; + sprintf(buf, "dotranslate_%i", ++dotranslate_count); + cn = (void *)qccHunkAlloc (sizeof(QCC_def_t) + strlen(buf)+1); + cn->name = (char*)(cn+1); + strcpy(cn->name, buf); + } + else + { + cn = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + cn->name = "IMMEDIATE"; + } cn->next = NULL; pr.def_tail->next = cn; pr.def_tail = cn; cn->type = type_string; - if(dotranslate > 0) - { - sprintf(buf, "dotranslate_%d", ++dotranslate_count); - cn->name = strdup(buf); - } - else - cn->name = "IMMEDIATE"; cn->constant = true; cn->initialized = 1; cn->scope = NULL; // always share immediates - cn->arraysize = 1; + cn->arraysize = 0; // 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))); + pHash_Add(translate?&stringconstdefstable_trans:&stringconstdefstable, strings+string, cn, qccHunkAlloc(sizeof(bucket_t))); G_INT(cn->ofs) = string; - return cn; } -QCC_type_t *QCC_PR_NewType (char *name, int basictype); +QCC_def_t *QCC_MakeStringConst(char *value) +{ + return QCC_MakeStringConstInternal(value, false); +} +QCC_def_t *QCC_MakeTranslateStringConst(char *value) +{ + return QCC_MakeStringConstInternal(value, true); +} + QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type) { QCC_type_t *newtype; - newtype = QCC_PR_NewType("POINTER TYPE", ev_pointer); + newtype = QCC_PR_NewType("ptr", ev_pointer, false); newtype->aux_type = type; return newtype; } @@ -3938,7 +4088,7 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas) f = QCC_MemberInParentClass(mt->name, clas->parentclass); if (f) { - if (m->arraysize>1) + if (m->arraysize) QCC_Error(ERR_INTERNAL, "FTEQCC does not support overloaded arrays of members"); a=0; for (o = 0; o < m->type->size; o++) @@ -3946,16 +4096,20 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas) continue; } - for (a = 0; a < m->arraysize; a++) + for (a = 0; a < (m->arraysize?m->arraysize:1); a++) { + /*if it was already set, don't go recursive and generate 500 fields for a one-member class that was intheritted from 500 times*/ + if (((int *)qcc_pr_globals)[o+a*mt->size+m->ofs]) + continue; + //we need the type in here so saved games can still work without saving ints as floats. (would be evil) - ft = QCC_PR_NewType(basictypenames[mt->type], ev_field); - ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type); + ft = QCC_PR_NewType(basictypenames[mt->type], ev_field, false); + ft->aux_type = QCC_PR_NewType(basictypenames[mt->type], mt->type, false); ft->aux_type->aux_type = type_void; ft->size = ft->aux_type->size; 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); + f = QCC_PR_GetDef(ft, membername, NULL, true, 0, 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]; @@ -3994,7 +4148,7 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_ if (type->type == ev_function) //FIXME: inheritance will not install all the member functions. { sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, type->name); - member = QCC_PR_GetDef(NULL, membername, NULL, false, 1, false); + member = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); if (!member) { QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername); @@ -4006,7 +4160,7 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_ } point = QCC_PR_Statement(&pr_opcodes[OP_ADDRESS], ed, member, NULL); sprintf(membername, "%s::%s", clas->name, type->name); - virt = QCC_PR_GetDef(type, membername, NULL, false, 1, false); + virt = QCC_PR_GetDef(type, membername, NULL, false, 0, false); QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL); } } @@ -4029,6 +4183,8 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) if (!basetype) QCC_PR_ParseError(ERR_INTERNAL, "Type %s was not defined...", tname); + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); pr_scope = NULL; memset(basictypefield, 0, sizeof(basictypefield)); @@ -4052,7 +4208,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) G_FUNCTION(scope->ofs) = df - functions; //locals here... - ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 1, false); + ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 0, false); virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false); if (!virt) @@ -4069,7 +4225,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) if (constructor) { //self = ent; self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false); - oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 1, false); + oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 0, false); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL)); //return to our old self. boom boom. QCC_PR_SimpleStatement(OP_CALL0, constructor->ofs, 0, 0, false); @@ -4088,684 +4244,480 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) locals_end = numpr_globals + basetype->size; df->locals = locals_end - df->parm_start; } -/* -============ -PR_ParseValue -Returns the global ofs for the current token -============ -*/ -QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) +QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) { - QCC_def_t *ao=NULL; //arrayoffset - QCC_def_t *d, *nd, *od; - char *name; + QCC_type_t *t; + QCC_def_t *idx; + QCC_def_t *tmp; QCC_dstatement_t *st; - int i; - static QCC_def_t intrinsic = { - NULL, // QCC_type_t *type; - NULL, // char *name; - NULL, // struct QCC_def_s *next; - NULL, // struct QCC_def_s *nextlocal; //provides a chain of local variables for the opt_locals_marshalling optimisation. - 0, // gofs_t ofs; - NULL, // struct QCC_def_s *scope; // function the var was defined in, or NULL - 1, // int initialized; // 1 when a declaration included "= immediate" - 1, // int constant; // 1 says we can use the value over and over again - 1, // int references; - 0, // int timescalled; //part of the opt_stripfunctions optimisation. - 0, // int s_file; - 0, // int s_line; - 0, // int arraysize; - 0, // pbool shared; - 0, // pbool saved; - 0, // pbool isstatic; - NULL // temp_t *temp; - }; + pbool allowarray; - char membername[2048]; + t = d->type; + idx = NULL; + while(1) + { + allowarray = false; + if (idx) + allowarray = t->arraysize>0; + else if (!idx) + { + allowarray = d->arraysize || + (d->type->type == ev_pointer) || + (d->type->type == ev_string) || + (d->type->type == ev_vector); + } -// if the token is an immediate, allocate a constant for it - if (pr_token_type == tt_immediate) - return QCC_PR_ParseImmediate (); + if (allowarray && QCC_PR_CheckToken("[")) + { + tmp = QCC_PR_Expression (TOP_PRIORITY, 0); + QCC_PR_Expect("]"); - if (QCC_PR_CheckToken("[")) //reacc support - { //looks like a funky vector. :) - vec3_t v; - pr_immediate_type = type_vector; - v[0] = pr_immediate._float; - QCC_PR_Lex(); - v[1] = pr_immediate._float; - QCC_PR_Lex(); - v[2] = pr_immediate._float; - pr_immediate.vector[0] = v[0]; - pr_immediate.vector[1] = v[1]; - pr_immediate.vector[2] = v[2]; - pr_immediate_type = type_vector; - d = QCC_PR_ParseImmediate(); - QCC_PR_Expect("]"); - return d; - } - name = QCC_PR_ParseName (); - - if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar' - { //try getting a member. - QCC_type_t *type; - type = assumeclass; - d = NULL; - while(type != type_entity && type) - { - sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); - od = d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); - if (d) - break; - - type = type->parentclass; - } - if (!d) - od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); - } - else - -// look through the defs - od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); + /*if its a pointer that got dereferenced, follow the type*/ + if (!idx && t->type == ev_pointer && !d->arraysize) + t = t->aux_type; - if (!d) - { - if ( (!strcmp(name, "random" )) || - (!strcmp(name, "randomv")) || - (!strcmp(name, "entnum")) || - (!strcmp(name, "_")) ) //intrinsics, any old function with no args will do. - { - intrinsic.name = name; - intrinsic.type = type_function; // can't put that in the static var - od = d = &intrinsic; - } - else if (keyword_class && !strcmp(name, "this")) - { - if (!pr_classtype) - QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n"); - od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false); - od = d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false); - } - else if (keyword_class && !strcmp(name, "super")) - { - if (!pr_classtype) - QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n"); - od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false); - od = d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false); - } - else - { - od = d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false); - if (!d) - QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name); - else + if (!idx && d->type->type == ev_pointer) { - QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name); + /*no bounds checks on pointer dereferences*/ } - } - } - -reloop: - - -//FIXME: Make this work with double arrays/2nd level structures. -//Should they just jump back to here? - if (QCC_PR_CheckToken("[")) - { - QCC_type_t *newtype; - if (ao) - { - 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. + else if (!idx && d->type->type == ev_string && !d->arraysize) { - 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 - else if (ao->type->type == ev_float) - nd = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], nd, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part - else + /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/ + } + else if (!idx && d->type->type == ev_vector && !d->arraysize) + { + if (tmp->constant) { - QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); - nd = NULL; + unsigned int i; + if (tmp->type->type == ev_integer) + i = G_INT(tmp->ofs); + else if (tmp->type->type == ev_float) + i = G_FLOAT(tmp->ofs); + if (i < 0 || i >= 3) + QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds"); } + else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) + { + tmp = QCC_SupplyConversion(tmp, ev_integer, true); + QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false); + } + t = type_float; } - - if (nd->type->type == ao->type->type) + else if (!((!idx)?d->arraysize:t->arraysize)) { - if (ao->type->type == ev_integer) - ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part - else if (ao->type->type == ev_float) - ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], ao, nd, NULL); //get add part - else + QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array"); + } + else if (tmp->constant) + { + unsigned int i; + if (tmp->type->type == ev_integer) + i = G_INT(tmp->ofs); + else if (tmp->type->type == ev_float) + i = G_FLOAT(tmp->ofs); + if (i < 0 || i >= ((!idx)?d->arraysize:t->arraysize)) + QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds"); + } + else + { + if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) { - QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); - nd = NULL; + tmp = QCC_SupplyConversion(tmp, ev_integer, true); + QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false); } } - else + if (t->size != 1 && (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))) /*don't multiply by type size if the instruction/emulation will do that instead*/ { - if (nd->type->type == ev_float) - nd = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], nd, 0, NULL); - ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part + if (tmp->type->type == ev_float) + tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL); + else + tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL); } - newtype = d->type; - d = od; + /*calc the new index*/ + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL); + else + idx = tmp; } - else + else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))) { - ao = QCC_PR_Expression (TOP_PRIORITY, 0); - QCC_PR_Expect("]"); + if (!idx && t->type == ev_pointer && !d->arraysize) + t = t->aux_type; - if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1) //we need to multiply it to find the offset. + for (t = t->param; t; t = t->next) { - if (ao->type->type == ev_integer) - ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(d->type->size), NULL); //get add part - else if (ao->type->type == ev_float) - ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], ao, QCC_MakeFloatDef((float)d->type->size), NULL); //get add part - else + if (QCC_PR_CheckName(t->name)) { - nd = NULL; - QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); + break; } + } + if (!t) + QCC_PR_ParseError(0, "%s is not a member", pr_token); - newtype = d->type; + tmp = QCC_MakeIntConst(t->ofs); + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); + else + idx = tmp; } - if (ao->type->type == ev_integer) + else + break; + } + + if (idx) + { + if (d->type->type == ev_pointer) { - switch(newtype->type) + switch (t->type) { + case ev_pointer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def. + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_integer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_string: - if (d->arraysize <= 1) - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = nd->type;//don't be fooled - } - else - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def. - } + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def. + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_entity: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def. + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_field: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def. + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def. - nd->type = d->type; + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_struct: + case ev_union: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; + + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + } + d->type = t; + } + else if (d->type->type == ev_string && d->arraysize == 0) + { + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL); + } + else if (d->type->type == ev_vector && d->arraysize == 0) + { + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + d->type = type_float; + } + else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) + { + /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/ + /*source type is a struct, or its an array, or something that can otherwise be directly accessed*/ + switch(t->type) + { case ev_pointer: - if (ao->constant && !G_INT(ao->ofs)) - ao->ofs = 0; - if (d->arraysize>1) //use the array - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - } - else - { //dereference the pointer. - switch(newtype->aux_type->type) - { - case ev_pointer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_field: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; case ev_struct: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - nd->type = d->type; + case ev_union: + //FIXME... + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_STRUCT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); break; default: QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; } - d=nd; + d->type = t; } - else if (ao->type->type == ev_float) + else if (idx->constant) { - if (qcc_targetformat == QCF_HEXEN2) - { //hexen2 style retrieval, mixed with q1 style assignments... - if (QCC_PR_CheckToken("=")) //(hideous concept) - { - QCC_def_t *funcretr; - QCC_def_t *args[2]; - if (d->scope) - QCC_PR_ParseError(0, "Scoped array without specific engine support"); - - funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); - nd = QCC_PR_Expression(TOP_PRIORITY, 0); - if (nd->type->type != d->type->type) - QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - - args[0] = ao; - args[1] = nd; - return QCC_PR_GenerateFunctionCall(funcretr, args, 2); - } - - switch(newtype->type) - { - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; - break; - case ev_string: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; - break; - case ev_entity: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; - break; - case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - QCC_FreeTemp(d); - QCC_FreeTemp(ao); + int cidx; + idx = QCC_SupplyConversion(idx, ev_integer, true); + cidx = G_INT(idx->ofs); - d=nd; - d->type = newtype; - return d; - } - else - { - if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //q1 compatible. - { //you didn't see this, okay? - QCC_def_t *funcretr; - if (d->scope) - QCC_PR_ParseError(0, "Scoped array without specific engine support"); + d->references++; + tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memcpy (tmp, d, sizeof(QCC_def_t)); + tmp->arraysize = 0; + tmp->ofs = d->ofs + (cidx * type_size[d->type->type]); + d = tmp; - if (allowarrayassign && QCC_PR_CheckToken("=")) - { - QCC_def_t *args[2]; + //d can be assigned to freely + } + else if (allowarrayassign && QCC_PR_CheckToken("=")) + { + /*if its assigned to, generate a functioncall to do the store*/ + QCC_def_t *args[2], *funcretr, *rhs; - funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); + d->references++; + funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 0, false); - nd = QCC_PR_Expression(TOP_PRIORITY, 0); - if (nd->type->type != d->type->type) - QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); + rhs = QCC_PR_Expression(TOP_PRIORITY, 0); + if (rhs->type->type != d->type->type) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - args[0] = ao; - args[1] = nd; - qcc_usefulstatement=true; - nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2); - nd->type = d->type->aux_type; - } - else - { - QCC_def_t *args[1]; - - def_parms[0].type = type_float; - funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); + args[0] = QCC_SupplyConversion(idx, ev_float, true); + args[1] = rhs; + qcc_usefulstatement=true; + d = QCC_PR_GenerateFunctionCall(funcretr, args, 2); + d->type = t; - args[0] = ao; - nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1); - nd->type = d->type->aux_type; - } - } - else - { - switch(newtype->type) - { - case ev_pointer: - if (d->arraysize>1) //use the array - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - } - else - { //dereference the pointer. - switch(newtype->aux_type->type) - { - case ev_pointer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } - break; + return d; + } + else if (QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F])) + { + if (!d->arraysize) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on non-array"); - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_string: - if (d->arraysize <= 1) - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, ao, NULL); //get pointer to precise def. - newtype = nd->type;//don't be fooled - } - else - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_vector: - 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. - 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. - break; - case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; + if (d->temp) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "array lookup on a temp"); - case ev_struct: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } + /*hexen2 format has opcodes to read arrays (but has no way to write)*/ + switch(t->type) + { + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. +// st->a = d->ofs; + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. +// st->a = d->ofs; + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. +// st->a = d->ofs; + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. +// st->a = d->ofs; + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. +// st->a = d->ofs; + break; + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + d = NULL; + break; } - d=nd; + d->type = t; } else - QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); - - d->type = newtype; - goto reloop; - } + { + /*emulate the array access using a function call to do the read for us*/ + QCC_def_t *args[1], *funcretr; + d->references++; - i = d->type->type; - if (i == ev_pointer) - { - int j; - QCC_type_t *type; - if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")) - { - for (i = d->type->num_parms, type = d->type+1; i; i--, type++) - { - if (QCC_PR_CheckName(type->name)) - { - //give result - if (ao) - { - numstatements--; //remove the last statement - d = od; + /*make sure the function type that we're calling exists*/ + def_parms[0].type = type_float; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false); - nd = QCC_MakeIntDef(type->ofs); - ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part + args[0] = QCC_SupplyConversion(idx, ev_float, true); + d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + d->type = t; + } - //so that we may offset it and readd it. - } - else - ao = QCC_MakeIntDef(type->ofs); - switch (type->type) - { - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def. - break; - case ev_string: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, ao, NULL); //get pointer to precise def. - break; - case ev_vector: - 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. - break; - case ev_field: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, ao, NULL); //get pointer to precise def. - break; - case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, ao, NULL); //get pointer to precise def. - nd->type = type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. - break; + /*parse recursively*/ + d = QCC_PR_ParseArrayPointer(d, allowarrayassign); + } -// case ev_struct: - //no suitable op. -// nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. -// nd->type = type; -// break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } + return d; +} - d=nd; - break; - } - if (type->num_parms) - { - 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); +/* +============ +PR_ParseValue - goto reloop; - } - } - else if (i == ev_struct || i == ev_union) - { - int j; - QCC_type_t *type; - if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")) - { - for (i = d->type->num_parms, type = d->type+1; i; i--, type++) - { - if (QCC_PR_CheckName(type->name)) - { - //give result - if (ao) - { - numstatements--; //remove the last statement - d = od; +Returns the global ofs for the current token +============ +*/ +QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) +{ + QCC_def_t *d, *od, *tmp; + QCC_type_t *t; + char *name; - nd = QCC_MakeIntDef(type->ofs); - ao = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], ao, nd, NULL); //get add part + char membername[2048]; - //so that we may offset it and readd it. - } - else - ao = QCC_MakeIntDef(type->ofs); - switch (type->type) - { - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def. - break; - case ev_string: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def. - break; - case ev_vector: - 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. - break; - case ev_field: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def. - break; - case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def. - nd->type = type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - break; +// if the token is an immediate, allocate a constant for it + if (pr_token_type == tt_immediate) + return QCC_PR_ParseImmediate (); -// case ev_struct: - //no suitable op. -// nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. -// nd->type = type; -// break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } + if (QCC_PR_CheckToken("[")) //reacc support + { //looks like a funky vector. :) + vec3_t v; + pr_immediate_type = type_vector; + v[0] = pr_immediate._float; + QCC_PR_Lex(); + v[1] = pr_immediate._float; + QCC_PR_Lex(); + v[2] = pr_immediate._float; + pr_immediate.vector[0] = v[0]; + pr_immediate.vector[1] = v[1]; + pr_immediate.vector[2] = v[2]; + pr_immediate_type = type_vector; + d = QCC_PR_ParseImmediate(); + QCC_PR_Expect("]"); + return d; + } + name = QCC_PR_ParseName (); - d=nd; - break; - } - if (type->num_parms) - { - 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); + if (assumeclass && assumeclass->parentclass) // 'testvar' becomes 'self::testvar' + { //try getting a member. + QCC_type_t *type; + type = assumeclass; + d = NULL; + while(type != type_entity && type) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + if (d) + break; - goto reloop; + type = type->parentclass; } + if (!d) + d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); + } + else + { + // look through the defs + d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); } -/* if (d->type->type == ev_pointer) - { //expand now, not in function call/maths parsing - switch(d->type->aux_type->type) + if (!d) + { + if ( (!strcmp(name, "random" )) || + (!strcmp(name, "randomv")) || + (!strcmp(name, "sizeof")) || + (!strcmp(name, "entnum")) || + (!strcmp(name, "_"))) //intrinsics, any old function with no args will do. { - case ev_string: - d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, NULL, NULL); - break; - case ev_float: - d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, NULL, NULL); - break; + d = QCC_PR_GetDef (type_function, name, NULL, true, 0, false); + d->initialized = 0; + } + else if (keyword_class && !strcmp(name, "this")) + { + if (!pr_classtype) + QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n"); + od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false); + d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 0, od->ofs, true, false); + } + else if (keyword_class && !strcmp(name, "super")) + { + if (!pr_classtype) + QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n"); + od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false); + d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 0, od->ofs, true, false); + } + else + { + d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 0, false); + if (!d) + QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name); + else + { + QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Unknown value \"%s\".", name); + } } } -*/ - if (!keyword_class) - return d; - if (d->type->parentclass||d->type->type == ev_entity) //class + d = QCC_PR_ParseArrayPointer(d, allowarrayassign); + + t = d->type; + if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))) { - if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")) + QCC_def_t *field; + if (QCC_PR_CheckToken("(")) { - QCC_def_t *field; - if (QCC_PR_CheckToken("(")) + field = QCC_PR_Expression(TOP_PRIORITY, 0); + QCC_PR_Expect(")"); + } + else + field = QCC_PR_ParseValue(d->type, false); + if (field->type->type == ev_field) + { + if (!field->type->aux_type) { - field = QCC_PR_Expression(TOP_PRIORITY, 0); - QCC_PR_Expect(")"); + QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type"); + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL); } else - field = QCC_PR_ParseValue(d->type, false); - if (field->type->type == ev_field) - { - if (!field->type->aux_type) - { - QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type"); - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL); - } - else - { - switch(field->type->aux_type->type) - { - default: - QCC_PR_ParseError(ERR_INTERNAL, "Bad field type"); - return d; - case ev_integer: - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL); - 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)); - nd->type = field->type->aux_type; - nd->ofs = d->ofs; - nd->temp = d->temp; - nd->constant = false; - nd->name = d->name; - return nd; - case ev_float: - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL); - case ev_string: - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL); - case ev_vector: - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL); - case ev_function: - { //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)); - nd->type = field->type->aux_type; - nd->ofs = d->ofs; - nd->temp = d->temp; - nd->constant = false; - nd->name = d->name; - return nd; - - } - case ev_entity: - return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL); - } + { + switch(field->type->aux_type->type) + { + default: + QCC_PR_ParseError(ERR_INTERNAL, "Bad field type"); + break; + case ev_integer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL); + break; + case ev_field: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL); + tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (tmp, 0, sizeof(QCC_def_t)); + tmp->type = field->type->aux_type; + tmp->ofs = d->ofs; + tmp->temp = d->temp; + tmp->constant = false; + tmp->name = d->name; + d = tmp; + break; + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL); + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL); + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL); + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL); + tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (tmp, 0, sizeof(QCC_def_t)); + tmp->type = field->type->aux_type; + tmp->ofs = d->ofs; + tmp->temp = d->temp; + tmp->constant = false; + tmp->name = d->name; + d = tmp; + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL); + break; } } - else - QCC_PR_IncludeChunk(".", false, NULL); } + else + QCC_PR_IncludeChunk(".", false, NULL); } return d; @@ -4794,10 +4746,10 @@ QCC_def_t *QCC_PR_Term (void) switch (e->type->type) { case ev_integer: - QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false); break; case ev_float: - QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false); break; default: QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "++ operator on unsupported type"); @@ -4816,10 +4768,10 @@ QCC_def_t *QCC_PR_Term (void) switch (e->type->type) { case ev_integer: - QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false); break; case ev_float: - QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false); break; default: QCC_PR_ParseError(ERR_BADPLUSPLUSOPERATOR, "-- operator on unsupported type"); @@ -4857,18 +4809,30 @@ QCC_def_t *QCC_PR_Term (void) else if (QCC_PR_CheckToken ("&")) { int st = numstatements; - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); t = e->type->type; if (st != numstatements) //woo, something like ent.field? { - if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) + if ((OP_LOAD_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOAD_FNC) || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) { statements[numstatements-1].op = OP_ADDRESS; e->type = QCC_PR_PointerType(e->type); return e; } + else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I) + { + statements[numstatements-1].op = OP_GLOBALADDRESS; + e->type = QCC_PR_PointerType(e->type); + return e; + } + else if (OP_LOADP_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADP_I) + { + statements[numstatements-1].op = OP_POINTER_ADD; + e->type = QCC_PR_PointerType(e->type); + return e; + } else //this is a restriction that could be lifted, I just want to make sure that I got all the bits first. { QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference"); @@ -4886,62 +4850,65 @@ QCC_def_t *QCC_PR_Term (void) } else if (QCC_PR_CheckToken ("*")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); t = e->type->type; - if (t != ev_pointer) - QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *"); - - switch(e->type->aux_type->type) + if (t == ev_string) + e2 = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], e, QCC_MakeFloatConst(0), NULL); + else if (t == ev_pointer) { - case ev_float: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL); - break; - case ev_string: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL); - break; - case ev_vector: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL); - break; - case ev_entity: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL); - break; - case ev_field: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL); - break; - case ev_function: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL); - break; - case ev_integer: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL); - break; - case ev_pointer: - e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL); - break; + switch(e->type->aux_type->type) + { + case ev_float: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_F], e, 0, NULL); + break; + case ev_string: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_S], e, 0, NULL); + break; + case ev_vector: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_V], e, 0, NULL); + break; + case ev_entity: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_ENT], e, 0, NULL); + break; + case ev_field: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL); + break; + case ev_function: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_FLD], e, 0, NULL); + break; + case ev_integer: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL); + break; + case ev_pointer: + e2 = QCC_PR_Statement (&pr_opcodes[OP_LOADP_I], e, 0, NULL); + break; - default: - QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)"); - e2 = NULL; - break; + default: + QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for * (unrecognised type)"); + e2 = NULL; + break; + } + e2->type = e->type->aux_type; } - - e2->type = e->type->aux_type; + else + QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for *"); return e2; } else if (QCC_PR_CheckToken ("-")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); switch(e->type->type) { case ev_float: - e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatDef(0), e, NULL); + e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_F], QCC_MakeFloatConst(0), e, NULL); break; case ev_vector: - e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorDef(0, 0, 0), e, NULL); + e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_V], QCC_MakeVectorConst(0, 0, 0), e, NULL); break; case ev_integer: - e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntDef(0), e, NULL); + e2 = QCC_PR_Statement (&pr_opcodes[OP_SUB_I], QCC_MakeIntConst(0), e, NULL); break; default: QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for -"); @@ -4952,7 +4919,7 @@ QCC_def_t *QCC_PR_Term (void) } else if (QCC_PR_CheckToken ("+")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); switch(e->type->type) { @@ -4975,7 +4942,72 @@ QCC_def_t *QCC_PR_Term (void) if (QCC_PR_CheckToken ("(")) { - if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts + QCC_type_t *newtype; + newtype = QCC_PR_ParseType(false, true); + if (newtype) + { + QCC_PR_Expect (")"); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); + + /*you may cast from a type to itself*/ + if (!typecmp(e->type, newtype)) + { + } + /*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/ + else if (newtype->size == e->type->size && (e->type->type == ev_integer || e->type->type == ev_float) && e->constant && !G_INT(e->ofs)) + { + //direct cast + e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (e2, 0, sizeof(QCC_def_t)); + + e2->type = newtype; + e2->ofs = e->ofs; + e2->constant = true; + e2->temp = e->temp; + return e2; + } + /*cast from int->float will convert*/ + else if (newtype->type == ev_float && e->type->type == ev_integer) + return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL); + /*cast from float->int will convert*/ + else if (newtype->type == ev_integer && e->type->type == ev_float) + return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL); + /*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/ + else if ( + //pointers + ((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer)) + //ents/classs + || (newtype->type == ev_entity && e->type->type == ev_entity) + //variants are fine too + || (newtype->type == ev_variant || e->type->type == ev_variant) + ) + { + //direct cast + e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (e2, 0, sizeof(QCC_def_t)); + + e2->type = newtype; + e2->ofs = e->ofs; + e2->constant = true; + e2->temp = e->temp; + return e2; + } + else + QCC_PR_ParseError(0, "Bad type cast\n"); + } +/* else if (QCC_PR_CheckToken("*")) + { + QCC_PR_Expect (")"); + e = QCC_PR_Term(); + e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (e2, 0, sizeof(QCC_def_t)); + e2->type = type_pointer; + e2->ofs = e->ofs; + e2->constant = true; + e2->temp = e->temp; + return e2; + } + else if (QCC_PR_CheckKeyword(keyword_float, "float")) //check for type casts { QCC_PR_Expect (")"); e = QCC_PR_Term(); @@ -5036,7 +5068,7 @@ QCC_def_t *QCC_PR_Term (void) else QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast"); } - else +*/ else { pbool oldcond = conditional; conditional = conditional?2:0; @@ -5068,6 +5100,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to) } } + if (from->type->type == ev_variant) + return 3; + /* if (from->type->type == ev_pointer && from->type->aux_type->type == to) return 1; @@ -5077,6 +5112,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to) if (from->type->type == ev_integer && to == ev_function) return 1; + if (from->constant && from->arraysize == 0 && (from->type->type == ev_integer || from->type->type == ev_float) && !G_INT(from->ofs)) + return 2; + return -100; } /* @@ -5105,7 +5143,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) while (1) { - if (priority == 1) + if (priority == FUNC_PRIORITY) { if (QCC_PR_CheckToken ("(") ) { @@ -5141,8 +5179,8 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) if (pr_token_type == tt_immediate) { - if (pr_immediate_type->type == ev_float) - if (pr_immediate._float < 0) //hehehe... was a minus all along... + if ((pr_immediate_type->type == ev_float && pr_immediate._float < 0) || + (pr_immediate_type->type == ev_integer && pr_immediate._int < 0)) //hehehe... was a minus all along... { QCC_PR_IncludeChunk(pr_token, true, NULL); strcpy(pr_token, "+");//two negatives would make a positive. @@ -5189,21 +5227,15 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) //this kills the add 0. e->ofs = statements[numstatements-1].a; numstatements--; - - if (e->type->type != ev_pointer) - { - type_pointer->aux_type->type = e->type->type; - e->type = type_pointer; - } } else { - statements[numstatements-1].op = OP_ADD_I; - if (e->type->type != ev_pointer) - { - type_pointer->aux_type->type = e->type->type; - e->type = type_pointer; - } + statements[numstatements-1].op = OP_POINTER_ADD; + } + if (e->type != type_pointer) + { + type_pointer->aux_type->type = e->type->type; + e->type = type_pointer; } } if ( !simplestore && statements[numstatements-1].op == OP_LOADP_C && e->ofs == statements[numstatements-1].c) @@ -5271,6 +5303,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) {//assignment if (op->type_a == &type_pointer) //ent var { + /*FIXME: I don't like this code*/ if (e->type->type != ev_pointer) c = -200; //don't cast to a pointer. else if ((*op->type_c)->type == ev_void && op->type_b == &type_pointer && e2->type->type == ev_pointer) @@ -5285,6 +5318,8 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) c=QCC_canConv(e2, (*op->type_b)->type); if (type_a != (*op->type_a)->type) //in this case, a is the final assigned value c = -300; //don't use this op, as we must not change var b's type + else if ((*op->type_a)->type == ev_pointer && e->type->aux_type->type != (*op->type_a)->aux_type->type) + c = -300; //don't use this op if its a pointer to a different type } } else @@ -5404,12 +5439,12 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false); if (e->type->type == ev_float) { - QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e2, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e2, false); QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false); } else if (e->type->type == ev_integer) { - QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e2, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e2, false); QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false); } else @@ -5430,7 +5465,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) e2 = QCC_GetTemp(type_float); QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false); - QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_F], e, QCC_MakeFloatConst(1), e, false); QCC_FreeTemp(e); e = e2; } @@ -5441,7 +5476,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) e2 = QCC_GetTemp(type_integer); QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false); - QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_ADD_I], e, QCC_MakeIntConst(1), e, false); QCC_FreeTemp(e); e = e2; } @@ -5466,12 +5501,12 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) QCC_PR_SimpleStatement(OP_ADDRESS, statements[numstatements-1].a, statements[numstatements-1].b, e3->ofs, false); if (e->type->type == ev_float) { - QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e2, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e2, false); QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], e2, e3, NULL, false); } else if (e->type->type == ev_integer) { - QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e2, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e2, false); QCC_PR_Statement3(&pr_opcodes[OP_STOREP_I], e2, e3, NULL, false); } else @@ -5489,7 +5524,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) e2 = QCC_GetTemp(type_float); QCC_PR_Statement3(&pr_opcodes[OP_STORE_F], e, e2, NULL, false); - QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_F], e, QCC_MakeFloatConst(1), e, false); QCC_FreeTemp(e); e = e2; } @@ -5500,7 +5535,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) e2 = QCC_GetTemp(type_integer); QCC_PR_Statement3(&pr_opcodes[OP_STORE_I], e, e2, NULL, false); - QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntDef(1), e, false); + QCC_PR_Statement3(&pr_opcodes[OP_SUB_I], e, QCC_MakeIntConst(1), e, false); QCC_FreeTemp(e); e = e2; } @@ -5519,13 +5554,36 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (",")) { + if (!qcc_usefulstatement) + QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement"); + QCC_FreeTemp(e); - return QCC_PR_Expression(TOP_PRIORITY, exprflags); + qcc_usefulstatement = false; + e = QCC_PR_Expression(TOP_PRIORITY, exprflags); } return e; } +int QCC_PR_IntConstExpr(void) +{ + QCC_def_t *def = QCC_PR_Expression(TOP_PRIORITY, 0); + if (def->constant) + { + def->references++; + if (def->type->type == ev_integer) + return G_INT(def->ofs); + if (def->type->type == ev_float) + { + int i = G_FLOAT(def->ofs); + if ((float)i == G_FLOAT(def->ofs)) + return i; + } + } + QCC_PR_ParseError(ERR_NOTACONSTANT, "Value is not an integer constant"); + return true; +} + void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname) { if (num_gotos >= max_gotos) @@ -5606,7 +5664,7 @@ void QCC_PR_ParseStatement (void) { e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0); e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0); - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL)); }*/ if (QCC_PR_CheckToken (";")) @@ -5620,7 +5678,7 @@ void QCC_PR_ParseStatement (void) return; } e = QCC_PR_Expression (TOP_PRIORITY, 0); - e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type); + e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type, true); if (e != e2) { QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); @@ -5902,7 +5960,7 @@ void QCC_PR_ParseStatement (void) float frame = pr_immediate._float; QCC_PR_Lex(); name = QCC_PR_ParseName(); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatDef(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STATE], QCC_MakeFloatConst(frame), QCC_PR_GetDef(type_function, name, NULL, false, 0, false), NULL)); QCC_PR_Expect(";"); return; } @@ -6116,7 +6174,7 @@ void QCC_PR_ParseStatement (void) if (pr_casesdef[i]->type->type != e->type->type) { if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float) - pr_casesdef[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef[i]->ofs]); + pr_casesdef[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef[i]->ofs]); else QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch case type mismatch"); } @@ -6125,7 +6183,7 @@ void QCC_PR_ParseStatement (void) if (pr_casesdef2[i]->type->type != e->type->type) { if (e->type->type == ev_integer && pr_casesdef[i]->type->type == ev_float) - pr_casesdef2[i] = QCC_MakeIntDef((int)qcc_pr_globals[pr_casesdef2[i]->ofs]); + pr_casesdef2[i] = QCC_MakeIntConst((int)qcc_pr_globals[pr_casesdef2[i]->ofs]); else QCC_PR_ParseWarning(WARN_SWITCHTYPEMISMATCH, "switch caserange type mismatch"); } @@ -6496,7 +6554,7 @@ void QCC_PR_ParseState (void) frame = QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], self, framef, NULL); if (cycle_wrapped) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(0), cycle_wrapped, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(0), cycle_wrapped, NULL)); QCC_UnFreeTemp(frame); //make sure the frame is within the bounds given. @@ -6513,25 +6571,25 @@ void QCC_PR_ParseState (void) 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); + QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, 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); if (cycle_wrapped) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatDef(1), cycle_wrapped, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(1), cycle_wrapped, NULL)); 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); + QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatConst(1)->ofs, frame->ofs, 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)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(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)); @@ -6550,7 +6608,7 @@ void QCC_PR_ParseState (void) name = QCC_PR_ParseName (); pr_scope = NULL; - def = QCC_PR_GetDef (type_function, name, NULL, true, 1, false); + def = QCC_PR_GetDef (type_function, name, NULL, true, 0, false); pr_scope = sc; QCC_PR_Expect ("]"); @@ -7109,6 +7167,7 @@ void QCC_Marshal_Locals(int first, int laststatement) { QCC_def_t *local; unsigned int newofs; + int size; // if (!opt_overlaptemps) //clear these after each function. we arn't overlapping them so why do we need to keep track of them? // { @@ -7144,9 +7203,11 @@ void QCC_Marshal_Locals(int first, int laststatement) if (local->constant) continue; - newofs += local->type->size*local->arraysize; - if (local->arraysize>1) - newofs++; + size = local->type->size*(local->arraysize?local->arraysize:1); + if (local->arraysize) + size++; + + newofs += size; } locals_start = MAX_REGS; @@ -7163,12 +7224,14 @@ void QCC_Marshal_Locals(int first, int laststatement) if (((int*)qcc_pr_globals)[local->ofs]) QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value"); - newofs -= local->type->size*local->arraysize; - if (local->arraysize>1) - newofs--; + size = local->type->size*(local->arraysize?local->arraysize:1); + if (local->arraysize) + size++; + + newofs -= size; - QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+local->type->size*local->arraysize, newofs); - QCC_FreeOffset(local->ofs, local->type->size*local->arraysize); + QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+size, newofs); + QCC_FreeOffset(local->ofs, size); local->ofs = newofs; } @@ -7203,9 +7266,9 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir break; } if (param) - fprintf(asmfile, "%s %s /* at %d */", TypeName(type), param->name, o); + fprintf(asmfile, "%s %s", TypeName(type), param->name); else - fprintf(asmfile, "%s /* at %d */", TypeName(type), o); + fprintf(asmfile, "%s", TypeName(type)); o += type->size; } @@ -7250,7 +7313,7 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir } } } - fprintf(asmfile, ";\n"); + fprintf(asmfile, "; /*%i*/\n", statement_linenums[i]); } fprintf(asmfile, "}\n\n"); @@ -7334,7 +7397,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) { if (!*pr_parm_names[i]) QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named"); - defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 1, false); + defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 0, false); defs[i]->references++; if (i < MAX_PARMS) @@ -7379,9 +7442,9 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) /*if (pr_classtype) { QCC_def_t *e, *e2; - e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 1); - e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 1); - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), e, NULL)); + e = QCC_PR_GetDef(pr_classtype, "__oself", pr_scope, true, 0); + e2 = QCC_PR_GetDef(type_entity, "self", NULL, true, 0); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), e, NULL)); }*/ // @@ -7404,7 +7467,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) do { name = QCC_PR_ParseName(); QCC_PR_Expect(":"); - e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1, false); + e2 = QCC_PR_GetDef(QCC_PR_ParseType(false, false), name, pr_scope, true, 0, false); QCC_PR_Expect(";"); } while(!QCC_PR_CheckToken("{")); } @@ -7469,7 +7532,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) QCC_def_t *e, *e2; e = QCC_PR_GetDef(NULL, "__oself", pr_scope, false, 0); e2 = QCC_PR_GetDef(NULL, "self", NULL, false, 0); - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 1, e2->ofs, false), NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], e, QCC_PR_DummyDef(pr_classtype, "self", pr_scope, 0, e2->ofs, false), NULL)); }*/ QCC_PR_Statement (pr_opcodes, 0,0, NULL); @@ -7521,7 +7584,7 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi QCC_def_t *eq; if (min == max || min+1 == max) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; @@ -7534,7 +7597,7 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } @@ -7555,7 +7618,7 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i QCC_def_t *eq; if (min == max || min+1 == max) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(min+0.5f), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; @@ -7568,7 +7631,7 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(mid+0.5f), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } @@ -7587,10 +7650,13 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) QCC_dfunction_t *df; QCC_def_t *temp, *index, *func; - func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 1, false); + func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false); pr_scope = func; + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); + df = &functions[numfunctions]; numfunctions++; @@ -7600,17 +7666,17 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) df->parm_size[0] = 1; df->numparms = 1; df->parm_start = numpr_globals; - index = QCC_PR_GetDef(type_float, "index___", func, true, 1, false); + index = QCC_PR_GetDef(type_float, "index___", func, true, 0, false); index->references++; - temp = QCC_PR_GetDef(type_float, "div3___", func, true, 1, false); + temp = QCC_PR_GetDef(type_float, "div3___", func, true, 0, false); 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_DIV_F, index, QCC_MakeFloatConst(3), temp, false); 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 - QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL); //err... we didn't find it, give up. + QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); //err... we didn't find it, give up. QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); //err... we didn't find it, give up. G_FUNCTION(func->ofs) = df - functions; @@ -7630,7 +7696,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) QCC_def_t *fasttrackpossible; if (flag_fasttrackarrays) - fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false); + fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); else fasttrackpossible = NULL; @@ -7645,6 +7711,9 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) pr_scope = scope; + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); + df = &functions[numfunctions]; numfunctions++; @@ -7654,7 +7723,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) df->parm_size[0] = 1; df->numparms = 1; df->parm_start = numpr_globals; - index = QCC_PR_GetDef(type_float, "indexg___", def, true, 1, false); + index = QCC_PR_GetDef(type_float, "indexg___", def, true, 0, false); G_FUNCTION(scope->ofs) = df - functions; @@ -7683,44 +7752,44 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) //we need to work out which part, x/y/z that it's stored in. //0,1,2 = i - ((int)i/3 *) 3; - div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false); - intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false); + div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false); + intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false); - 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! + eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((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); + QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, &st); div3->references++; 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_DIV_F, index, QCC_MakeFloatConst(3), div3, 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); vectortrick->references++; - ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 1, false); + ret = QCC_PR_GetDef(type_vector, "vec__", pr_scope, true, 0, false); ret->references+=4; QCC_PR_Statement3(pr_opcodes+OP_STORE_V, &def_ret, ret, NULL, false); QCC_FreeTemp(&def_ret); - div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatDef(3), NULL); + div3 = QCC_PR_Statement(pr_opcodes+OP_MUL_F, intdiv3, QCC_MakeFloatConst(3), NULL); QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false); QCC_FreeTemp(div3); - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(0+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(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_F, index, QCC_MakeFloatDef(1+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(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_F, index, QCC_MakeFloatDef(2+0.5), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst(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); @@ -7734,7 +7803,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize); } - QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, NULL); + QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL); QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); @@ -7753,7 +7822,7 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t QCC_def_t *eq; if (min == max || min+1 == max) { - eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatConst((float)min), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 3; @@ -7770,7 +7839,7 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef((float)mid), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatConst((float)mid), NULL); QCC_UnFreeTemp(index); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } @@ -7791,13 +7860,16 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) QCC_def_t *fasttrackpossible; if (flag_fasttrackarrays) - fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false); + fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); else fasttrackpossible = NULL; def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false); pr_scope = scope; + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); + df = &functions[numfunctions]; numfunctions++; @@ -7808,8 +7880,8 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) df->parm_size[1] = def->type->size; df->numparms = 2; df->parm_start = numpr_globals; - index = QCC_PR_GetDef(type_float, "indexs___", def, true, 1, false); - value = QCC_PR_GetDef(def->type, "value___", def, true, 1, false); + index = QCC_PR_GetDef(type_float, "indexs___", def, true, 0, false); + value = QCC_PR_GetDef(def->type, "value___", def, true, 0, false); locals_end = numpr_globals; df->locals = locals_end - df->parm_start; @@ -7825,7 +7897,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) 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 QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p if (def->type->size != 1)//shift it upwards for larger types - QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntDef(def->type->size), index, true); + QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(def->type->size), index, true); QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add if (def->type->size >= 3) QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true); //*b = a @@ -7883,7 +7955,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a KEYWORD(asm); } - for (a = 0; a < arraysize; a++) + for (a = 0; a < (arraysize?arraysize:1); a++) { if (a == 0) *array = '\0'; @@ -7899,7 +7971,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a def = (void *)qccHunkAlloc (sizeof(QCC_def_t)); memset (def, 0, sizeof(*def)); def->next = NULL; - def->arraysize = arraysize; + def->arraysize = a?0:arraysize; if (name) { pr.def_tail->next = def; @@ -7911,6 +7983,8 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a def->s_line = pr_source_line; def->s_file = s_file; + if (a) + def->initialized = 1; def->name = (void *)qccHunkAlloc (strlen(newname)+1); strcpy (def->name, newname); @@ -7919,7 +7993,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a def->scope = scope; def->saved = saved; - // if (arraysize>1) + //if (type->type = ev_field) def->constant = true; if (ofs + type->size*a >= MAX_REGS) @@ -7941,14 +8015,14 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a { case ev_vector: sprintf(newname, "%s%s.%s", name, array, parttype->name); - QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved); + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved); sprintf(newname, "%s%s.%s_x", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, false); sprintf(newname, "%s%s.%s_y", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+1, false, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+1, false, false); sprintf(newname, "%s%s.%s_z", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a + parttype->ofs+2, false, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+2, false, false); break; case ev_float: @@ -7961,12 +8035,12 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a case ev_union: case ev_variant: //for lack of any better alternative sprintf(newname, "%s%s.%s", name, array, parttype->name); - QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a + parttype->ofs, false, saved); + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, saved); break; case ev_function: sprintf(newname, "%s%s.%s", name, array, parttype->name); - QCC_PR_DummyDef(parttype, newname, scope, 1, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true; + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a +parttype->ofs, false, saved)->initialized = true; break; case ev_void: break; @@ -7977,11 +8051,11 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a else if (type->type == ev_vector) { //do the vector thing. sprintf(newname, "%s%s_x", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+0, referable, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, false); sprintf(newname, "%s%s_y", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+1, referable, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, false); sprintf(newname, "%s%s_z", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 1, ofs + type->size*a+2, referable, false); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, false); } else if (type->type == ev_field) { @@ -7989,20 +8063,21 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a { //do the vector thing. sprintf(newname, "%s%s_x", name, array); - QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+0, referable, false); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+0, referable, false); sprintf(newname, "%s%s_y", name, array); - QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+1, referable, false); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, false); sprintf(newname, "%s%s_z", name, array); - QCC_PR_DummyDef(type_floatfield, newname, scope, 1, ofs + type->size*a+2, referable, false); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, false); } } + first->deftail = pr.def_tail; } if (referable) { if (!pHash_Get(&globalstable, "end_sys_fields")) first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off. - if (arraysize <= 1 && first->type->type != ev_field) + if (!arraysize && first->type->type != ev_field) first->constant = false; if (scope) pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t))); @@ -8010,7 +8085,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a pHash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(bucket_t))); if (!scope && asmfile) - fprintf(asmfile, "%s %s; /* at %d */\n", TypeName(first->type), first->name, first->ofs); + fprintf(asmfile, "%s %s;\n", TypeName(first->type), first->name); } return first; @@ -8022,6 +8097,9 @@ PR_GetDef If type is NULL, it will match any type If allocate is true, a new def will be allocated if it can't be found +If arraysize=0, its not an array and has 1 element. +If arraysize>0, its an array and requires array notation +If arraysize<0, its an array with undefined size - GetDef will fail if its not already allocated. ============ */ @@ -8033,6 +8111,9 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool unsigned int i; QCC_def_t *foundstatic = NULL; + if (!allocate) + arraysize = -1; + if (scope) { def = Hash_Get(&localstable, name); @@ -8047,7 +8128,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (type && typecmp(def->type, type)) QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); - if (def->arraysize != arraysize && arraysize) + if (def->arraysize != arraysize && arraysize>=0) QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { @@ -8083,7 +8164,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (!pr_scope) QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); } - if (def->arraysize != arraysize && arraysize) + if (def->arraysize != arraysize && arraysize>=0) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { @@ -8117,7 +8198,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (type && typecmp(def->type, type)) QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); - if (def->arraysize != arraysize && arraysize) + if (def->arraysize != arraysize && arraysize>=0) QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { @@ -8153,7 +8234,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (!pr_scope) QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); } - if (def->arraysize != arraysize && arraysize) + if (def->arraysize != arraysize && arraysize>=0) QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { @@ -8181,7 +8262,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (!allocate) return NULL; - if (arraysize < 1) + if (arraysize < 0) { QCC_PR_ParseError (ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name); } @@ -8193,7 +8274,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool } ofs = numpr_globals; - if (arraysize > 1) + if (arraysize) { //write the array size ofs = QCC_GetFreeOffsetSpace(1 + (type->size * arraysize)); @@ -8201,14 +8282,14 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool ofs++; } else - ofs = QCC_GetFreeOffsetSpace(type->size * arraysize); + ofs = QCC_GetFreeOffsetSpace(type->size); def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, true, saved); //fix up fields. if (type->type == ev_field && allocate != 2) { - for (i = 0; i < type->size*arraysize; i++) //make arrays of fields work. + for (i = 0; i < type->size*(arraysize?arraysize:1); i++) //make arrays of fields work. *(int *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i; pr.size_fields += i; @@ -8235,7 +8316,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, startfield = *fieldofs; maxfield = startfield; - for (a = 0; a < arraysize; a++) + for (a = 0; a < (arraysize?arraysize:1); a++) { if (a == 0) *array = '\0'; @@ -8309,14 +8390,14 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, sprintf(newname, "%s%s.%s", name, array, parttype->name); else sprintf(newname, "%s%s", parttype->name, array); - ftype = QCC_PR_NewType("FIELD TYPE", ev_field); + ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false); ftype->aux_type = parttype; if (parttype->type == ev_vector) ftype->size = parttype->size; //vector fields create a _y and _z too, so we need this still. - def = QCC_PR_GetDef(NULL, newname, scope, false, 1, saved); + def = QCC_PR_GetDef(NULL, newname, scope, false, 0, saved); if (!def) { - def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved); + def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); } else { @@ -8330,9 +8411,9 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, sprintf(newname, "%s%s.%s", name, array, parttype->name); else sprintf(newname, "%s%s", parttype->name, array); - ftype = QCC_PR_NewType("FIELD TYPE", ev_field); + ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false); ftype->aux_type = parttype; - def = QCC_PR_GetDef(ftype, newname, scope, true, 1, saved); + def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); def->initialized = true; ((int *)qcc_pr_globals)[def->ofs] = *fieldofs; *fieldofs += parttype->size; @@ -8363,6 +8444,221 @@ void QCC_PR_ExpandUnionToFields(QCC_type_t *type, int *fields) QCC_PR_DummyFieldDef(pass, "", pr_scope, 1, fields, true); } + +void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type, int offset) +{ + QCC_def_t *tmp; + int i; + + if (arraysize) + { + //arrays go recursive + QCC_PR_Expect("{"); + for (i = 0; i < arraysize; i++) + { + QCC_PR_ParseInitializerType(0, def, type, offset + i*type->size); + if (!QCC_PR_CheckToken(",")) + break; + } + QCC_PR_Expect("}"); + } + else + { + if (type->type == ev_function && pr_token_type == tt_punct) + { + /*begin function special case*/ + QCC_def_t *parentfunc = pr_scope; + QCC_function_t *f; + QCC_dfunction_t *df; + QCC_type_t *parm; + + tmp = NULL; + + def->references++; + pr_scope = def; + if (QCC_PR_CheckToken ("#") || QCC_PR_CheckToken (":")) + { + int binum = 0; + if (pr_token_type == tt_immediate + && pr_immediate_type == type_float + && pr_immediate._float == (int)pr_immediate._float) + binum = (int)pr_immediate._float; + else if (pr_token_type == tt_immediate && pr_immediate_type == type_integer) + binum = pr_immediate._int; + else + QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate"); + QCC_PR_Lex(); + + if (def->initialized) + for (i = 0; i < numfunctions; i++) + { + if (functions[i].first_statement == -binum) + { + tmp = QCC_MakeIntConst(i); + break; + } + } + + if (!tmp) + { + f = (void *)qccHunkAlloc (sizeof(QCC_function_t)); + f->builtin = binum; + + locals_start = locals_end = OFS_PARM0; //hmm... + } + else + f = NULL; + } + else + f = QCC_PR_ParseImmediateStatements (type); + if (!tmp) + { + pr_scope = parentfunc; + tmp = QCC_MakeIntConst(numfunctions); + f->def = def; + + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); + + // fill in the dfunction + df = &functions[numfunctions]; + numfunctions++; + if (f->builtin) + df->first_statement = -f->builtin; + else + df->first_statement = f->code; + + if (f->builtin && opt_function_names) + optres_function_names += strlen(f->def->name); + else + df->s_name = QCC_CopyString (f->def->name); + df->s_file = s_file2; + df->numparms = f->def->type->num_parms; + df->locals = locals_end - locals_start; + df->parm_start = locals_start; + for (i=0,parm = type->param ; inumparms ; i++, parm = parm->next) + { + df->parm_size[i] = parm->size; + } + /*end function special case*/ + } + } + else if (type->type == ev_string && QCC_PR_CheckName("_")) + { + char trname[128]; + QCC_PR_Expect("("); + if (pr_token_type != tt_immediate || pr_immediate_type->type != ev_string) + QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate"); + tmp = QCC_MakeStringConst(pr_immediate_string); + QCC_PR_Lex(); + QCC_PR_Expect(")"); + + if (!pr_scope || def->constant) + { + QCC_def_t *dt; + sprintf(trname, "dotranslate_%i", ++dotranslate_count); + dt = QCC_PR_DummyDef(type_string, trname, pr_scope, 0, offset, true, true); + dt->references = 1; + dt->constant = 1; + dt->initialized = 1; + } + } + else if (type->type == ev_struct || type->type == ev_union) + { + //structs go recursive + QCC_type_t *parttype; + int partnum; + int parms; + pbool isunion; + QCC_PR_Expect("{"); + + isunion = ((type)->type == ev_union); + for (partnum = 0, parttype = (type)->param, parms = (type)->num_parms; partnum < parms; partnum++, parttype = parttype->next) + { + QCC_PR_ParseInitializerType(parttype->arraysize, def, parttype, offset + parttype->ofs); + if (isunion || !QCC_PR_CheckToken(",")) + break; + } + QCC_PR_Expect("}"); + return; + } + else + { + tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); + if (typecmp(type, tmp->type)) + { + /*you can cast from const 0 to anything*/ + if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs)) + { + } + /*cast from int->float will convert*/ + else if (type->type == ev_float && tmp->type->type == ev_integer) + tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], tmp, 0, NULL); + /*cast from float->int will convert*/ + else if (type->type == ev_integer && tmp->type->type == ev_float) + tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], tmp, 0, NULL); + else + QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type"); + } + } + + if (!pr_scope || def->constant) + { + if (!tmp->constant) + QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initializer is not constant"); + + if (def->initialized) + { + for (i = 0; (unsigned)i < type->size; i++) + if (G_INT(offset+i) != G_INT(tmp->ofs+i)) + QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "incompatible redeclaration"); + } + else + { + for (i = 0; (unsigned)i < type->size; i++) + G_INT(offset+i) = G_INT(tmp->ofs+i); + } + } + else + { + QCC_def_t lhs, rhs; + if (def->initialized) + QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s initialised twice", def->name); + + memset(&lhs, 0, sizeof(lhs)); + memset(&rhs, 0, sizeof(rhs)); + def->references++; + for (i = 0; (unsigned)i < type->size; ) + { + rhs.type = lhs.type = type_float; + lhs.ofs = offset+i; + tmp->references++; + rhs.ofs = tmp->ofs+i; + + if (type->size - i >= 3) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &rhs, &lhs, NULL)); + i+=3; + } + else + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &rhs, &lhs, NULL)); + i++; + } + } + } + QCC_FreeTemp(tmp); + } +} + +void QCC_PR_ParseInitializerDef(QCC_def_t *def, pbool isvar, pbool isconst) +{ + def->constant = (isconst || (!isvar && !pr_scope)); + QCC_PR_ParseInitializerType(def->arraysize, def, def->type, def->ofs); + if (!def->initialized) + def->initialized = 1; +} + int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata /* ================ @@ -8388,10 +8684,12 @@ void QCC_PR_ParseDefs (char *classname) pbool nosave = false; pbool allocatenew = true; pbool inlinefunction = false; - int ispointer; gofs_t oldglobals; int arraysize; + while (QCC_PR_CheckToken(";")) + ; + if (QCC_PR_CheckKeyword(keyword_enum, "enum")) { if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int")) @@ -8424,7 +8722,7 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_Lex(); } } - def = QCC_MakeIntDef(iv); + def = QCC_MakeIntConst(iv); pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); iv++; @@ -8466,7 +8764,7 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_Lex(); } } - def = QCC_MakeFloatDef(fv); + def = QCC_MakeFloatConst(fv); pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); fv++; @@ -8528,11 +8826,11 @@ void QCC_PR_ParseDefs (char *classname) bits++; i>>=1; } - if (bits != 1) + if (bits > 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv); } - def = QCC_MakeIntDef(iv); + def = QCC_MakeIntConst(iv); pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); iv*=2; @@ -8587,11 +8885,11 @@ void QCC_PR_ParseDefs (char *classname) bits++; i>>=1; } - if (bits != 1) + if (bits > 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv); } - def = QCC_MakeFloatDef(fv); + def = QCC_MakeFloatConst(fv); pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); fv*=2; @@ -8607,12 +8905,13 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckKeyword (keyword_typedef, "typedef")) { - type = QCC_PR_ParseType(true); + type = QCC_PR_ParseType(true, false); if (!type) { QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens"); } type->name = QCC_CopyString(pr_token)+strings; + type->typedefed = true; QCC_PR_Lex(); QCC_PR_Expect(";"); return; @@ -8637,7 +8936,7 @@ void QCC_PR_ParseDefs (char *classname) if (accglobalsblock == 3) { if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false)) - QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false); + QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false); } QCC_PR_ParseName(); @@ -8656,11 +8955,11 @@ void QCC_PR_ParseDefs (char *classname) if (accglobalsblock == 3) { if (!QCC_PR_GetDef(type_void, "end_sys_fields", NULL, false, 0, false)) - QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 1, false); + QCC_PR_GetDef(type_void, "end_sys_fields", NULL, true, 0, false); } else if (!QCC_PR_GetDef(type_void, "end_sys_globals", NULL, false, 0, false)) - QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 1, false); + QCC_PR_GetDef(type_void, "end_sys_globals", NULL, true, 0, false); accglobalsblock = 3; } } @@ -8681,12 +8980,12 @@ void QCC_PR_ParseDefs (char *classname) break; } if (QCC_PR_CheckKeyword(keyword_object, "object")) - QCC_PR_GetDef(type_entity, name, NULL, true, 1, true); + QCC_PR_GetDef(type_entity, name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_string, "string")) - QCC_PR_GetDef(type_string, name, NULL, true, 1, true); + QCC_PR_GetDef(type_string, name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_real, "real")) { - def = QCC_PR_GetDef(type_float, name, NULL, true, 1, true); + def = QCC_PR_GetDef(type_float, name, NULL, true, 0, true); if (QCC_PR_CheckToken("=")) { G_FLOAT(def->ofs) = pr_immediate._float; @@ -8695,7 +8994,7 @@ void QCC_PR_ParseDefs (char *classname) } else if (QCC_PR_CheckKeyword(keyword_vector, "vector")) { - def = QCC_PR_GetDef(type_vector, name, NULL, true, 1, true); + def = QCC_PR_GetDef(type_vector, name, NULL, true, 0, true); if (QCC_PR_CheckToken("=")) { QCC_PR_Expect("["); @@ -8709,7 +9008,7 @@ void QCC_PR_ParseDefs (char *classname) } } else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc")) - QCC_PR_GetDef(type_function, name, NULL, true, 1, true); + QCC_PR_GetDef(type_function, name, NULL, true, 0, true); else QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n"); QCC_PR_Expect (";"); @@ -8736,15 +9035,15 @@ void QCC_PR_ParseDefs (char *classname) break; } if (QCC_PR_CheckKeyword(keyword_object, "object")) - QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 1, true); + QCC_PR_GetDef(QCC_PR_FieldType(type_entity), name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_string, "string")) - QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 1, true); + QCC_PR_GetDef(QCC_PR_FieldType(type_string), name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_real, "real")) - QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 1, true); + QCC_PR_GetDef(QCC_PR_FieldType(type_float), name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_vector, "vector")) - QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 1, true); + QCC_PR_GetDef(QCC_PR_FieldType(type_vector), name, NULL, true, 0, true); else if (QCC_PR_CheckKeyword(keyword_pfunc, "pfunc")) - QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 1, true); + QCC_PR_GetDef(QCC_PR_FieldType(type_function), name, NULL, true, 0, true); else QCC_PR_ParseError(ERR_BADNOTTYPE, "Bad type\n"); QCC_PR_Expect (";"); @@ -8778,7 +9077,7 @@ void QCC_PR_ParseDefs (char *classname) break; } - type = QCC_PR_ParseType (false); + type = QCC_PR_ParseType (false, false); if (type == NULL) //ignore return; @@ -8796,9 +9095,7 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_Expect("("); type = QCC_PR_ParseFunctionTypeReacc(false, type); QCC_PR_Expect(";"); - if (!stricmp(name, "null")) - printf("null!\n"); - def = QCC_PR_GetDef (type, name, NULL, true, 1, false); + def = QCC_PR_GetDef (type, name, NULL, true, 0, false); if (autoprototype) { //ignore the code and stuff @@ -8850,6 +9147,9 @@ void QCC_PR_ParseDefs (char *classname) // if (pr_dumpasm) // PR_PrintFunction (def); + if (numfunctions >= MAX_FUNCTIONS) + QCC_Error(ERR_INTERNAL, "Too many function defs"); + // fill in the dfunction df = &functions[numfunctions]; numfunctions++; @@ -8878,15 +9178,8 @@ void QCC_PR_ParseDefs (char *classname) // QCC_PR_ParseError ("Fields must be global"); do - { - if (QCC_PR_CheckToken ("*")) - { - ispointer = 1; - while(QCC_PR_CheckToken ("*")) - ispointer++; - name = QCC_PR_ParseName (); - } - else if (QCC_PR_CheckToken (";")) + { + if (QCC_PR_CheckToken (";")) { if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct)) { @@ -8899,12 +9192,10 @@ void QCC_PR_ParseDefs (char *classname) // } QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name"); name = NULL; - ispointer = false; } else { name = QCC_PR_ParseName (); - ispointer = false; } if (QCC_PR_CheckToken("::") && !classname) @@ -8940,46 +9231,18 @@ void QCC_PR_ParseDefs (char *classname) } else { - def = QCC_PR_Expression(TOP_PRIORITY, 0); - if (!def->constant) - QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value"); - else if (def->type->type == ev_integer) - arraysize = G_INT(def->ofs); - else if (def->type->type == ev_float) - { - arraysize = (int)G_FLOAT(def->ofs); - if ((float)arraysize != G_FLOAT(def->ofs)) - QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value"); - } - else - QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size must be of int value"); -/* if(pr_token_type == tt_name) - { - def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), pr_scope, false, 0); - if (def && def->arraysize==1) - { - if (def->type->type == ev_integer) - arraysize = G_INT(def->ofs); - else if (def->type->type == ev_float && (float)(int)G_FLOAT(def->ofs) == G_FLOAT(def->ofs)) - arraysize = (int)G_FLOAT(def->ofs); - } - } - else if (pr_token_type == tt_immediate) - { - arraysize = atoi (pr_token); - QCC_PR_Lex(); - } -*/ QCC_PR_Expect("]"); + arraysize = QCC_PR_IntConstExpr(); + QCC_PR_Expect("]"); } if (arraysize < 1) { QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name); - arraysize=0; //grrr... + arraysize=1; //grrr... } } else - arraysize = 1; + arraysize = 0; if (QCC_PR_CheckToken("(")) { @@ -9007,19 +9270,7 @@ void QCC_PR_ParseDefs (char *classname) oldglobals = numpr_globals; - if (ispointer) - { - parm = type; - while(ispointer) - { - ispointer--; - parm = QCC_PointerTypeTo(parm); - } - - def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize, !nosave); - } - else - def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave); + def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave); if (!def) QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname); @@ -9051,13 +9302,12 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_ParseError (ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised"); } - arraysize = def->arraysize; - d = def; //apply to ALL elements - while(arraysize--) + d = def; + while (d != def->deftail) { + d = d->next; d->initialized = 1; //fake function G_FUNCTION(d->ofs) = 0; - d = d->next; } continue; @@ -9074,14 +9324,14 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name); if (def->initialized == 1) { - if (def->type->type == ev_function) - { - i = G_FUNCTION(def->ofs); - df = &functions[i]; - QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file); - } - else - QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name); +// if (def->type->type == ev_function) +// { +// i = G_FUNCTION(def->ofs); +// df = &functions[i]; +// QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file); +// } +// else +// QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name); } if (autoprototype) @@ -9119,588 +9369,7 @@ void QCC_PR_ParseDefs (char *classname) continue; } - 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; (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 (def->type->size >= 3) - { - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], d, def, NULL)); - def->constant = false; - def->initialized = false; - continue; - } - else - { - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], d, def, NULL)); - def->constant = false; - def->initialized = false; - continue; - } - } - else - if (pr_token_type == tt_name && strcmp(pr_token, "_")) - { - unsigned int i; - - if (def->arraysize>1) - QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly braces"); - - d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token); - if (typecmp(def->type, d->type)) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - - - for (i = 0; i < d->type->size; i++) - G_INT(def->ofs) = G_INT(d->ofs); - QCC_PR_Lex(); - - if (type->type == ev_function) - { - def->initialized = 1; - def->constant = !isvar; - } - continue; - } - - else if (type->type == ev_function) - { - if (isvar) - def->constant = false; - else - def->constant = true; - if (QCC_PR_CheckImmediate("0") || QCC_PR_CheckImmediate("0i")) - { - def->constant = 0; - def->initialized = 1; //fake function - G_FUNCTION(def->ofs) = 0; - continue; - } - - if (!def->constant && arraysize==1) - { - def->constant = 0; - def->initialized = 1; //fake function - - name = QCC_PR_ParseName (); - d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not previously defined", name); - G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs); - continue; - } - - if (arraysize>1) - { - int i; - def->initialized = 1; //fake function - QCC_PR_Expect ("{"); - i = 0; - do - { - 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 (); - - d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined", name); - else - { - if (!d->initialized) - QCC_PR_ParseWarning(WARN_NOTDEFINED, "initialisation of function arrays must be placed after the body of all functions used (%s)", name); - G_FUNCTION(def->ofs+i) = G_FUNCTION(d->ofs); - } - } - - i++; - } while(QCC_PR_CheckToken(",")); - - arraysize = def->arraysize; - d = def; //apply to ALL elements - while(arraysize--) - { - d->initialized = 1; //fake function - d = d->next; - } - - QCC_PR_Expect("}"); - if (i > def->arraysize) - QCC_PR_ParseError(ERR_TOOMANYINITIALISERS, "Too many initializers"); - continue; - } - if (!def->constant) - QCC_PR_ParseError(0, "Initialised functions must be constant"); - - def->references++; - pr_scope = def; - f = QCC_PR_ParseImmediateStatements (type); - pr_scope = NULL; - def->initialized = 1; - G_FUNCTION(def->ofs) = numfunctions; - f->def = def; -// if (pr_dumpasm) -// PR_PrintFunction (def); - - // fill in the dfunction - df = &functions[numfunctions]; - numfunctions++; - if (f->builtin) - df->first_statement = -f->builtin; - else - df->first_statement = f->code; - - if (f->builtin && opt_function_names) - optres_function_names += strlen(f->def->name); - else - df->s_name = QCC_CopyString (f->def->name); - df->s_file = s_file2; - df->numparms = f->def->type->num_parms; - df->locals = locals_end - locals_start; - df->parm_start = locals_start; - for (i=0,parm = type->param ; inumparms ; i++, parm = parm->next) - { - df->parm_size[i] = parm->size; - } - - continue; - } - - else if (type->type == ev_struct) - { - int arraypart, partnum; - QCC_type_t *parttype; - def->initialized = 1; - if (isvar) - def->constant = true; - else - 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++) - { - parttype = type->param; - QCC_PR_Expect("{"); - for (partnum = 0; partnum < type->num_parms; partnum++) - { - switch (parttype->type) - { - case ev_float: - case ev_integer: - case ev_vector: - if (pr_token_type == tt_punct) - { - if (QCC_PR_CheckToken("{")) - { - QCC_PR_Expect("}"); - } - else - QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation"); - - } - else if (pr_token_type == tt_immediate) - { - if (pr_immediate_type->type == ev_float && parttype->type == ev_integer) - G_INT(def->ofs + arraypart*type->size + parttype->ofs) = (int)pr_immediate._float; - else if (pr_immediate_type->type != parttype->type) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name); - else - memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]); - } - else if (pr_token_type == tt_name) - { - d = QCC_PR_GetDef(NULL, pr_token, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", pr_token); - else if (d->type->type != parttype->type) - QCC_PR_ParseError (ERR_WRONGSUBTYPE, "wrong subtype for %s.%s", def->name, parttype->name); - else if (!d->constant) - QCC_PR_ParseError(ERR_NOTACONSTANT, "%s isn't a constant\n", pr_token); - - memcpy (qcc_pr_globals + def->ofs + arraypart*type->size + parttype->ofs, qcc_pr_globals + d->ofs, 4*d->type->size); - } - else - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate subtype for %s.%s", def->name, parttype->name); - QCC_PR_Lex (); - - break; - case ev_string: - if (pr_token_type == tt_punct) - { - if (QCC_PR_CheckToken("{")) - { - unsigned int i; - for (i = 0; i < parttype->size; i++) - { -/* //the executor defines strings as true c strings, but reads in index from string table. - //structures can hide these strings. - d = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - d->next = NULL; - pr.def_tail->next = d; - pr.def_tail = d; - - d->type = parttype; - d->name = "STRUCTIMMEDIATE"; - d->constant = constant; - d->initialized = 1; - d->scope = NULL; - - d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i; -*/ - G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = QCC_CopyString(pr_immediate_string); - QCC_PR_Lex (); - - if (!QCC_PR_CheckToken(",")) - { - i++; - break; - } - } - for (; i < parttype->size; i++) - { -/* //the executor defines strings as true c strings, but reads in index from string table. - //structures can hide these strings. - d = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - d->next = NULL; - pr.def_tail->next = d; - pr.def_tail = d; - - d->type = parttype; - d->name = "STRUCTIMMEDIATE"; - d->constant = constant; - d->initialized = 1; - d->scope = NULL; - - d->ofs = def->ofs+arraypart*type->size+parttype->ofs+i; -*/ - G_INT(def->ofs+arraypart*type->size+parttype->ofs+i) = 0; - } - QCC_PR_Expect("}"); - } - else - QCC_PR_ParseError(ERR_UNEXPECTEDPUNCTUATION, "Unexpected punctuation"); - } - else - { -/* //the executor defines strings as true c strings, but reads in index from string table. - //structures can hide these strings. - d = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - d->next = NULL; - pr.def_tail->next = d; - pr.def_tail = d; - - d->type = parttype; - d->name = "STRUCTIMMEDIATE"; - d->constant = constant; - d->initialized = 1; - d->scope = NULL; - - d->ofs = def->ofs+arraypart*type->size+parttype->ofs; -*/ - G_INT(def->ofs+arraypart*type->size+parttype->ofs) = QCC_CopyString(pr_immediate_string); - QCC_PR_Lex (); - } - break; - case ev_function: - if (pr_token_type == tt_immediate) - { - if (pr_immediate._int != 0) - QCC_PR_ParseError(ERR_NOTFUNCTIONTYPE, "Expected function name or NULL"); - G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = 0; - QCC_PR_Lex(); - } - else - { - name = QCC_PR_ParseName (); - - d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError(ERR_NOTDEFINED, "%s was not defined\n", name); - else - G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = G_FUNCTION(d->ofs); - } - break; - default: - QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type); - QCC_PR_Lex(); - break; - } - if (!QCC_PR_CheckToken(",")) - break; - - parttype=parttype->next; - } - QCC_PR_Expect("}"); - if (!QCC_PR_CheckToken(",")) - break; - } - QCC_PR_Expect("}"); - continue; - } - - else if (type->type == ev_integer) //handle these differently, because they may need conversions - { - if (isvar) - def->constant = false; - else - def->constant = true; - - def->initialized = 1; - memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]); - QCC_PR_Lex (); - - if (pr_immediate_type->type == ev_float) - G_INT(def->ofs) = (int)pr_immediate._float; - else if (pr_immediate_type->type != ev_integer) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - - continue; - } - else if (type->type == ev_string) - { - int dotranslate = 0; - char buf[64]; - if (!strcmp(pr_token, "_")) - { - dotranslate = 1; - QCC_PR_Lex(); - } - if(dotranslate) - QCC_PR_Expect("("); - - if (arraysize>=1 && QCC_PR_CheckToken("{")) - { - int i; - for (i = 0; i < arraysize; i++) - { - int dotranslate2; - - //the executor defines strings as true c strings, but reads in index from string table. - //structures can hide these strings. - if (i != 0) //not for the first entry - already a string def for that - { - d = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - d->next = NULL; - pr.def_tail->next = d; - pr.def_tail = d; - - d->name = "IMMEDIATE"; - d->type = type_string; - if (isvar) - d->constant = false; - else - d->constant = true; - d->initialized = 1; - d->scope = NULL; - - d->ofs = def->ofs+i; - if (d->ofs >= MAX_REGS) - QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small"); - } - - if (!strcmp(pr_token, "_")) - { - dotranslate2 = 1; - QCC_PR_Lex(); - } - if(dotranslate2) - QCC_PR_Expect("("); - - if(dotranslate || dotranslate2) - { - sprintf(buf, "dotranslate_%d", ++dotranslate_count); - d->name = strdup(buf); - } - - (((int *)qcc_pr_globals)[def->ofs+i]) = QCC_CopyString(pr_immediate_string); - QCC_PR_Lex (); - - if(dotranslate2) - QCC_PR_Expect(")"); - - if (!QCC_PR_CheckToken(",")) - break; - } - QCC_PR_Expect("}"); - } - else if (arraysize<=1) - { - if (isvar) - def->constant = false; - else - def->constant = true; - def->initialized = 1; - (((int *)qcc_pr_globals)[def->ofs]) = QCC_CopyString(pr_immediate_string); - QCC_PR_Lex (); - - if(dotranslate) - { - sprintf(buf, "dotranslate_%d", ++dotranslate_count); - def->name = strdup(buf); - } - - if (pr_immediate_type->type == ev_float) - G_INT(def->ofs) = (int)pr_immediate._float; - else if (pr_immediate_type->type != ev_string) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - } - else - QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces"); - - if(dotranslate) - QCC_PR_Expect(")"); - continue; - } - else if (type->type == ev_float) - { - if (arraysize>=1 && QCC_PR_CheckToken("{")) - { - int i; - for (i = 0; i < arraysize; i++) - { - if (pr_immediate_type->type != ev_float) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - (((float *)qcc_pr_globals)[def->ofs+i]) = pr_immediate._float; - QCC_PR_Lex (); - - if (!QCC_PR_CheckToken(",")) - break; - } - QCC_PR_Expect("}"); - - continue; - } - else if (arraysize<=1) - { - if (isvar) - def->constant = false; - else - def->constant = true; - - def->initialized = 1; - - if (pr_immediate_type->type != ev_float) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - - if (def->constant && opt_dupconstdefs) - { - if (def->ofs == oldglobals) - { - if (Hash_GetKey(&floatconstdefstable, *(int*)&pr_immediate._float)) - optres_dupconstdefs++; - QCC_FreeOffset(def->ofs, def->type->size); - d = QCC_MakeFloatDef(pr_immediate._float); - d->references++; - def->ofs = d->ofs; - QCC_PR_Lex(); - continue; - } - } - - (((float *)qcc_pr_globals)[def->ofs]) = pr_immediate._float; - QCC_PR_Lex (); - - continue; - } - else - QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces"); - } - else if (type->type == ev_vector) - { - if (arraysize>=1 && QCC_PR_CheckToken("{")) - { - int i; - for (i = 0; i < arraysize; i++) - { - if (pr_immediate_type->type != ev_vector) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - (((float *)qcc_pr_globals)[def->ofs+i*3+0]) = pr_immediate.vector[0]; - (((float *)qcc_pr_globals)[def->ofs+i*3+1]) = pr_immediate.vector[1]; - (((float *)qcc_pr_globals)[def->ofs+i*3+2]) = pr_immediate.vector[2]; - QCC_PR_Lex (); - - if (!QCC_PR_CheckToken(",")) - break; - } - QCC_PR_Expect("}"); - - continue; - } - else if (arraysize<=1) - { - if (isvar) - def->constant = false; - else - def->constant = true; - def->initialized = 1; - - if (pr_immediate_type->type != ev_vector) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); - (((float *)qcc_pr_globals)[def->ofs+0]) = pr_immediate.vector[0]; - (((float *)qcc_pr_globals)[def->ofs+1]) = pr_immediate.vector[1]; - (((float *)qcc_pr_globals)[def->ofs+2]) = pr_immediate.vector[2]; - QCC_PR_Lex (); - - continue; - } - else - QCC_PR_ParseError(ERR_ARRAYNEEDSBRACES, "Array initialisation requires curly brasces"); - } - else if (pr_token_type == tt_name) - { -// if (pr_scope)//create a new instance, emit a copy op -// { -// QCC_PR_ParseError ("name defined for local : %s", name); -// } -// else - { - d = QCC_PR_GetDef (NULL, pr_token, pr_scope, false, 0, false); - if (!d) - QCC_PR_ParseError (ERR_NOTDEFINED, "initialisation name not defined : %s", pr_token); - if (!d->constant) - { - QCC_PR_ParseWarning (WARN_NOTCONSTANT, "initialisation name not a constant : %s", pr_token); - QCC_PR_ParsePrintDef(WARN_NOTCONSTANT, d); - } - memcpy (def, d, sizeof(*d)); - def->name = name; - def->initialized = true; - } - } - else if (pr_token_type != tt_immediate) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "not an immediate for %s - %s", name, pr_token); - else if (pr_immediate_type->type != type->type) - QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s - %s", name, pr_token); - else - memcpy (qcc_pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]); - - if (isvar) - def->constant = false; - else - def->constant = true; - def->initialized = true; - QCC_PR_Lex (); + QCC_PR_ParseInitializerDef(def, isvar, isconstant); } else { @@ -9723,7 +9392,13 @@ void QCC_PR_ParseDefs (char *classname) def->constant = isconstant; } - + d = def; + while (d != def->deftail) + { + d = d->next; + d->constant = def->constant; + d->initialized = def->initialized; + } } while (QCC_PR_CheckToken (",")); if (type->type == ev_function) @@ -9817,7 +9492,6 @@ pbool QCC_Include(char *filename) int opr_source_line; char *ocompilingfile; struct qcc_includechunk_s *oldcurrentchunk; - extern struct qcc_includechunk_s *currentchunk; ocompilingfile = compilingfile; os_file = s_file; diff --git a/misc/source/fteqcc-src/qcc_pr_lex.c b/misc/source/fteqcc-src/qcc_pr_lex.c index 9bdd11c4..7a4319ba 100644 --- a/misc/source/fteqcc-src/qcc_pr_lex.c +++ b/misc/source/fteqcc-src/qcc_pr_lex.c @@ -6,22 +6,14 @@ #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 +#ifdef _WIN64 + #ifdef _SDL + #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); + //void *__imp__vsnprintf = vsnprintf; + #endif #endif #define MEMBERFIELDNAME "__m%s" @@ -82,6 +74,8 @@ QCC_type_t *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void}; QCC_type_t *type_pointer;// = {ev_pointer/*, &def_pointer*/}; QCC_type_t *type_integer;// = {ev_integer/*, &def_integer*/}; QCC_type_t *type_variant;// = {ev_integer/*, &def_integer*/}; +QCC_type_t *type_floatpointer; +QCC_type_t *type_intpointer; QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float}; @@ -106,13 +100,6 @@ void QCC_PR_LexWhitespace (void); //for compiler constants and file includes. -typedef struct qcc_includechunk_s { - struct qcc_includechunk_s *prev; - char *filename; - char *currentdatapoint; - int currentlinenumber; - CompilerConstant_t *cnst; -} qcc_includechunk_t; qcc_includechunk_t *currentchunk; void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst) { @@ -237,16 +224,34 @@ int ParsePrecompilerIf(void) { CompilerConstant_t *c; int eval = 0; - //char *start = pr_file_p; //warning: unused variable âstartâ + pbool notted = false; + + /*skip whitespace*/ + while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n') + { + pr_file_p++; + } + if (*pr_file_p == '!') + { + pr_file_p++; + notted = true; + while (*pr_file_p && *pr_file_p <= ' ' && *pr_file_p != '\n') + { + pr_file_p++; + } + } + if (!QCC_PR_SimpleGetToken()) { if (*pr_file_p == '(') { + pr_file_p++; eval = ParsePrecompilerIf(); while (*pr_file_p == ' ' || *pr_file_p == '\t') pr_file_p++; if (*pr_file_p != ')') QCC_PR_ParseError(ERR_EXPECTED, "unclosed bracket condition\n"); + pr_file_p++; } else QCC_PR_ParseError(ERR_EXPECTED, "expected bracket or constant\n"); @@ -280,6 +285,9 @@ int ParsePrecompilerIf(void) eval = atoi(c->value); } + if (notted) + eval = !eval; + QCC_PR_SimpleGetToken(); if (!strcmp(pr_token, "||")) eval = ParsePrecompilerIf()||eval; @@ -514,7 +522,7 @@ pbool QCC_PR_Precompiler(void) 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] = '\0'; while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line, yes, I KNOW we are going to register an error, and not properly leave this function tree, but... { @@ -647,11 +655,6 @@ pbool QCC_PR_Precompiler(void) if (*pr_file_p == '\r') pr_file_p++; - 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++; @@ -831,6 +834,18 @@ pbool QCC_PR_Precompiler(void) { defaultstatic = atoi(msg); } + else if (!strncmp(qcc_token, "wrasm", 5)) + { + pbool on = atoi(msg); + + if (asmfile && !on) + { + fclose(asmfile); + asmfile = NULL; + } + if (!asmfile && on) + asmfile = fopen("qc.asm", "wb"); + } else if (!strncmp(qcc_token, "sourcefile", 10)) { #define MAXSOURCEFILESLIST 8 @@ -847,7 +862,7 @@ pbool QCC_PR_Precompiler(void) if (!strcmp(sourcefileslist[i], qcc_token)) break; } - if (i == numsourcefiles) + if (i == numsourcefiles && numsourcefiles < MAXSOURCEFILESLIST) strcpy(sourcefileslist[numsourcefiles++], qcc_token); } else if (!QC_strcasecmp(qcc_token, "TARGET")) @@ -857,7 +872,7 @@ pbool QCC_PR_Precompiler(void) else if (!QC_strcasecmp(msg, "H2") || !QC_strcasecmp(msg, "HEXEN2")) { if (numstatements) - QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch from hexen2 target \'%s\'. Ignored.", msg); + QCC_PR_ParseWarning(WARN_BADTARGET, "Cannot switch to hexen2 target \'%s\'. Ignored.", msg); else qcc_targetformat = QCF_HEXEN2; } @@ -1354,7 +1369,7 @@ int QCC_PR_LexInteger (void) len++; pr_file_p++; c = *pr_file_p; - } while ((c >= '0' && c<= '9') || c == '.' || (c>='a' && c <= 'f')); + } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.') || (c>='a' && c <= 'f')); pr_token[len] = 0; return atoi (pr_token); } @@ -1407,7 +1422,7 @@ void QCC_PR_LexNumber (void) num*=base; num += c -'A'+10; } - else if (c == '.') + else if (c == '.' && pr_file_p[1]!='.') { pr_token[tokenlen++] = c; pr_file_p++; @@ -1434,6 +1449,15 @@ void QCC_PR_LexNumber (void) pr_immediate._float = (float)atof(pr_token); return; } + else if (c == 'f') + { + pr_token[tokenlen++] = c; + pr_token[tokenlen++] = 0; + pr_file_p++; + pr_immediate_type = type_float; + pr_immediate._float = num*sign; + return; + } else if (c == 'i') { pr_token[tokenlen++] = c; @@ -1487,6 +1511,8 @@ float QCC_PR_LexFloat (void) pr_file_p++; c = *pr_file_p; } while ((c >= '0' && c<= '9') || (c == '.'&&pr_file_p[1]!='.')); //only allow a . if the next isn't too... + if (*pr_file_p == 'f') + pr_file_p++; pr_token[len] = 0; return (float)atof (pr_token); } @@ -1532,6 +1558,7 @@ void QCC_PR_LexVector (void) default: QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant"); } + pr_file_p++; if (*pr_file_p != '\'') QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant"); pr_file_p++; @@ -1680,6 +1707,7 @@ void QCC_PR_LexWhitespace (void) } if (pr_file_p[1] == 0) { + QCC_PR_ParseError(0, "EOF inside comment\n"); pr_file_p++; return; } @@ -1964,7 +1992,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name) // if (numCompilerConstants >= MAX_CONSTANTS) // QCC_PR_ParseError("Too many compiler constants - %i >= %i", numCompilerConstants, MAX_CONSTANTS); - if (strlen(name) >= MAXCONSTANTLENGTH || !*name) + if (strlen(name) >= MAXCONSTANTNAMELENGTH || !*name) QCC_PR_ParseError(ERR_NAMETOOLONG, "Compiler constant name length is too long or short"); cnst = pHash_Get(&compconstantstable, name); @@ -2112,6 +2140,43 @@ void QCC_PR_ConditionCompilation(void) pr_file_p = s; } +/* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */ +static void QCC_PR_ExpandStrCat(char **buffer, int *bufferlen, int *buffermax, char *newdata, int newlen) +{ + int newmax = *bufferlen + newlen; + if (newmax < *bufferlen) + { + QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory"); + return; + } + if (newmax > *buffermax) + { + char *newbuf; + if (newmax < 64) + newmax = 64; + if (newmax < *bufferlen * 2) + { + newmax = *bufferlen * 2; + if (newmax < *bufferlen) /*overflowed?*/ + { + QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory"); + return; + } + } + newbuf = realloc(*buffer, newmax); + if (!newbuf) + { + QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory"); + return; /*OOM*/ + } + *buffer = newbuf; + *buffermax = newmax; + } + memcpy(*buffer + *bufferlen, newdata, newlen); + *bufferlen += newlen; + /*no null terminator, remember to cat one if required*/ +} + int QCC_PR_CheakCompConst(void) { char *oldpr_file_p = pr_file_p; @@ -2165,7 +2230,10 @@ int QCC_PR_CheakCompConst(void) { int p; char *start; - char buffer[1024]; + char *starttok; + char *buffer; + int buffermax; + int bufferlen; char *paramoffset[MAXCONSTANTPARAMS+1]; int param=0; int plevel=0; @@ -2220,38 +2288,45 @@ int QCC_PR_CheakCompConst(void) QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Not enough macro parameters"); paramoffset[param] = start; - *buffer = '\0'; + buffer = NULL; + bufferlen = 0; + buffermax = 0; oldpr_file_p = pr_file_p; pr_file_p = c->value; for(;;) { - whitestart = p = strlen(buffer); + whitestart = bufferlen; + starttok = pr_file_p; while(*pr_file_p <= ' ') //copy across whitespace { if (!*pr_file_p) break; - buffer[p++] = *pr_file_p++; + pr_file_p++; + } + if (starttok != pr_file_p) + { + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, starttok, pr_file_p - starttok); } - buffer[p] = 0; if(*pr_file_p == '\"') { + starttok = pr_file_p; do { - buffer[p++] = *pr_file_p; - ++pr_file_p; + pr_file_p++; } while( (pr_file_p[-1] == '\\' || pr_file_p[0] != '\"') && *pr_file_p && *pr_file_p != '\n' ); - buffer[p++] = *pr_file_p; // copy the end-quote too - buffer[p] = 0; - ++pr_file_p; // and skip it + if(*pr_file_p == '\"') + pr_file_p++; + + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, starttok, pr_file_p - starttok); continue; } else if (*pr_file_p == '#') //if you ask for #a##b you will be shot. use #a #b instead, or chain macros. { if (pr_file_p[1] == '#') - { //concatinate (srip out whitespace) - buffer[whitestart] = '\0'; + { //concatinate (strip out whitespace before the token) + bufferlen = whitestart; pr_file_p+=2; } else @@ -2265,16 +2340,16 @@ int QCC_PR_CheakCompConst(void) { if (!STRCMP(qcc_token, c->params[p])) { - strcat(buffer, "\""); - strcat(buffer, paramoffset[p]); - strcat(buffer, "\""); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p])); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1); break; } } if (p == param) { - strcat(buffer, "#"); - strcat(buffer, qcc_token); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "#", 1); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token)); //QCC_PR_ParseWarning(0, "Stringification ignored"); } continue; //already did this one @@ -2289,12 +2364,12 @@ int QCC_PR_CheakCompConst(void) { if (!STRCMP(qcc_token, c->params[p])) { - strcat(buffer, paramoffset[p]); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p])); break; } } if (p == param) - strcat(buffer, qcc_token); + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token)); } for (p = 0; p < param-1; p++) @@ -2302,12 +2377,17 @@ int QCC_PR_CheakCompConst(void) paramoffset[p][strlen(paramoffset[p])] = ')'; pr_file_p = oldpr_file_p; - if (!*buffer) + if (!bufferlen) expandedemptymacro = true; - QCC_PR_IncludeChunkEx(buffer, true, NULL, c); + else + { + QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\0", 1); + QCC_PR_IncludeChunkEx(buffer, true, NULL, c); + } + free(buffer); } else - QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without opening brace"); + QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list"); } else { @@ -2495,7 +2575,7 @@ void QCC_PR_Lex (void) QCC_PR_LexNumber(); return; } - if ( (c == '.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') ) + if ( (c == '.'&&pr_file_p[1]!='.'&&pr_file_p[1] >='0' && pr_file_p[1] <= '9') || (c >= '0' && c <= '9') || ( c=='-' && pr_file_p[1]>='0' && pr_file_p[1] <='9') ) { pr_token_type = tt_immediate; QCC_PR_LexNumber (); @@ -2688,13 +2768,13 @@ void VARGS QCC_PR_Note (int type, char *file, int line, char *error, ...) printf ("note: %s\n", string); } -void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...) +pbool VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...) { va_list argptr; char string[1024]; if (qccwarningdisabled[type]) - return; + return false; va_start (argptr,error); QC_vsnprintf (string,sizeof(string)-1, error,argptr); @@ -2711,6 +2791,8 @@ void VARGS QCC_PR_Warning (int type, char *file, int line, char *error, ...) else printf ("warning: %s\n", string); pr_warning_count++; + + return true; } @@ -2816,7 +2898,12 @@ char *QCC_PR_ParseName (void) char *ret; if (pr_token_type != tt_name) - QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token); + { + if (pr_token_type == tt_eof) + QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token); + else + 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); @@ -2838,7 +2925,6 @@ a new one and copies it out. */ //0 if same -QCC_type_t *QCC_PR_NewType (char *name, int basictype); int typecmp(QCC_type_t *a, QCC_type_t *b) { if (a == b) @@ -2849,7 +2935,9 @@ int typecmp(QCC_type_t *a, QCC_type_t *b) if (a->type != b->type) return 1; if (a->num_parms != b->num_parms) + { return 1; + } if (a->size != b->size) return 1; @@ -2883,7 +2971,7 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in) if (!in) return NULL; - out = QCC_PR_NewType(in->name, in->type); + out = QCC_PR_NewType(in->name, in->type, false); out->aux_type = QCC_PR_DuplicateType(in->aux_type); out->param = QCC_PR_DuplicateType(in->param); ip = in->param; @@ -2896,6 +2984,7 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in) op = (op->next = QCC_PR_DuplicateType(ip)); ip = ip->next; } + out->arraysize = in->arraysize; out->size = in->size; out->num_parms = in->num_parms; out->ofs = in->ofs; @@ -2923,17 +3012,29 @@ char *TypeName(QCC_type_t *type) if (type->type == ev_function) { + pbool varg = type->num_parms < 0; + int args = type->num_parms; + if (args < 0) + args = -(args+1); strcat(ret, type->aux_type->name); strcat(ret, " ("); type = type->param; while(type) { + if (args<=0) + strcat(ret, "optional "); + args--; + strcat(ret, type->name); type = type->next; - if (type) + if (type || varg) strcat(ret, ", "); } + if (varg) + { + strcat(ret, "..."); + } strcat(ret, ")"); } else if (type->type == ev_entity && type->parentclass) @@ -3060,17 +3161,18 @@ char pr_parm_names[MAX_PARMS][MAX_NAME]; pbool recursivefunctiontype; -QCC_type_t *QCC_PR_NewType (char *name, int basictype); //expects a ( to have already been parsed. QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) { QCC_type_t *ftype, *ptype, *nptype; char *name; int definenames = !recursivefunctiontype; + int optional = 0; + int numparms = 0; recursivefunctiontype++; - ftype = QCC_PR_NewType(type_function->name, ev_function); + ftype = QCC_PR_NewType(type_function->name, ev_function, false); ftype->aux_type = returntype; // return type ftype->num_parms = 0; @@ -3089,11 +3191,21 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) if (QCC_PR_CheckToken ("...")) { - ftype->num_parms = (ftype->num_parms * -1) - 1; + if (optional) + numparms = optional-1; + ftype->num_parms = (numparms * -1) - 1; break; } - nptype = QCC_PR_ParseType(true); + if (QCC_PR_CheckKeyword(keyword_optional, "optional")) + { + if (!optional) + optional = numparms+1; + } + else if (optional) + QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n"); + + nptype = QCC_PR_ParseType(true, false); if (nptype->type == ev_void) break; @@ -3114,11 +3226,15 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) { name = QCC_PR_ParseName (); if (definenames) - strcpy (pr_parm_names[ftype->num_parms], name); + strcpy (pr_parm_names[numparms], name); } else if (definenames) - strcpy (pr_parm_names[ftype->num_parms], ""); - ftype->num_parms++; + strcpy (pr_parm_names[numparms], ""); + numparms++; + if (optional) + ftype->num_parms = optional-1; + else + ftype->num_parms = numparms; } while (QCC_PR_CheckToken (",")); QCC_PR_Expect (")"); @@ -3137,7 +3253,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) recursivefunctiontype++; - ftype = QCC_PR_NewType(type_function->name, ev_function); + ftype = QCC_PR_NewType(type_function->name, ev_function, false); ftype->aux_type = returntype; // return type ftype->num_parms = 0; @@ -3164,19 +3280,19 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) { sprintf(argname, "arg%i", ftype->num_parms); name = argname; - nptype = QCC_PR_NewType("Variant", ev_variant); + nptype = QCC_PR_NewType("Variant", ev_variant, false); } else if (QCC_PR_CheckName("vect")) //this can only be of vector sizes, so... { sprintf(argname, "arg%i", ftype->num_parms); name = argname; - nptype = QCC_PR_NewType("Vector", ev_vector); + nptype = QCC_PR_NewType("Vector", ev_vector, false); } else { name = QCC_PR_ParseName(); QCC_PR_Expect(":"); - nptype = QCC_PR_ParseType(true); + nptype = QCC_PR_ParseType(true, false); } if (nptype->type == ev_void) @@ -3207,26 +3323,34 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) } QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto) { - QCC_type_t *ptype; - char name[128]; - sprintf(name, "*%s", pointsto->name); - ptype = QCC_PR_NewType(name, ev_pointer); + QCC_type_t *ptype, *e; + ptype = QCC_PR_NewType("ptr", ev_pointer, false); ptype->aux_type = pointsto; - return QCC_PR_FindType (ptype); + e = QCC_PR_FindType (ptype); + if (e == ptype) + { + char name[128]; + sprintf(name, "ptr to %s", pointsto->name); + e->name = strdup(name); + } + return e; } QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto) { QCC_type_t *ptype; char name[128]; sprintf(name, "FIELD TYPE(%s)", pointsto->name); - ptype = QCC_PR_NewType(name, ev_field); + ptype = QCC_PR_NewType(name, ev_field, false); ptype->aux_type = pointsto; ptype->size = ptype->aux_type->size; return QCC_PR_FindType (ptype); } pbool type_inlinefunction; -QCC_type_t *QCC_PR_ParseType (int newtype) +/*newtype=true: creates a new type always + silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL +*/ +QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) { QCC_type_t *newparm; QCC_type_t *newt; @@ -3240,14 +3364,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype) if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges) { - newt = QCC_PR_NewType("FIELD TYPE", ev_field); - newt->aux_type = QCC_PR_ParseType (false); + newt = QCC_PR_NewType("FIELD TYPE", ev_field, false); + newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; newt = QCC_PR_FindType (newt); - type = QCC_PR_NewType("FIELD TYPE", ev_field); + type = QCC_PR_NewType("FIELD TYPE", ev_field, false); type->aux_type = newt; type->size = type->aux_type->size; @@ -3258,8 +3382,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype) } if (QCC_PR_CheckToken (".")) { - newt = QCC_PR_NewType("FIELD TYPE", ev_field); - newt->aux_type = QCC_PR_ParseType (false); + newt = QCC_PR_NewType("FIELD TYPE", ev_field, false); + newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; @@ -3286,6 +3410,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype) /* Look to see if this type is already defined */ for(i=0;isize=type_entity->size; @@ -3333,7 +3459,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) // if (QCC_PR_CheckToken(",")) // type->next = QCC_PR_NewType(type->name, type->type); // else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (newparm->type == ev_struct || newparm->type == ev_union) //we wouldn't be able to handle it. QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname); @@ -3354,10 +3480,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype) newparm->name = QCC_CopyString("")+strings; sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name); - fieldtype = QCC_PR_NewType(newparm->name, ev_field); + fieldtype = QCC_PR_NewType(newparm->name, ev_field, false); fieldtype->aux_type = newparm; fieldtype->size = newparm->size; - QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 1, false); + QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false); newparm->ofs = 0;//newt->size; @@ -3377,7 +3503,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) } if (QCC_PR_CheckKeyword (keyword_struct, "struct")) { - newt = QCC_PR_NewType("struct", ev_struct); + newt = QCC_PR_NewType("struct", ev_struct, false); newt->size=0; QCC_PR_Expect("{"); @@ -3392,10 +3518,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype) { if (!newparm) QCC_PR_ParseError(ERR_NOTANAME, "element missing type"); - newparm = QCC_PR_NewType(newparm->name, newparm->type); + newparm = QCC_PR_NewType(newparm->name, newparm->type, false); } else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (!QCC_PR_CheckToken(";")) { @@ -3403,8 +3529,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) QCC_PR_Lex(); if (QCC_PR_CheckToken("[")) { - newparm->size*=atoi(pr_token); - QCC_PR_Lex(); + newparm->arraysize=QCC_PR_IntConstExpr(); QCC_PR_Expect("]"); } QCC_PR_CheckToken(";"); @@ -3412,7 +3537,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) else newparm->name = QCC_CopyString("")+strings; newparm->ofs = newt->size; - newt->size += newparm->size; + newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1); newt->num_parms++; if (type) @@ -3425,7 +3550,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) } if (QCC_PR_CheckKeyword (keyword_union, "union")) { - newt = QCC_PR_NewType("union", ev_union); + newt = QCC_PR_NewType("union", ev_union, false); newt->size=0; QCC_PR_Expect("{"); @@ -3435,25 +3560,34 @@ QCC_type_t *QCC_PR_ParseType (int newtype) newparm = NULL; while (!QCC_PR_CheckToken("}")) { + int arraysize; if (QCC_PR_CheckToken(",")) { if (!newparm) QCC_PR_ParseError(ERR_NOTANAME, "element missing type"); - newparm = QCC_PR_NewType(newparm->name, newparm->type); + newparm = QCC_PR_NewType(newparm->name, newparm->type, false); } else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (QCC_PR_CheckToken(";")) newparm->name = QCC_CopyString("")+strings; else { newparm->name = QCC_CopyString(pr_token)+strings; QCC_PR_Lex(); + if (QCC_PR_CheckToken("[")) + { + newparm->arraysize=QCC_PR_IntConstExpr(); + QCC_PR_Expect("]"); + } QCC_PR_Expect(";"); } newparm->ofs = 0; - if (newparm->size > newt->size) - newt->size = newparm->size; + arraysize = newparm->arraysize; + if (!arraysize) + arraysize = 1; + if (newparm->size*arraysize > newt->size) + newt->size = newparm->size*arraysize; newt->num_parms++; if (type) @@ -3467,6 +3601,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype) type = NULL; for (i = 0; i < numtypeinfos; i++) { + if (!qcc_typeinfo[i].typedefed) + continue; if (!STRCMP(qcc_typeinfo[i].name, name)) { type = &qcc_typeinfo[i]; @@ -3492,16 +3628,22 @@ QCC_type_t *QCC_PR_ParseType (int newtype) type = type_function; else { + if (silentfail) + return NULL; + QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name); type = type_float; // shut up compiler warning } } QCC_PR_Lex (); + while (QCC_PR_CheckToken("*")) + type = QCC_PointerTypeTo(type); + if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function. { type_inlinefunction = true; - return QCC_PR_ParseFunctionType(newtype, type); + type = QCC_PR_ParseFunctionType(newtype, type); } else { @@ -3509,9 +3651,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype) { type = QCC_PR_DuplicateType(type); } - - return type; } + return type; } #endif diff --git a/misc/source/fteqcc-src/qccgui.c b/misc/source/fteqcc-src/qccgui.c index e6fb7bd0..9bcd9077 100644 --- a/misc/source/fteqcc-src/qccgui.c +++ b/misc/source/fteqcc-src/qccgui.c @@ -4,19 +4,18 @@ #include #include #include +#include #include "qcc.h" #include "gui.h" - - /* ============== LoadFile ============== */ -unsigned char *QCC_ReadFile (char *fname, void *buffer, int len) +unsigned char *QCC_ReadFile (const char *fname, void *buffer, int len) { long length; FILE *f; @@ -31,7 +30,7 @@ unsigned char *QCC_ReadFile (char *fname, void *buffer, int len) return buffer; } -int QCC_FileSize (char *fname) +int QCC_FileSize (const char *fname) { long length; FILE *f; @@ -45,7 +44,7 @@ int QCC_FileSize (char *fname) return length; } -pbool QCC_WriteFile (char *name, void *data, int len) +pbool QCC_WriteFile (const char *name, void *data, int len) { long length; FILE *f; @@ -281,11 +280,14 @@ typedef struct editor_s { char filename[MAX_PATH]; //abs HWND window; HWND editpane; + pbool modified; + time_t filemodifiedtime; struct editor_s *next; } editor_t; editor_t *editors; +void EditorReload(editor_t *editor); int EditorSave(editor_t *edit); void EditFile(char *name, int line); pbool EditorModified(editor_t *e); @@ -318,7 +320,7 @@ void GenericMenu(WPARAM wParam) break; case IDM_ABOUT: - MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\nBasically that means it was written by Spike.\n\nIt has a few cool features, like a useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0); + MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\n\nIt has a few cool features, like a semi-useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0); break; case IDM_CASCADE: @@ -409,7 +411,7 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message, { case WM_CLOSE: case WM_QUIT: - if (EditorModified(editor)) + if (editor->modified) { switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL)) { @@ -478,22 +480,49 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message, return TRUE; break; case WM_COMMAND: - if (mdibox) - goto gdefault; - EditorMenu(editor, wParam); + if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == editor->editpane) + { + if (!editor->modified) + { + char title[2048]; + CHARRANGE chrg; + + editor->modified = true; + if (EditorModified(editor)) + if (MessageBox(NULL, "warning: file was modified externally. reload?", "Modified!", MB_YESNO) == IDYES) + EditorReload(editor); + + + SendMessage(editor->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg); + if (editor->modified) + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + else + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + SetWindowText(editor->window, title); + } + } + else + { + if (mdibox) + goto gdefault; + EditorMenu(editor, wParam); + } break; case WM_NOTIFY: { NMHDR *nmhdr; SELCHANGE *sel; - char message[2048]; + char title[2048]; nmhdr = (NMHDR *)lParam; switch(nmhdr->code) { case EN_SELCHANGE: sel = (SELCHANGE *)nmhdr; - sprintf(message, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); - SetWindowText(editor->window, message); + if (editor->modified) + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + else + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + SetWindowText(editor->window, title); break; } } @@ -758,7 +787,7 @@ int Rehighlight(editor_t *edit) InvalidateRect(edit->editpane, NULL, true); InvalidateRect(edit->window, NULL, true); - SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE); + SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos); SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg); @@ -845,11 +874,46 @@ int Rehighlight(editor_t *edit) } #endif -void EditFile(char *name, int line) +void EditorReload(editor_t *editor) { - char title[1024]; + struct stat sbuf; int flen; char *file; + + flen = QCC_FileSize(editor->filename); + if (flen >= 0) + { + file = malloc(flen+1); + QCC_ReadFile(editor->filename, file, flen); + file[flen] = 0; + } + + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0); + + /*clear it out*/ + Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane)); + Edit_ReplaceSel(editor->editpane,""); + + if (!fl_autohighlight) + { + GUIPrint(editor->editpane, file); + } + else + { + GUIFormattingPrint(editor->editpane, file); + } + free(file); + + editor->modified = false; + stat(editor->filename, &sbuf); + editor->filemodifiedtime = sbuf.st_mtime; + + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); +} + +void EditFile(char *name, int line) +{ + char title[1024]; editor_t *neweditor; WNDCLASS wndclass; HMENU menu, menufile, menuhelp, menunavig; @@ -871,8 +935,7 @@ void EditFile(char *name, int line) } } - flen = QCC_FileSize(name); - if (flen == -1) + if (QCC_FileSize(name) == -1) { MessageBox(NULL, "File not found.", "Error", 0); return; @@ -896,9 +959,9 @@ void EditFile(char *name, int line) menufile = CreateMenu(); menuhelp = CreateMenu(); menunavig = CreateMenu(); - AppendMenu(menu, MF_POPUP, (UINT)menufile, "&File"); - AppendMenu(menu, MF_POPUP, (UINT)menunavig, "&Navigation"); - AppendMenu(menu, MF_POPUP, (UINT)menuhelp, "&Help"); + AppendMenu(menu, MF_POPUP, (UINT_PTR)menufile, "&File"); + AppendMenu(menu, MF_POPUP, (UINT_PTR)menunavig, "&Navigation"); + AppendMenu(menu, MF_POPUP, (UINT_PTR)menuhelp, "&Help"); AppendMenu(menufile, 0, IDM_OPENNEW, "Open &new file "); AppendMenu(menufile, 0, IDM_SAVE, "&Save "); // AppendMenu(menufile, 0, IDM_FIND, "&Find"); @@ -940,7 +1003,7 @@ void EditFile(char *name, int line) mcs.lParam = 0; neweditor->window = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, - (LONG) (LPMDICREATESTRUCT) &mcs); + (LONG_PTR) (LPMDICREATESTRUCT) &mcs); } else { @@ -959,23 +1022,7 @@ void EditFile(char *name, int line) return; } - flen = QCC_FileSize(name); - file = malloc(flen+1); - QCC_ReadFile(name, file, flen); - file[flen] = 0; - - SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, 0); - - if (!fl_autohighlight) - { - GUIPrint(neweditor->editpane, file); - } - else - { - GUIFormattingPrint(neweditor->editpane, file); - } - - SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE); + EditorReload(neweditor); if (line >= 0) Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)); @@ -992,6 +1039,7 @@ void EditFile(char *name, int line) int EditorSave(editor_t *edit) { + struct stat sbuf; int len; char *file; len = Edit_GetTextLength(edit->editpane); @@ -1009,6 +1057,11 @@ int EditorSave(editor_t *edit) } free(file); + /*now whatever is on disk should have the current time*/ + edit->modified = false; + stat(edit->filename, &sbuf); + edit->filemodifiedtime = sbuf.st_mtime; + return true; } void EditorsRun(void) @@ -1016,7 +1069,7 @@ void EditorsRun(void) } -char *GUIReadFile(char *fname, void *buffer, int blen) +char *GUIReadFile(const char *fname, void *buffer, int blen) { editor_t *e; for (e = editors; e; e = e->next) @@ -1032,7 +1085,7 @@ char *GUIReadFile(char *fname, void *buffer, int blen) return QCC_ReadFile(fname, buffer, blen); } -int GUIFileSize(char *fname) +int GUIFileSize(const char *fname) { editor_t *e; for (e = editors; e; e = e->next) @@ -1046,26 +1099,14 @@ int GUIFileSize(char *fname) return QCC_FileSize(fname); } +/*checks if the file has been modified externally*/ pbool EditorModified(editor_t *e) { - char *buffer; - int elen, flen; - elen = Edit_GetTextLength(e->editpane); - flen = QCC_FileSize(e->filename); - - if (elen != flen) + struct stat sbuf; + stat(e->filename, &sbuf); + if (e->filemodifiedtime != sbuf.st_mtime) return true; - buffer = malloc(elen+flen); - Edit_GetText(e->editpane, buffer, elen); - QCC_ReadFile(e->filename, buffer+elen, flen); - if (memcmp(buffer, buffer+elen, elen)) - { - free(buffer); - return true; - } - free(buffer); - return false; } @@ -1559,20 +1600,20 @@ static LONG CALLBACK MainWndProc(HWND hWnd,UINT message, HMENU rootmenu, windowmenu, m; rootmenu = CreateMenu(); - AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()), "&File"); + AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&File"); AppendMenu(m, 0, IDM_OPENNEW, "Open &new file "); AppendMenu(m, 0, IDM_SAVE, "&Save "); // AppendMenu(m, 0, IDM_FIND, "&Find"); AppendMenu(m, 0, IDM_UNDO, "&Undo Ctrl+Z"); AppendMenu(m, 0, IDM_REDO, "&Redo Ctrl+Y"); - AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()), "&Navigation"); + AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&Navigation"); AppendMenu(m, 0, IDM_GOTODEF, "Go to definition"); AppendMenu(m, 0, IDM_OPENDOCU, "Open selected file"); - AppendMenu(rootmenu, MF_POPUP, (UINT)(m = windowmenu = CreateMenu()), "&Window"); + AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = windowmenu = CreateMenu()), "&Window"); AppendMenu(m, 0, IDM_CASCADE, "&Cascade"); AppendMenu(m, 0, IDM_TILE_HORIZ, "Tile &Horizontally"); AppendMenu(m, 0, IDM_TILE_VERT, "Tile &Vertically"); - AppendMenu(rootmenu, MF_POPUP, (UINT)(m = CreateMenu()), "&Help"); + AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&Help"); AppendMenu(m, 0, IDM_ABOUT, "About"); SetMenu(hWnd, rootmenu); @@ -1893,11 +1934,46 @@ int GUIprintf(const char *msg, ...) void Sys_Error(const char *text, ...); void RunCompiler(char *args) { - char *argv[64]; + char *argv[128]; int argc; progexterns_t ext; progfuncs_t funcs; + editor_t *editor; + for (editor = editors; editor; editor = editor->next) + { + if (editor->modified) + { + if (EditorModified(editor)) + { + char msg[1024]; + sprintf(msg, "%s is modified in both memory and on disk. Overwrite external modification? (saying no will reload from disk)", editor->filename); + switch(MessageBox(NULL, msg, "Modification conflict", MB_YESNOCANCEL)) + { + case IDYES: + EditorSave(editor); + break; + case IDNO: + EditorReload(editor); + break; + case IDCANCEL: + break; /*compiling will use whatever is in memory*/ + } + } + else + { + /*not modified on disk, but modified in memory? try and save it, cos we might as well*/ + EditorSave(editor); + } + } + else + { + /*modified on disk but not in memory? just reload it off disk*/ + if (EditorModified(editor)) + EditorReload(editor); + } + } + memset(&funcs, 0, sizeof(funcs)); funcs.parms = &ext; memset(&ext, 0, sizeof(ext)); @@ -1957,7 +2033,7 @@ void CreateOutputWindow(void) mcs.lParam = 0; outputwindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, - (LONG) (LPMDICREATESTRUCT) &mcs); + (LONG_PTR) (LPMDICREATESTRUCT) &mcs); ShowWindow(outputwindow, SW_SHOW); } diff --git a/misc/source/fteqcc-src/qccmain.c b/misc/source/fteqcc-src/qccmain.c index cad17a6c..8c849307 100644 --- a/misc/source/fteqcc-src/qccmain.c +++ b/misc/source/fteqcc-src/qccmain.c @@ -27,8 +27,6 @@ void QCC_PR_LexWhitespace (void); void *FS_ReadToMem(char *fname, void *membuf, int *len); void FS_CloseFromMem(void *mem); -struct qcc_includechunk_s *currentchunk; - unsigned int MAX_REGS; int MAX_STRINGS; @@ -78,14 +76,17 @@ int numfielddefs; PATHSTRING *precache_sounds; int *precache_sounds_block; +int *precache_sounds_used; int numsounds; PATHSTRING *precache_textures; int *precache_textures_block; +int *precache_textures_block; int numtextures; PATHSTRING *precache_models; int *precache_models_block; +int *precache_models_used; int nummodels; PATHSTRING *precache_files; @@ -96,11 +97,13 @@ extern int numCompilerConstants; hashtable_t compconstantstable; hashtable_t globalstable; hashtable_t localstable; +#ifdef WRITEASM +FILE *asmfile; +#endif hashtable_t floatconstdefstable; hashtable_t stringconstdefstable; -hashtable_t stringconstdefstable_dotranslate; -int dotranslate; -int dotranslate_count; +hashtable_t stringconstdefstable_trans; +extern int dotranslate_count; pbool qccwarningdisabled[WARN_MAX]; @@ -184,7 +187,7 @@ optimisations_t optimisations[] = {&opt_return_only, "ro", 3, FLAG_KILLSDEBUGGERS, "return_only", "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."}, {&opt_compound_jumps, "cj", 3, FLAG_KILLSDEBUGGERS, "compound_jumps", "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."}, // {&opt_comexprremoval, "cer", 4, 0, "expression_removal", "Eliminate common sub-expressions"}, //this would be too hard... - {&opt_stripfunctions, "sf", 3, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games."}, + {&opt_stripfunctions, "sf", 4, 0, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games. This can affect FTE_MULTIPROGS."}, {&opt_locals_marshalling, "lm", 4, FLAG_KILLSDEBUGGERS, "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."}, {&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."}, {NULL} @@ -215,6 +218,7 @@ compiler_flag_t compiler_flag[] = { {&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output. {&keyword_shared, defaultkeyword, "shared", "Keyword: shared", "Disables the 'shared' keyword."}, //mark global to be copied over when progs changes (part of FTE_MULTIPROGS) {&keyword_state, nondefaultkeyword,"state", "Keyword: state", "Disables the 'state' keyword."}, + {&keyword_optional, defaultkeyword,"optional", "Keyword: optional", "Disables the 'optional' keyword."}, {&keyword_string, defaultkeyword, "string", "Keyword: string", "Disables the 'string' keyword."}, {&keyword_struct, defaultkeyword, "struct", "Keyword: struct", "Disables the 'struct' keyword."}, {&keyword_switch, defaultkeyword, "switch", "Keyword: switch", "Disables the 'switch' keyword."}, @@ -241,7 +245,9 @@ compiler_flag_t compiler_flag[] = { {&flag_filetimes, 0, "filetimes", "Check Filetimes", "Recompiles the progs only if the file times are modified."}, {&flag_fasttrackarrays, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"fastarrays","fast arrays where possible", "Generates extra instructions inside array handling functions to detect engine and use extension opcodes only in supporting engines.\nAdds a global which is set by the engine if the engine supports the extra opcodes. Note that this applies to all arrays or none."}, {&flag_assume_integer, FLAG_MIDCOMPILE,"assumeint", "Assume Integers", "Numerical constants are assumed to be integers, instead of floats."}, - {&pr_subscopedlocals, FLAG_MIDCOMPILE, "subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."}, + {&pr_subscopedlocals, FLAG_MIDCOMPILE,"subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."}, + {&verbose, FLAG_MIDCOMPILE,"verbose", "Verbose", "Lots of extra compiler messages."}, + {&flag_typeexplicit, FLAG_MIDCOMPILE,"typeexplicit", "Explicit types", "All type conversions must be explicit or directly supported by instruction set."}, {NULL} }; @@ -313,11 +319,13 @@ int QCC_CopyString (char *str) int old; char *s; + if (!str) + return 0; + if (!*str) + return 1; + if (opt_noduplicatestrings) { - if (!str || !*str) - return 0; - for (s = strings; s < strings+strofs; s++) if (!strcmp(s, str)) { @@ -482,7 +490,7 @@ void QCC_InitData (void) qcc_sourcefile = NULL; numstatements = 1; - strofs = 1; + strofs = 2; numfunctions = 1; numglobaldefs = 1; numfielddefs = 1; @@ -516,7 +524,7 @@ int WriteBodylessFuncs (int handle) { if (d->type->type == ev_function && !d->scope)// function parms are ok { - if (d->initialized != 1 && d->references>0) + if (!(d->initialized & 1) && d->references>0) { SafeWrite(handle, d->name, strlen(d->name)+1); ret++; @@ -648,8 +656,8 @@ pbool QCC_WriteData (int crc) if (compressoutput) progs.blockscompressed |=64; //line numbers if (compressoutput) progs.blockscompressed |=128; //types //include a type block? - types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES"); //useful for debugging and saving (maybe, anyway...). - if (sizeof(char *) != sizeof(string_t)) + types = debugtarget; + if (types && sizeof(char *) != sizeof(string_t)) { //qcc_typeinfo_t has a char* inside it, which changes size printf("AMD64 builds cannot write typeinfo structures\n"); @@ -692,6 +700,18 @@ pbool QCC_WriteData (int crc) for (def = pr.def_head.next ; def ; def = def->next) { + if ((def->type->type == ev_struct || def->type->type == ev_union || def->arraysize) && def->deftail) + { + QCC_def_t *d; + d = def; + while (d != def->deftail) + { + d = d->next; + h = d->references; + d->references += def->references; + def->references += h; + } + } if (def->type->type == ev_vector || (def->type->type == ev_field && def->type->aux_type->type == ev_vector)) { //do the references, so we don't get loadsa not referenced VEC_HULL_MINS_x sprintf(element, "%s_x", def->name); @@ -727,14 +747,14 @@ pbool QCC_WriteData (int crc) } if (def->references<=0) { - if (def->constant) - QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s no references", def->name); - else - QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s no references", def->name); - if (!warnedunref) + int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED; + if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references", def->name)) { - QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message."); - warnedunref = true; + if (!warnedunref) + { + QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message."); + warnedunref = true; + } } if (opt_unreferenced && def->type->type != ev_field) @@ -770,13 +790,15 @@ pbool QCC_WriteData (int crc) } else if (def->type->type == ev_field && def->constant) { + if (numfielddefs >= MAX_FIELDS) + QCC_PR_ParseError(0, "Too many fields. Limit is %u\n", MAX_FIELDS); dd = &fields[numfielddefs]; numfielddefs++; dd->type = def->type->aux_type->type; dd->s_name = QCC_CopyString (def->name); dd->ofs = G_INT(def->ofs); } - else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings)) + else if ((def->scope||def->constant) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings))) { if (opt_constant_names) { @@ -831,9 +853,10 @@ pbool QCC_WriteData (int crc) continue; if (dd->ofs == qcc_globals[h].ofs) { - if (dd->type != qcc_globals[h].type) + if ((dd->type&~DEF_SAVEGLOBAL) != (qcc_globals[h].type&~DEF_SAVEGLOBAL)) { - if (dd->type != ev_vector && qcc_globals[h].type != ev_float) + if (!(((dd->type&~DEF_SAVEGLOBAL) == ev_vector && (qcc_globals[h].type&~DEF_SAVEGLOBAL) == ev_float) || + ((dd->type&~DEF_SAVEGLOBAL) == ev_struct || (dd->type&~DEF_SAVEGLOBAL) == ev_union))) QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name); } //remove the saveglobal flag on the duplicate globals. @@ -1593,7 +1616,7 @@ PR_PrintDefs QCC_PR_PrintOfs (d->ofs); }*/ -QCC_type_t *QCC_PR_NewType (char *name, int basictype) +QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed) { if (numtypeinfos>= maxtypeinfos) QCC_Error(ERR_TOOMANYTYPES, "Too many types"); @@ -1603,6 +1626,8 @@ QCC_type_t *QCC_PR_NewType (char *name, int basictype) qcc_typeinfo[numtypeinfos].num_parms = 0; qcc_typeinfo[numtypeinfos].param = NULL; qcc_typeinfo[numtypeinfos].size = type_size[basictype]; + qcc_typeinfo[numtypeinfos].arraysize = 0; + qcc_typeinfo[numtypeinfos].typedefed = typedefed; numtypeinfos++; @@ -1638,40 +1663,44 @@ void QCC_PR_BeginCompilation (void *memory, int memsize) pr_global_defs[i] = &def_void; */ - type_void = QCC_PR_NewType("void", ev_void); - type_string = QCC_PR_NewType("string", ev_string); - type_float = QCC_PR_NewType("float", ev_float); - type_vector = QCC_PR_NewType("vector", ev_vector); - type_entity = QCC_PR_NewType("entity", ev_entity); - type_field = QCC_PR_NewType("field", ev_field); - type_function = QCC_PR_NewType("function", ev_function); - type_pointer = QCC_PR_NewType("pointer", ev_pointer); - type_integer = QCC_PR_NewType("__integer", ev_integer); - type_variant = QCC_PR_NewType("__variant", ev_variant); - - type_floatfield = QCC_PR_NewType("fieldfloat", ev_field); + type_void = QCC_PR_NewType("void", ev_void, true); + type_string = QCC_PR_NewType("string", ev_string, true); + type_float = QCC_PR_NewType("float", ev_float, true); + type_vector = QCC_PR_NewType("vector", ev_vector, true); + type_entity = QCC_PR_NewType("entity", ev_entity, true); + type_field = QCC_PR_NewType("__field", ev_field, false); + type_function = QCC_PR_NewType("__function", ev_function, false); + type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false); + type_integer = QCC_PR_NewType("__integer", ev_integer, true); + type_variant = QCC_PR_NewType("variant", ev_variant, true); + type_variant = QCC_PR_NewType("__variant", ev_variant, true); + + type_floatfield = QCC_PR_NewType("fieldfloat", ev_field, false); type_floatfield->aux_type = type_float; - type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float); + type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float, false); + + type_intpointer = QCC_PR_NewType("__intpointer", ev_pointer, false); + type_intpointer->aux_type = type_integer; + type_floatpointer = QCC_PR_NewType("__floatpointer", ev_pointer, false); + type_floatpointer->aux_type = type_float; type_function->aux_type = type_void; //type_field->aux_type = type_float; - if (keyword_integer) - type_integer = QCC_PR_NewType("integer", ev_integer); - if (keyword_int) - type_integer = QCC_PR_NewType("int", ev_integer); + type_integer = QCC_PR_NewType("integer", ev_integer, keyword_integer?true:false); + type_integer = QCC_PR_NewType("int", ev_integer, keyword_integer?true:false); if (output_parms) { //this tends to confuse the brains out of decompilers. :) numpr_globals = 1; - QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++; + QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 0, false)->references++; for (i = 0; i < MAX_PARMS; i++) { sprintf(name, "PARM%i", i); - QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++; + QCC_PR_GetDef(type_vector, name, NULL, true, 0, false)->references++; } } else @@ -1733,11 +1762,12 @@ int QCC_PR_FinishCompilation (void) } else { - QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name); + QCC_PR_ParseWarning(ERR_NOFUNC, "function %s was not defined",d->name); + QCC_PR_ParsePrintDef(ERR_NOFUNC, d); bodylessfuncs = true; errors = true; } - s_file = NULL; + s_file = 0; // errors = true; } else if (d->initialized==2) @@ -1870,6 +1900,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) QCC_def_t *d; int f; unsigned short crc; + QCC_def_t *ld; // int c; file[0] = '\0'; @@ -1904,6 +1935,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS)); for (d=pr.def_head.next ; d ; d=d->next) { + ld = d; if (!strcmp (d->name, "end_sys_globals")) break; if (d->ofsname)); - d=d->next->next->next; // skip the elements + if (d->deftail) + d=d->deftail; // skip the elements break; case ev_string: ADD(qcva("\tstring_t\t%s;\n",d->name)); @@ -1956,7 +1989,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) break; case ev_vector: ADD(qcva("\tvec3_t\t%s;\n",d->name)); - d=d->next->next->next; // skip the elements + if (d->deftail) + d=d->deftail; // skip the elements break; case ev_string: ADD(qcva("\tstring_t\t%s;\n",d->name)); @@ -2755,6 +2789,7 @@ void QCC_SetDefaultProperties (void) qccwarningdisabled[WARN_FTE_SPECIFIC] = true; qccwarningdisabled[WARN_EXTENSION_USED] = true; qccwarningdisabled[WARN_IFSTRING_USED] = true; + qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true; @@ -2866,10 +2901,10 @@ void QCC_main (int argc, char **argv) //as part of the quake engine pHash_GetNext = &Hash_GetNext; pHash_Add = &Hash_Add; - MAX_REGS = 65536; + MAX_REGS = 1<<17; MAX_STRINGS = 1000000; - MAX_GLOBALS = 65535; - MAX_FIELDS = 2048; + MAX_GLOBALS = 1<<17; + MAX_FIELDS = 1<<12; MAX_STATEMENTS = 0x80000; MAX_FUNCTIONS = 16384; maxtypeinfos = 16384; @@ -2977,7 +3012,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine QCC_PurgeTemps(); strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS); - strofs = 1; + strofs = 2; statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS); numstatements = 0; @@ -2991,13 +3026,12 @@ void QCC_main (int argc, char **argv) //as part of the quake engine qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS); numpr_globals=0; - Hash_InitTable(&globalstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS))); - Hash_InitTable(&localstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS))); - Hash_InitTable(&floatconstdefstable, MAX_REGS+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS+1))); - Hash_InitTable(&stringconstdefstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS))); - Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS))); - dotranslate=0; - dotranslate_count=0; + Hash_InitTable(&globalstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2))); + Hash_InitTable(&localstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2))); + Hash_InitTable(&floatconstdefstable, MAX_REGS/2+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2+1))); + Hash_InitTable(&stringconstdefstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2))); + Hash_InitTable(&stringconstdefstable_trans, 1000, qccHunkAlloc(Hash_BytesForBuckets(1000))); + dotranslate_count = 0; // pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS); diff --git a/misc/source/fteqcc-src/qcdecomp.c b/misc/source/fteqcc-src/qcdecomp.c index 24fc433f..8e0b2788 100644 --- a/misc/source/fteqcc-src/qcdecomp.c +++ b/misc/source/fteqcc-src/qcdecomp.c @@ -51,9 +51,11 @@ extern QCC_type_t *type_function;// = {ev_function/*, &def_function*/,NULL,&type // type_function is a void() function used for state defs extern QCC_type_t *type_pointer;// = {ev_pointer/*, &def_pointer*/}; extern QCC_type_t *type_integer;// = {ev_integer/*, &def_integer*/}; +extern QCC_type_t *type_floatpointer; +extern QCC_type_t *type_intpointer; extern QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float}; -QCC_type_t *QCC_PR_NewType (char *name, int basictype); +QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed); jmp_buf decompilestatementfailure; @@ -763,21 +765,21 @@ void FigureOutTypes(progfuncs_t *progfuncs) memset(ofstype, 0, sizeof(*ofstype)*65535); memset(ofsflags, 0, sizeof(*ofsflags)*65535); - type_void = QCC_PR_NewType("void", ev_void); - type_string = QCC_PR_NewType("string", ev_string); - type_float = QCC_PR_NewType("float", ev_float); - type_vector = QCC_PR_NewType("vector", ev_vector); - type_entity = QCC_PR_NewType("entity", ev_entity); - type_field = QCC_PR_NewType("field", ev_field); - type_function = QCC_PR_NewType("function", ev_function); - type_pointer = QCC_PR_NewType("pointer", ev_pointer); - type_integer = QCC_PR_NewType("integer", ev_integer); + type_void = QCC_PR_NewType("void", ev_void, true); + type_string = QCC_PR_NewType("string", ev_string, true); + type_float = QCC_PR_NewType("float", ev_float, true); + type_vector = QCC_PR_NewType("vector", ev_vector, true); + type_entity = QCC_PR_NewType("entity", ev_entity, true); + type_field = QCC_PR_NewType("field", ev_field, false); + type_function = QCC_PR_NewType("function", ev_function, false); + type_pointer = QCC_PR_NewType("pointer", ev_pointer, false); + type_integer = QCC_PR_NewType("integer", ev_integer, true); // type_variant = QCC_PR_NewType("__variant", ev_variant); - type_floatfield = QCC_PR_NewType("fieldfloat", ev_field); + type_floatfield = QCC_PR_NewType("fieldfloat", ev_field, false); type_floatfield->aux_type = type_float; - type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float); + type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float, false); type_function->aux_type = type_void; diff --git a/misc/source/fteqcc-src/qcc.dsp b/misc/source/fteqcc-src/vc6/qcc.dsp similarity index 69% rename from misc/source/fteqcc-src/qcc.dsp rename to misc/source/fteqcc-src/vc6/qcc.dsp index f5af89c8..62c6bfe3 100644 --- a/misc/source/fteqcc-src/qcc.dsp +++ b/misc/source/fteqcc-src/vc6/qcc.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 ../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../fteqcc.exe" +# ADD LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../fteqcc.exe" !ELSEIF "$(CFG)" == "qcc - Win32 Debug" @@ -76,7 +76,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 ..\libs\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../fteqcc_dbg.exe" /pdbtype:sept +# ADD LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../fteqcc_dbg.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "qcc - Win32 GUIDebug" @@ -100,8 +100,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 ..\libs\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../fteqcc.exe" /pdbtype:sept -# ADD LINK32 ..\libs\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib comdlg32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"..\..\fteqcc.exe" /pdbtype:sept +# ADD BASE LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../fteqcc.exe" /pdbtype:sept +# ADD LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib comdlg32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"..\..\fteqcc.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "qcc - Win32 GUIRelease" @@ -126,8 +126,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 ../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../../fteqcc.exe" -# ADD LINK32 ../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386 /out:"../../fteqccgui.exe" +# ADD BASE LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../../../fteqcc.exe" +# ADD LINK32 ../../libs/zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386 /out:"../../fteqccgui.exe" # SUBTRACT LINK32 /pdb:none !ENDIF @@ -143,32 +143,32 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File -SOURCE=.\Comprout.c +SOURCE=..\Comprout.c # End Source File # Begin Source File -SOURCE=.\hash.c +SOURCE=..\hash.c # End Source File # Begin Source File -SOURCE=.\qcc_cmdlib.c +SOURCE=..\qcc_cmdlib.c # End Source File # Begin Source File -SOURCE=.\qcc_gtk.c +SOURCE=..\qcc_gtk.c # PROP Exclude_From_Build 1 # End Source File # Begin Source File -SOURCE=.\qcc_pr_comp.c +SOURCE=..\qcc_pr_comp.c # End Source File # Begin Source File -SOURCE=.\qcc_pr_lex.c +SOURCE=..\qcc_pr_lex.c # End Source File # Begin Source File -SOURCE=.\qccgui.c +SOURCE=..\qccgui.c !IF "$(CFG)" == "qcc - Win32 Release" @@ -187,7 +187,7 @@ SOURCE=.\qccgui.c # End Source File # Begin Source File -SOURCE=.\qccguistuff.c +SOURCE=..\qccguistuff.c !IF "$(CFG)" == "qcc - Win32 Release" @@ -206,11 +206,11 @@ SOURCE=.\qccguistuff.c # End Source File # Begin Source File -SOURCE=.\QccMain.c +SOURCE=..\QccMain.c # End Source File # Begin Source File -SOURCE=.\qcctui.c +SOURCE=..\qcctui.c !IF "$(CFG)" == "qcc - Win32 Release" @@ -229,7 +229,7 @@ SOURCE=.\qcctui.c # End Source File # Begin Source File -SOURCE=.\qcd_main.c +SOURCE=..\qcd_main.c # End Source File # End Group # Begin Group "Header Files" @@ -237,15 +237,15 @@ SOURCE=.\qcd_main.c # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File -SOURCE=.\gui.h +SOURCE=..\gui.h # End Source File # Begin Source File -SOURCE=.\pr_comp.h +SOURCE=..\pr_comp.h # End Source File # Begin Source File -SOURCE=.\qcc.h +SOURCE=..\qcc.h # End Source File # End Group # Begin Group "Resource Files" diff --git a/misc/source/fteqcc-src/vc6/qcc.dsw b/misc/source/fteqcc-src/vc6/qcc.dsw new file mode 100644 index 00000000..4b65a4d2 --- /dev/null +++ b/misc/source/fteqcc-src/vc6/qcc.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "qcc"=".\qcc.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + -- 2.39.2