From d474f48fd1f06edc830298dac4cd86a140e9f527 Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 18 Jul 2018 13:02:03 +0000 Subject: [PATCH] rework class fields a little - fields now map onto a single underlaying array symbol, which avoids the need for differently sized underlaying arrays per member that were then conflicting between classes. tweak the decompiler to deal with fte-optimised progs a little better. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5272 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/decomp.c | 249 +++++++++++++++++++++++++++---------- engine/qclib/qcc.h | 1 + engine/qclib/qcc_pr_comp.c | 95 +------------- engine/qclib/qcc_pr_lex.c | 21 ++-- engine/qclib/qccmain.c | 23 ++++ 5 files changed, 226 insertions(+), 163 deletions(-) diff --git a/engine/qclib/decomp.c b/engine/qclib/decomp.c index 0e882509..122161a3 100644 --- a/engine/qclib/decomp.c +++ b/engine/qclib/decomp.c @@ -91,12 +91,12 @@ char *type_names[] = "ev_quat", "ev_uinteger" }; -char *typetoname(QCC_type_t *type) +const char *typetoname(QCC_type_t *type) { return type->name; } -char *temp_type (int temp, dstatement_t *start, dfunction_t *df) +const char *temp_type (int temp, dstatement_t *start, dfunction_t *df) { int i; dstatement_t *stat; @@ -452,7 +452,7 @@ static struct { {80, "infokey", &type_string, {&type_entity, &type_string}, "string(entity e, string key)"}, {81, "stof", &type_float, {&type_string}, "float(string s)"}, {82, "multicast", NULL, {&type_vector, &type_float}, "void(vector where, float set)"}, - +/* //these are mvdsv specific {83, "executecmd", NULL, {NULL}, NULL}, {84, "tokenize", NULL, {&type_string}, NULL}, @@ -475,6 +475,50 @@ static struct { {101, "redirectcmd", NULL, {NULL}, NULL}, {102, "calltimeofday", NULL, {NULL}, NULL}, {103, "forcedemoframe", NULL, {NULL}, NULL}, +*/ + +//some QSG extensions + + {83, NULL, NULL, {NULL}, NULL}, + {84, NULL, NULL, {NULL}, NULL}, + {85, NULL, NULL, {NULL}, NULL}, + {86, NULL, NULL, {NULL}, NULL}, + {87, NULL, NULL, {NULL}, NULL}, + {88, NULL, NULL, {NULL}, NULL}, + {89, NULL, NULL, {NULL}, NULL}, + {90, "tracebox", NULL, {&type_vector, &type_vector, &type_vector, &type_vector, &type_float, &type_entity}, "void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent)"}, + {91, "randomvec", &type_vector, {NULL}, "vector()"}, + {92, "getlight", &type_vector, {&type_vector}, "vector(vector org)"}, + {93, "registercvar", &type_float, {&type_string, &type_string}, "float(string cvarname, string defaultvalue)"}, + {94, "min", &type_float, {&type_float,&type_float,&type_float,&type_float,&type_float,&type_float,&type_float,&type_float},"float(float a, float b, ...)"}, + {95, "max", &type_float, {&type_float,&type_float,&type_float,&type_float,&type_float,&type_float,&type_float,&type_float},"float(float a, float b, ...)"}, + {96, "bound", &type_float, {&type_float,&type_float,&type_float}, "float(float minimum, float val, float maximum)"}, + {97, "pow", &type_float, {&type_float,&type_float}, "float(float value, float exp)"}, + {98, "findfloat", &type_entity, {&type_entity,&type_field,&type_float}, "entity(entity start, .__variant fld, __variant match)"}, + + {99, "checkextension",&type_float, {&type_string}, "float(string extname)"}, + {100, "builtin_find", &type_float, {&type_string}, "float(string builtinname)"}, + {101, "redirectcmd", NULL, {&type_entity,&type_string}, "void(entity to, string str)"}, + {102, "anglemod", &type_float, {&type_float}, "float(float value)"}, + {103, "cvar_string", &type_string, {&type_string}, "string(string cvarname)"}, + + {104, "showpic", NULL, {NULL}, "void(string slot, string picname, float x, float y, float zone, optional entity player)"}, + {105, "hidepic", NULL, {NULL}, "void(string slot, optional entity player)"}, + {106, "movepic", NULL, {NULL}, "void(string slot, float x, float y, float zone, optional entity player)"}, + {107, "changepic", NULL, {NULL}, "void(string slot, string picname, optional entity player)"}, + {108, "showpicent", NULL, {NULL}, "void(string slot, entity player)"}, + {109, "hidepicent", NULL, {NULL}, "void(string slot, entity player)"}, + + {110, "fopen", &type_float, {&type_string,&type_float}, "filestream(string filename, float mode, optional float mmapminsize)"}, + {111, "fclose", NULL, {&type_float}, "void(filestream fhandle)"}, + {112, "fgets", &type_string, {&type_float,&type_string}, "string(filestream fhandle)"}, + {113, "fputs", NULL, {&type_float,&type_string}, "void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)"}, + {114, "strlen", &type_float, {&type_string}, "float(string s)"}, + {115, "strcat", &type_string, {&type_string,&type_string}, "string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8)"}, + {116, "substring", &type_string, {&type_string,&type_float,&type_float}, "string(string s, float start, float length)"}, + {117, "stov", &type_vector, {&type_string}, "vector(string s)"}, + {118, "strzone", &type_string, {&type_string}, "string(string s, ...)"}, + {119, "strunzone", NULL, {&type_string}, "void(string s)"}, }; char *DecompileValueString(etype_t type, void *val); @@ -1044,11 +1088,12 @@ void DecompileCalcProfiles(void) */ for (j = 0, ps = 0; j < df->numparms; j++) - ps += df->parm_size[j]; + ps += df->parm_size[j]; if (ps > 0) { - for (j = df->parm_start; j < (df->parm_start) + ps; j++) + int p; + for (p = 0, j = df->parm_start; j < (df->parm_start) + ps; p++) { line[0] = '\0'; par = DecompileGetParameter(j); @@ -1059,16 +1104,31 @@ void DecompileCalcProfiles(void) { //Error("Error - No parameter names with offset %i.", j); // printf("No parameter names with offset %i\n", j); - if (j < (df->parm_start) + ps - 1) - QC_snprintfz(line, sizeof(line), "float par%i, ", j - df->parm_start); + if (p<8) + j += df->parm_size[p]; else - QC_snprintfz(line, sizeof(line), "float par%i", j - df->parm_start); + j += 1; + if (p<8&&df->parm_size[p] == 3) + { + if (j < (df->parm_start) + ps) + QC_snprintfz(line, sizeof(line), "vector par%i, ", p); + else + QC_snprintfz(line, sizeof(line), "vector par%i", p); + } + else + { + if (j < (df->parm_start) + ps) + QC_snprintfz(line, sizeof(line), "__variant par%i, ", p); + else + QC_snprintfz(line, sizeof(line), "__variant par%i", p); + } } else { if (par->type == ev_vector) j += 2; - if (j < (df->parm_start) + ps - 1) + j++; + if (j < (df->parm_start) + ps) { QC_snprintfz(line, sizeof(line), "%s, ", DecompilePrintParameter(par)); } @@ -1195,7 +1255,7 @@ char *DecompileGlobal(dfunction_t *df, gofs_t ofs, QCC_type_t * req_t) if (def) { - if (!strcmp(strings + def->s_name, "IMMEDIATE") || !strcmp(strings + def->s_name, ".imm")) + if (!strcmp(strings + def->s_name, "IMMEDIATE") || !strcmp(strings + def->s_name, ".imm") || !def->s_name) { etype_t ty; if (!req_t) @@ -1363,6 +1423,24 @@ void DecompileImmediate_Insert(dfunction_t *df, gofs_t ofs, char *knew, QCC_type } } +void FloatToString(char *out, size_t outsize, float f) +{ + char *e; + QC_snprintfz(out, outsize, "%f", f); + + //trim any trailing decimals + e = strchr(out, '.'); + if (e) + { + e = e+strlen(e); + while (e > out && e[-1] == '0') + e--; + if (e > out && e[-1] == '.') + e--; + *e = 0; + } +} + char *DecompileImmediate_Get(dfunction_t *df, gofs_t ofs, QCC_type_t *req_t) { char *res; @@ -1402,16 +1480,21 @@ char *DecompileImmediate_Get(dfunction_t *df, gofs_t ofs, QCC_type_t *req_t) { case ev_void: //for lack of any better ideas. case ev_float: - if ((float)(int)pr_globals[ofs] == pr_globals[ofs]) - QC_snprintfz(temp, sizeof(temp), "%i", (int)(pr_globals[ofs])); - else if ((*(int*)&pr_globals[ofs] & 0x7f800000) || !(*(int*)&pr_globals[ofs] & 0x7fffffff)) - QC_snprintfz(temp, sizeof(temp), "%f", pr_globals[ofs]); + //denormalised floats need special handling. + if ((0x7fffffff&*(int*)&pr_globals[ofs]) >= 1 && (0x7fffffff&*(int*)&pr_globals[ofs]) < 0x00800000) + { + QC_snprintfz(temp, sizeof(temp), "((float)(__variant)%ii)", *(int*)&pr_globals[ofs]); + +// if (req_t && *(int*)&pr_globals[ofs] >= 1 && *(int*)&pr_globals[ofs] < strofs) +// ; //failure to break means we'll print out a trailing /*string*/ +// else + break; + } else - QC_snprintfz(temp, sizeof(temp), "%%%i", *(int*)&pr_globals[ofs]); - if (pr_globals[ofs] == 0 || ((int*)pr_globals)[ofs] < 0 || ((int*)pr_globals)[ofs] >= strofs || strcmp(temp, "0.000000")) + { + FloatToString(temp, sizeof(temp), pr_globals[ofs]); break; -// printf("Hey! That's not a float! error in %s\n", strings + df->s_name); -// printf("%f could be %s\n", pr_globals[ofs], &strings[((int*)pr_globals)[ofs]]); + } case ev_string: { const char *in; @@ -1495,7 +1578,13 @@ char *DecompileImmediate_Get(dfunction_t *df, gofs_t ofs, QCC_type_t *req_t) } break; case ev_vector: - QC_snprintfz(temp, sizeof(temp), "\'%f %f %f\'", pr_globals[ofs],pr_globals[ofs+1],pr_globals[ofs+2]); + { + char x[64], y[64], z[64]; + FloatToString(x, sizeof(x), pr_globals[ofs+0]); + FloatToString(y, sizeof(y), pr_globals[ofs+1]); + FloatToString(z, sizeof(z), pr_globals[ofs+2]); + QC_snprintfz(temp, sizeof(temp), "\'%s %s %s\'", x, y, z); + } break; // case ev_quat: // QC_snprintfz(temp, sizeof(temp), "\'%f %f %f %f\'", pr_globals[ofs],pr_globals[ofs+1],pr_globals[ofs+2],pr_globals[ofs+3]); @@ -2498,57 +2587,15 @@ QCC_ddef_t *DecompileFunctionGlobal(int funcnum) return NULL; } -void DecompileFunction(const char *name, int *lastglobal) +void DecompilePreceedingGlobals(int start, int end, const char *name) { - int i, findex, ps; - dstatement_t *ds, *ts, *altdone; - dfunction_t *df; QCC_ddef_t *par; - char *arg2; - unsigned short dom, tom; - int j, start, end; + int j; QCC_ddef_t *ef; static char line[8192]; - dstatement_t *k; - int dum; - size_t startpos; const char *matchingfield; - for (i = 1; i < numfunctions; i++) - if (!strcmp(name, strings + functions[i].s_name)) - break; - if (i == numfunctions) - { - printf("Fatal Error: No function named \"%s\"\n", name); - exit(1); - } - df = functions + i; - altdone = statements + numstatements; - for (j = i+1; j < numfunctions; j++) - { - if (functions[j].first_statement <= 0) - continue; - altdone = statements + functions[j].first_statement; - break; - } - - findex = i; - - start = *lastglobal; - -// if (dfpred->first_statement <= 0 && df->first_statement > 0) -// start -= 1; - - end = df->parm_start; - if (!end) - { - par = DecompileFindGlobal(name); - if (par) - end = par - globals; - } - *lastglobal = max(*lastglobal, end + df->locals); - //print globals leading up to the function. for (j = start; j < end; j++) { @@ -2584,7 +2631,7 @@ void DecompileFunction(const char *name, int *lastglobal) } else if (par->type != ev_pointer) { - if (strcmp(strings + par->s_name, "IMMEDIATE") && strcmp(strings + par->s_name, ".imm")) + if (strcmp(strings + par->s_name, "IMMEDIATE") && strcmp(strings + par->s_name, ".imm") && par->s_name) { if (par->type == ev_field) @@ -2656,8 +2703,58 @@ void DecompileFunction(const char *name, int *lastglobal) } } } +} +void DecompileFunction(const char *name, int *lastglobal) +{ + int i, findex, ps; + dstatement_t *ds, *ts, *altdone; + dfunction_t *df; + QCC_ddef_t *par; + char *arg2; + unsigned short dom, tom; + int j, start, end; + static char line[8192]; + dstatement_t *k; + int dum; + size_t startpos; + + + + for (i = 1; i < numfunctions; i++) + if (!strcmp(name, strings + functions[i].s_name)) + break; + if (i == numfunctions) + { + printf("Fatal Error: No function named \"%s\"\n", name); + exit(1); + } + df = functions + i; + altdone = statements + numstatements; + for (j = i+1; j < numfunctions; j++) + { + if (functions[j].first_statement <= 0) + continue; + altdone = statements + functions[j].first_statement; + break; + } + + findex = i; + + start = *lastglobal; +// if (dfpred->first_statement <= 0 && df->first_statement > 0) +// start -= 1; + end = df->parm_start; + if (!end) + { + par = DecompileFindGlobal(name); + if (par) + end = par - globals; + } + *lastglobal = max(*lastglobal, end + df->locals); + DecompilePreceedingGlobals(start, end, name); + /* - * Check ''local globals'' + * Check ''local globals'' */ if (df->first_statement <= 0) @@ -2967,6 +3064,7 @@ void DecompileDecompileFunctions(const char *origcopyright) vfile_t *f; char fname[512]; int lastglob = 1; + QCC_ddef_t *def; DecompileCalcProfiles(); @@ -2985,6 +3083,27 @@ void DecompileDecompileFunctions(const char *origcopyright) QCC_CatVFile(Decompileprogssrc, "//#pragma copyright \"%s\"\n", origcopyright); QCC_CatVFile(Decompileprogssrc, "\n", origcopyright); + def = DecompileFindGlobal("end_sys_fields"); + lastglob = def?def->ofs+1:1; + if (lastglob != 1) + { + QC_snprintfz(synth_name, sizeof(synth_name), "sysdefs.qc"); + QC_snprintfz(fname, sizeof(fname), synth_name); + if (!DecompileAlreadySeen(fname, &f)) + { + printf("decompiling %s\n", fname); + compilecb(); + QCC_CatVFile(Decompileprogssrc, "%s\n", fname); + } + if (!f) + { + printf("Fatal Error - Could not open \"%s\" for output.\n", fname); + exit(1); + } + Decompileofile = f; + + DecompilePreceedingGlobals(1, lastglob, ""); + } for (i = 1; i < numfunctions; i++) { diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index ebba250c..ef2a3b6e 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -975,6 +975,7 @@ void QCC_PR_NewLine (pbool incomment); #define GDF_USED 64 //don't strip this, ever. #define GDF_BASICTYPE 128 //don't care about #merge types not being known correctly. #define GDF_SCANLOCAL 256 //don't use the locals hash table +#define GDF_POSTINIT 512 //field must be initialised at the end of the compile (allows arrays to be extended later) QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags); QCC_sref_t QCC_PR_GetSRef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags); void QCC_FreeTemp(QCC_sref_t t); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index efd19b7b..79effb9e 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -6826,94 +6826,6 @@ QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas) return QCC_MemberInParentClass(name, clas->parentclass); } -#if 0 -//create fields for the types, instanciate the members to the fields. -//we retouch the parents each time to guarentee polymorphism works. -//FIXME: virtual methods will not work properly. Need to trace down to see if a parent already defined it -void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas, int *basictypefield) -{ -//we created fields for each class when we defined the actual classes. -//we need to go through each member and match it to the offset of it's parent class, if overloaded, or create a new field if not.. - -//basictypefield is cleared before we do this -//we emit the parent's fields first (every time), thus ensuring that we don't reuse parent fields on a child class. - char membername[2048]; - unsigned int p; - int a; - unsigned int o; - QCC_type_t *mt, *ft; - QCC_def_t *f, *m; - extern pbool verbose; - if (clas->parentclass != type_entity) //parents MUST have all their fields set or inheritance would go crazy. - QCC_PR_EmitFieldsForMembers(clas->parentclass, basictypefield); - - for (p = 0; p < clas->num_parms; p++) - { - mt = clas->params[p].type; - QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, clas->name, clas->params[p].paramname); - m = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); - - f = QCC_MemberInParentClass(clas->params[p].paramname, clas->parentclass); - if (f) - { - if (f->type->type != ev_field || typecmp(f->type->aux_type, mt)) - { - char ct[256]; - char pt[256]; - TypeName(f->type->aux_type, pt, sizeof(pt)); - TypeName(mt, ct, sizeof(ct)); - QCC_PR_Warning(0, NULL, 0, "type mismatch on inheritance of %s::%s. %s vs %s", clas->name, clas->params[p].paramname, ct, pt); - } - if (!m) - { - basictypefield[mt->type] += 1; - continue; - } - 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++) - ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+a*mt->size+f->ofs]; - continue; - } - - //came from parent class instead? - if (!m) - QCC_Error(ERR_INTERNAL, "field def missing for class member (%s::%s)", clas->name, clas->params[p].paramname); - - 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 inheritted from 500 times*/ - if (((int *)qcc_pr_globals)[0+a*mt->size+m->ofs]) - { - ++basictypefield[mt->type]; - continue; - } - - //we need the type in here so saved games can still work without saving ints as floats. (would be evil) - ft = QCC_PR_FieldType(*basictypes[mt->type]); - QC_snprintfz(membername, sizeof(membername), "::%s%i", basictypenames[mt->type], ++basictypefield[mt->type]); - f = QCC_PR_GetDef(ft, membername, NULL, false, 0, GDF_CONST); - if (!f) - { - //give it a location if this is the first class that uses this fieldspace - f = QCC_PR_GetDef(ft, membername, NULL, true, 0, GDF_CONST); - for (o = 0; o < m->type->size; o++) - ((int *)qcc_pr_globals)[o+f->ofs] = pr.size_fields + o; - pr.size_fields += o; - } - - for (o = 0; o < m->type->size; o++) - ((int *)qcc_pr_globals)[o+a*mt->size+m->ofs] = ((int *)qcc_pr_globals)[o+f->ofs]; - - if (verbose) - QCC_PR_Note(0, NULL, 0, "%s maps to %s", m->name, f->name); - - f->references++; - } - } -} -#endif void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_sref_t ed) { //go through clas, do the virtual thing only if the child class does not override. @@ -13641,11 +13553,14 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, const char *name, QCC_function_t *s if (!rootsymbol) { rootsymbol = first; - rootsymbol->symboldata = qccHunkAlloc ((def->arraysize?def->arraysize:1) * type->size * sizeof(float)); + if (flags & GDF_POSTINIT) + rootsymbol->symboldata = NULL; + else + rootsymbol->symboldata = qccHunkAlloc ((def->arraysize?def->arraysize:1) * type->size * sizeof(float)); } def->symbolheader = rootsymbol; - def->symboldata = rootsymbol->symboldata + def->ofs; + def->symboldata = (rootsymbol->symboldata?rootsymbol->symboldata + def->ofs:NULL); def->symbolsize = (def->arraysize?def->arraysize:1) * type->size; if (type->type == ev_struct && (!arraysize || a>=0)) diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 61fb147a..dbf78293 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -5619,19 +5619,24 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) d = QCC_PR_GetDef(NULL, parmname, NULL, 0, 0, GDF_CONST); if (!d) { //don't go all weird with unioning generic fields - QC_snprintfz(membername, sizeof(membername), "::%s%i", basictypenames[newparm->type], basicindex+1); + QC_snprintfz(membername, sizeof(membername), "::*%s", basictypenames[newparm->type]); d = QCC_PR_GetDef(NULL, membername, NULL, 0, 0, GDF_CONST); if (!d) { - d = QCC_PR_GetDef(QCC_PR_FieldType(*basictypes[newparm->type]), membername, NULL, 2, arraysize, GDF_CONST); - for (i = 0; (unsigned int)i < newparm->size*(arraysize?arraysize:1); i++) - d->symboldata[i]._int = pr.size_fields+i; - pr.size_fields += i; + d = QCC_PR_GetDef(QCC_PR_FieldType(*basictypes[newparm->type]), membername, NULL, 2, arraysize, GDF_CONST|GDF_POSTINIT); +// for (i = 0; (unsigned int)i < newparm->size*(arraysize?arraysize:1); i++) +// d->symboldata[i]._int = pr.size_fields+i; +// pr.size_fields += i; d->referenced = true; //always referenced, so you can inherit safely. } - else if (d->arraysize != arraysize) - QCC_PR_ParseError(ERR_INTERNAL, "array members are kinda limited, sorry. try rearranging them or adding padding for alignment\n"); //FIXME: add relocs to cope with this all of a type can then be contiguous and thus allow arrays. + if (d->arraysize < basicindex+(arraysize?arraysize:1)) + { + if (d->symboldata) + QCC_PR_ParseError(ERR_INTERNAL, "array members are kinda limited, sorry. try rearranging them or adding padding for alignment\n"); //FIXME: add relocs to cope with this all of a type can then be contiguous and thus allow arrays. + else + d->arraysize = basicindex+(arraysize?arraysize:1); + } } QCC_FreeDef(d); @@ -5639,7 +5644,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) //actually, that seems pointless. QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, classname, parmname); // printf("define %s -> %s\n", membername, d->name); - d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, arraysize, d, 0, true, (isnull?0:GDF_CONST)|(opt_classfields?GDF_STRIP:0)); + d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, arraysize, d, basicindex, true, (isnull?0:GDF_CONST)|(opt_classfields?GDF_STRIP:0)); d->referenced = true; //always referenced, so you can inherit safely. } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index b0a6724c..f2618eae 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -3145,6 +3145,27 @@ void QCC_PR_BeginCompilation (void *memory, int memsize) QCC_PrioritiseOpcodes(); } +void QCC_PR_FinishFieldDef(QCC_def_t *d) +{ + int i; + if (d->symboldata) + return; //nothing to finish + + d->symbolsize = (d->arraysize?d->arraysize:1) * d->type->size; + + if (d->symbolheader != d) + { + QCC_PR_FinishFieldDef(d->symbolheader); + d->symboldata = d->symbolheader->symboldata + d->ofs; + } + else + { + d->symboldata = qccHunkAlloc (d->symbolsize * sizeof(float)); + for (i = 0; i < d->symbolsize; i++) + d->symboldata[i]._int = pr.size_fields++; + } +} + /* ============== PR_FinishCompilation @@ -3172,6 +3193,8 @@ int QCC_PR_FinishCompilation (void) // check to make sure all functions prototyped have code for (d=pr.def_head.next ; d ; d=d->next) { + if (d->type->type == ev_field && !d->symboldata) + QCC_PR_FinishFieldDef(d); if (d->type->type == ev_function && d->constant)// function parms are ok { // f = G_FUNCTION(d->ofs);