From fc82e561be13df6c2320222a21b5d4a1955ea87f Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 2 Jun 2013 06:03:54 +0000 Subject: [PATCH] Rewritten how arguments and fields are stored. No longer mangles types quite so much. Fixes for class support. Its actually usable now. Seriously! I've even modified my menu code to use it! Why don't you believe me? Fixes for structs+pointers. Added warnings for comparisons against incompatible function etc types. This'll probably generate a load of th_pain warnings in vanilla code. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4383 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/comprout.c | 2 +- engine/qclib/execloop.h | 14 +- engine/qclib/pr_comp.h | 7 + engine/qclib/progtype.h | 2 +- engine/qclib/qcc.h | 24 +- engine/qclib/qcc_pr_comp.c | 1158 +++++++++++++++++++++--------------- engine/qclib/qcc_pr_lex.c | 615 ++++++++++++------- engine/qclib/qccmain.c | 11 +- 8 files changed, 1107 insertions(+), 726 deletions(-) diff --git a/engine/qclib/comprout.c b/engine/qclib/comprout.c index 0637e22ba..2ce95e56c 100644 --- a/engine/qclib/comprout.c +++ b/engine/qclib/comprout.c @@ -54,7 +54,7 @@ void PostCompile(void) { fclose(asmfile); asmfile = NULL; - } + } } pbool PreCompile(void) { diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 5a2cf2c6a..5006fcc5b 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -489,7 +489,7 @@ reeval: //get a pointer to a field var case OP_ADDRESS: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) + if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts) { pr_xstatement = st-pr_statements; if (PR_RunWarning (&progfuncs->funcs, "OP_ADDRESS references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name))) @@ -538,10 +538,16 @@ reeval: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) + if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts) { pr_xstatement = st-pr_statements; - PR_RunError (&progfuncs->funcs, "OP_LOAD references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)); + + if (PR_RunWarning (&progfuncs->funcs, "OP_LOAD references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name))) + { + st--; + goto cont; + } + PR_RunError (&progfuncs->funcs, "OP_LOAD references invalid entity %i in %s", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)); } ed = PROG_TO_EDICT(progfuncs, OPA->edict); #ifdef PARANOID @@ -552,7 +558,7 @@ reeval: break; case OP_LOAD_V: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) + if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts) { pr_xstatement = st-pr_statements; PR_RunError (&progfuncs->funcs, "OP_LOAD_V references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)); diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index 61995e016..35ea6e504 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -355,6 +355,13 @@ enum qcop_e { OP_BINARYNOT_F, OP_BINARYNOT_I, + OP_EQ_P, + OP_NE_P, + OP_LE_P, + OP_GE_P, + OP_LT_P, + OP_GT_P, + OP_NUMOPS }; diff --git a/engine/qclib/progtype.h b/engine/qclib/progtype.h index ab1201549..e8b8c6810 100644 --- a/engine/qclib/progtype.h +++ b/engine/qclib/progtype.h @@ -10,7 +10,7 @@ typedef vec_t vec3_t[3]; #ifndef t_bool #define t_bool -typedef int pbool; +typedef unsigned int pbool; #else #define t_bool diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index b5798bf90..d1a134dfc 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -284,6 +284,7 @@ extern hashtable_t globalstable, localstable; #ifdef WRITEASM extern FILE *asmfile; +extern pbool asmfilebegun; #endif //============================================================================= @@ -293,22 +294,30 @@ typedef struct QCC_function_s QCC_function_t; #define MAX_PARMS 8 +typedef struct QCC_typeparam_s +{ + struct QCC_type_s *type; + pbool optional; + unsigned int ofs; + unsigned int arraysize; + char *paramname; +}; + typedef struct QCC_type_s { etype_t type; struct QCC_type_s *parentclass; //type_entity... - struct QCC_type_s *next; +// struct QCC_type_s *next; // function types are more complex struct QCC_type_s *aux_type; // return type or field type - struct QCC_type_s *param; - int num_parms; // -1 = variable args -// struct QCC_type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated + + struct QCC_typeparam_s *params; //[num_parms] + unsigned int num_parms; - unsigned int ofs; //inside a structure. unsigned int size; - unsigned int arraysize; - pbool typedefed; + pbool typedefed:1; + pbool vargs:1; char *name; char *aname; } QCC_type_t; @@ -638,6 +647,7 @@ enum { WARN_MISSINGOPTIONAL, WARN_SYSTEMCRC, WARN_CONDITIONALTYPEMISMATCH, + WARN_SELFNOTTHIS, //warned for because 'self' does not have the right type. we convert such references to 'this' instead, which is more usable. ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called. diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 2157cbe37..8ef247e54 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -137,7 +137,7 @@ 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); QCC_def_t *QCC_PR_Term (int exprflags); -QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], int argcount); +QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], QCC_type_t *argtypelist[], int argcount); void QCC_Marshal_Locals(int firststatement, int laststatement); void QCC_PR_ParseState (void); @@ -153,7 +153,7 @@ QCC_pr_info_t pr; //======================================== QCC_def_t *pr_scope; // the function being parsed, or NULL -QCC_type_t *pr_classtype; +QCC_type_t *pr_classtype; // the class that the current function is part of. pbool pr_dumpasm; QCC_string_t s_file, s_file2; // filename for function definition @@ -554,6 +554,14 @@ QCC_opcode_t pr_opcodes[] = {7, "~", "BINARYNOT_F", -1, ASSOC_LEFT, &type_float, &type_void, &type_float}, {7, "~", "BINARYNOT_I", -1, ASSOC_LEFT, &type_integer, &type_void, &type_integer}, + {7, "==", "EQ_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, "!=", "NE_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, "<=", "LE_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, ">=", "GE_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, "<", "LT_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, ">", "GT_P", 5, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + + {0, NULL} }; @@ -724,6 +732,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_EQ_I], &pr_opcodes[OP_EQ_IF], &pr_opcodes[OP_EQ_FI], + &pr_opcodes[OP_EQ_P], &pr_opcodes[OP_NE_F], &pr_opcodes[OP_NE_V], @@ -733,23 +742,28 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_NE_I], &pr_opcodes[OP_NE_IF], &pr_opcodes[OP_NE_FI], + &pr_opcodes[OP_NE_P], &pr_opcodes[OP_LE_F], &pr_opcodes[OP_LE_I], &pr_opcodes[OP_LE_IF], &pr_opcodes[OP_LE_FI], + &pr_opcodes[OP_LE_P], &pr_opcodes[OP_GE_F], &pr_opcodes[OP_GE_I], &pr_opcodes[OP_GE_IF], &pr_opcodes[OP_GE_FI], + &pr_opcodes[OP_GE_P], &pr_opcodes[OP_LT_F], &pr_opcodes[OP_LT_I], &pr_opcodes[OP_LT_IF], &pr_opcodes[OP_LT_FI], + &pr_opcodes[OP_LT_P], &pr_opcodes[OP_GT_F], &pr_opcodes[OP_GT_I], &pr_opcodes[OP_GT_IF], &pr_opcodes[OP_GT_FI], + &pr_opcodes[OP_GT_P], NULL }, { //6 @@ -1587,10 +1601,34 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size) } #endif +//need_lock is set if it crossed a function call. +int QCC_PR_FindSourceForTemp(QCC_def_t *tempdef, int op, pbool *need_lock) +{ + int st = -1; + *need_lock = false; + if (tempdef->temp) + { + for (st = numstatements-1; st>=0; st--) + { + if (statements[st].c == tempdef->ofs) + { + if (statements[st].op == op) + return st; + return -1; + } + + if ((statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8) || (statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H)) + *need_lock = true; + } + } + + return st; +} 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) { + char typea[256], typeb[256]; QCC_dstatement_t *statement; QCC_def_t *var_c=NULL, *temp=NULL; @@ -1623,14 +1661,6 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ QCC_FreeTemp(var_b); } - if (keyword_class && var_a && var_b) - { - if (var_a->type->type == ev_entity && var_b->type->type == ev_entity) - if (var_a->type != var_b->type) - if (strcmp(var_a->type->name, var_b->type->name)) - QCC_PR_ParseWarning(0, "Implicit cast from '%s' to '%s'", var_a->type->name, var_b->type->name); - } - //maths operators if (opt_constantarithmatic) { @@ -1908,6 +1938,45 @@ 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_STORE_F: + case OP_STORE_V: + case OP_STORE_FLD: + case OP_STORE_P: + case OP_STORE_I: + case OP_STORE_ENT: + case OP_STORE_FNC: + { + QCC_type_t *t = var_a->type; + while(t) + { + if (!typecmp_lax(t, var_b->type)) + break; + t = t->parentclass; + } + if (!t) + { + TypeName(var_a->type, typea, sizeof(typea)); + TypeName(var_b->type, typeb, sizeof(typeb)); + QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Implicit assignment from %s to %s", typea, typeb); + } + } + break; + + case OP_STOREP_F: + case OP_STOREP_V: + case OP_STOREP_FLD: + case OP_STOREP_P: + case OP_STOREP_I: + case OP_STOREP_ENT: + case OP_STOREP_FNC: + if (typecmp_lax(var_a->type, var_b->type->aux_type)) + { + TypeName(var_a->type, typea, sizeof(typea)); + TypeName(var_b->type->aux_type, typeb, sizeof(typeb)); + QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Implicit field assignment from %s to %s", typea, typeb); + } + break; + case OP_LOADA_F: case OP_LOADA_V: case OP_LOADA_S: @@ -1947,6 +2016,12 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_GE_F: case OP_LT_F: case OP_GT_F: + if (typecmp_lax(var_a->type, var_b->type)) + { + TypeName(var_a->type, typea, sizeof(typea)); + TypeName(var_b->type, typeb, sizeof(typeb)); + QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "'%s' type mismatch: %s with %s", op->name, typea, typeb); + } if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); break; @@ -2073,10 +2148,9 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_ADD_I: { QCC_def_t *arg[2] = {var_a, var_b}; + QCC_type_t *argt[2] = {type_integer, type_integer}; numstatements--; - def_parms[0].type = type_integer; - def_parms[1].type = type_integer; - var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "AddInt", NULL, true, 0, false), arg, 2); + var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "AddInt", NULL, true, 0, false), arg, argt, 2); var_c->type = type_integer; return var_c; } @@ -2084,10 +2158,9 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_SUB_I: { QCC_def_t *arg[2] = {var_a, var_b}; + QCC_type_t *argt[2] = {type_integer, type_integer}; numstatements--; - def_parms[0].type = type_integer; - def_parms[1].type = type_integer; - var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "SubInt", NULL, true, 0, false), arg, 2); + var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "SubInt", NULL, true, 0, false), arg, argt, 2); var_c->type = type_integer; return var_c; } @@ -2095,10 +2168,9 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_MUL_I: { QCC_def_t *arg[2] = {var_a, var_b}; + QCC_type_t *argt[2] = {type_integer, type_integer}; numstatements--; - def_parms[0].type = type_integer; - def_parms[1].type = type_integer; - var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "MulInt", NULL, true, 0, false), arg, 2); + var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "MulInt", NULL, true, 0, false), arg, argt, 2); var_c->type = type_integer; return var_c; } @@ -2106,10 +2178,9 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_DIV_I: { QCC_def_t *arg[2] = {var_a, var_b}; + QCC_type_t *argt[2] = {type_integer, type_integer}; numstatements--; - def_parms[0].type = type_integer; - def_parms[1].type = type_integer; - var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "DivInt", NULL, true, 0, false), arg, 2); + var_c = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "DivInt", NULL, true, 0, false), arg, argt, 2); var_c->type = type_integer; return var_c; } @@ -2123,8 +2194,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ else { numstatements--; - def_parms[0].type = type_integer; - var_a = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "itof", NULL, true, 0, false), &var_a, 1); + var_a = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "itof", NULL, true, 0, false), &var_a, &type_integer, 1); var_a->type = type_float; statement = &statements[numstatements]; numstatements++; @@ -2138,8 +2208,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ else { numstatements--; - def_parms[0].type = type_float; - var_a = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "ftoi", NULL, true, 0, false), &var_a, 1); + var_a = QCC_PR_GenerateFunctionCall(QCC_PR_GetDef(type_function, "ftoi", NULL, true, 0, false), &var_a, &type_float, 1); var_a->type = type_integer; statement = &statements[numstatements]; numstatements++; @@ -2362,6 +2431,24 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ case OP_STOREP_P: op = &pr_opcodes[OP_STOREP_I]; break; + case OP_EQ_P: + op = &pr_opcodes[OP_EQ_I]; + break; + case OP_NE_P: + op = &pr_opcodes[OP_NE_I]; + break; + case OP_GT_P: + op = &pr_opcodes[OP_GT_I]; + break; + case OP_GE_P: + op = &pr_opcodes[OP_GE_I]; + break; + case OP_LE_P: + op = &pr_opcodes[OP_LE_I]; + break; + case OP_LT_P: + op = &pr_opcodes[OP_LT_I]; + break; case OP_BITCLR: //b = var, a = bit field. @@ -2413,27 +2500,8 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ //don't chain these... this expansion is not the same. { int st; - int need_lock = false; - if (var_b->temp) - { - 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) - { - st = -1; - break; - } - } - } - else - st = -1; + int need_lock; + st = QCC_PR_FindSourceForTemp(var_b, OP_ADDRESS, &need_lock); var_c = QCC_GetTemp(*op->type_c); if (st < 0) @@ -2614,7 +2682,15 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ statement->c = var_c->ofs; if (op->type_b == &type_field) { - var_c->name = var_b->name; + if (var_b->type->aux_type->type == ev_entity) + { + var_c->type = var_b->type->aux_type; + var_c->name = var_b->type->name; + } + else + { + var_c->name = var_b->name; + } var_c->s_file = var_b->s_file; var_c->s_line = var_b->s_line; } @@ -2966,16 +3042,17 @@ void QCC_PrecacheFileOptimised (char *n, int ch) numfiles++; } -QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], int argcount) //warning, the func could have no name set if it's a field call. +QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], QCC_type_t *argtypelist[], int argcount) //warning, the func could have no name set if it's a field call. { - QCC_def_t *d, *oldret, *oself; + QCC_def_t *d, *oldret, *oself, *self; int i; - QCC_type_t *t; + QCC_type_t *t, *oldrettype; // int np; int laststatement = numstatements; int callconvention; QCC_dstatement_t *st; + pbool crossedfunc; func->timescalled++; @@ -2986,92 +3063,89 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i callconvention = OP_CALL1; //standard t = func->type; - - if (t->type == ev_variant) - { - t->aux_type = type_variant; - } - if (t->type != ev_function && t->type != ev_variant) { QCC_PR_ParseErrorPrintDef (ERR_NOTAFUNCTION, func, "not a function"); } -/* if (t->type == ev_variant) - { - extraparms = true; - np = 0; - } - else if (t->num_parms < 0) - { - extraparms = true; - np = (t->num_parms * -1) - 1; - } - else - np = t->num_parms; -*/ + self = NULL; + oself = NULL; + d = NULL; - if (strchr(func->name, ':') && laststatement && statements[laststatement-1].op == OP_LOAD_FNC && statements[laststatement-1].c == func->ofs) - { //we're entering OO code with a different self. make sure self is preserved. - //eg: other.touch(self) - - //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, 0, false); - if (statements[laststatement-1].a != d->ofs) + if (strchr(func->name, ':') && func->temp) + { + //the function might be: + //parentclass::func(); + //global.func(); + //local.func(); + if (func->temp) { - oself = QCC_GetTemp(type_entity); - //oself = self - QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, false); - //self = other - QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, false); + laststatement = QCC_PR_FindSourceForTemp(func, OP_LOAD_FNC, &crossedfunc); + if (laststatement >= 0) + { //we're entering OO code with a different self. make sure self is preserved. + //eg: other.touch(self) - //if the args refered to self, update them to refer to oself instead - //(as self is now set to 'other') - for (i = 0; i < argcount; i++) - { - if (arglist[i]->ofs == d->ofs) + self = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); + if (statements[laststatement].a != self->ofs) { - arglist[i] = oself; + oself = QCC_GetTemp(type_entity); + //oself = self + QCC_PR_SimpleStatement(OP_STORE_ENT, self->ofs, oself->ofs, 0, false); + //self = other + QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement].a, self->ofs, 0, false); + + //if the args refered to self, update them to refer to oself instead + //(as self is now set to 'other') + for (i = 0; i < argcount; i++) + { + if (arglist[i]->ofs == self->ofs) + { + arglist[i] = oself; + } + } } } + else + QCC_PR_ParseError(ERR_INTERNAL, "unable to determine the source of %s temp\n", func->name); } - else + else if (pr_classtype) { - //it was self.func() anyway - oself = NULL; - d = NULL; + QCC_PR_ParseWarning(0, "Class-specific call from non-class function\n"); } } - else - { //regular func call - oself = NULL; - d = NULL; - } // write the arguments (except for first two if hexenc) for (i = 0; i < argcount; i++) { if (i>=MAX_PARMS) + { d = extra_parms[i - MAX_PARMS]; + if (!d) + { + d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t)); + d->name = "extra parm"; + d->ofs = QCC_GetFreeGlobalOffsetSpace (3); + extra_parms[i - MAX_PARMS] = d; + } + } else d = &def_parms[i]; + if (argtypelist && argtypelist[i]) + d->type = argtypelist[i]; + else + d->type = arglist[i]->type; - if (callconvention == OP_CALL1H) - if (i < 2) - { - //first two args are passed in the call opcode, so don't need to be copied - arglist[i]->references++; - d->references++; - /*don't free these temps yet, free them after the return check*/ - continue; - } - - if (arglist[i]->type->size == 3 || !opt_nonvec_parms) + if (callconvention == OP_CALL1H && i < 2) + { + //first two args are passed in the call opcode, so don't need to be copied + arglist[i]->references++; + d->references++; + /*don't free these temps yet, free them after the return check*/ + } + else 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 { - d->type = arglist[i]->type; QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], arglist[i], d, (QCC_dstatement_t **)0xffffffff)); optres_nonvec_parms++; } @@ -3079,9 +3153,15 @@ 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) + { + oldrettype = def_ret.type; oldret = QCC_GetTemp(def_ret.type); + } else + { + oldrettype = NULL; oldret = NULL; + } /*can free temps used for arguments now*/ if (callconvention == OP_CALL1H) @@ -3139,10 +3219,15 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i //restore the class owner if (oself) { - QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, false); + QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, self->ofs, 0, false); QCC_FreeTemp(oself); } + if (t->type == ev_variant) + def_ret.type = type_variant; + else + def_ret.type = t->aux_type; + if (oldret) { if (oldret->temp && !oldret->temp->used) @@ -3162,6 +3247,7 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i else QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, (void*)0xffffffff)); } + def_ret.type = oldrettype; if (def_ret.type->size == 3) QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, (void*)0xffffffff)); else @@ -3173,14 +3259,9 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], i return d; } - if (t->type == ev_variant) - def_ret.type = type_variant; - else - def_ret.type = t->aux_type; if (def_ret.temp->used) QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); def_ret.temp->used = true; - return &def_ret; } @@ -3192,12 +3273,13 @@ PR_ParseFunctionCall QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could have no name set if it's a field call. { QCC_def_t *e, *d, *oself, *out; - int arg; + unsigned int arg; QCC_type_t *t, *p; int extraparms=false; - int np; + unsigned int np; QCC_def_t *param[MAX_PARMS+MAX_EXTRA_PARMS]; + QCC_type_t *paramtypes[MAX_PARMS+MAX_EXTRA_PARMS]; func->timescalled++; @@ -3718,10 +3800,10 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could extraparms = true; np = 0; } - else if (t->num_parms < 0) + else if (t->vargs) { extraparms = true; - np = (t->num_parms * -1) - 1; + np = t->num_parms; } else np = t->num_parms; @@ -3729,9 +3811,13 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could //any temps referenced to build the parameters don't need to be locked. if (!QCC_PR_CheckToken(")")) { - p = t->param; do { + if (arg >= t->num_parms) + p = NULL; + else + p = t->params[arg].type; + if (extraparms && arg >= MAX_PARMS) QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS); else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS) @@ -3780,20 +3866,6 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could } } - if (arg>=MAX_PARMS) - { - if (!extra_parms[arg - MAX_PARMS]) - { - d = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t)); - d->name = "extra parm"; - d->ofs = QCC_GetFreeGlobalOffsetSpace (3); - extra_parms[arg - MAX_PARMS] = d; - } - d = extra_parms[arg - MAX_PARMS]; - } - else - d = &def_parms[arg]; - if (pr_classtype && e->type->type == ev_field && p->type != ev_field) { //convert. oself = QCC_PR_GetDef(type_entity, "self", NULL, true, 0, false); @@ -3862,22 +3934,16 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function)) { - QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2))); + QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2))); QCC_PR_ParsePrintDef(WARN_LAXCAST, func); } else - QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2))); + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2))); } } + p = e->type; } - - d->type = p; - - p=p->next; } - // a vector copy will copy everything - else - d->type = type_void; if (arg == 1 && !STRCMP(func->name, "setmodel")) { @@ -3885,6 +3951,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could } param[arg] = e; + paramtypes[arg] = p; /* if (e->type->size>1) QCC_PR_Statement (&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff); else @@ -3893,7 +3960,10 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could arg++; } while (QCC_PR_CheckToken (",")); - if (t->num_parms != -1 && arg < np) + //don't warn if we omited optional arguments + while (np > arg && func->type->params[np-1].optional) + np--; + if (arg < np) QCC_PR_ParseWarning (WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name); QCC_PR_Expect (")"); } @@ -3903,7 +3973,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could QCC_PR_ParsePrintDef (WARN_TOOFEWPARAMS, func); } - return QCC_PR_GenerateFunctionCall(func, param, arg); + return QCC_PR_GenerateFunctionCall(func, param, paramtypes, arg); } int constchecks; @@ -4113,7 +4183,6 @@ QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type) return newtype; } -int basictypefield[ev_union+1]; char *basictypenames[] = { "void", "string", @@ -4130,9 +4199,8 @@ char *basictypenames[] = { QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas) { //if a member exists, return the member field (rather than mapped-to field) - QCC_type_t *mt; QCC_def_t *def; - int p, np; + unsigned int p; char membername[2048]; if (!clas) @@ -4143,17 +4211,18 @@ QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas) return NULL; } - np = clas->num_parms; - for (p = 0, mt = clas->param; p < np; p++, mt = mt->next) + for (p = 0; p < clas->num_parms; p++) { - if (strcmp(mt->name, name)) + if (strcmp(clas->params[p].paramname, name)) continue; //the parent has it. - sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name); + sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, clas->params[p].paramname); def = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); - return def; + if (def) + return def; + break; } return QCC_MemberInParentClass(name, clas->parentclass); @@ -4162,45 +4231,57 @@ QCC_def_t *QCC_MemberInParentClass(char *name, QCC_type_t *clas) //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) +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]; - int p, np, a; + 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); + QCC_PR_EmitFieldsForMembers(clas->parentclass, basictypefield); - np = clas->num_parms; - mt = clas->param; - for (p = 0; p < np; p++, mt = mt->next) + for (p = 0; p < clas->num_parms; p++) { - sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, mt->name); + mt = clas->params[p].type; + sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, clas->params[p].paramname); m = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); - f = QCC_MemberInParentClass(mt->name, clas->parentclass); + f = QCC_MemberInParentClass(clas->params[p].paramname, clas->parentclass); if (f) { + 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+f->ofs]; + ((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_NewType(basictypenames[mt->type], ev_field, false); @@ -4209,36 +4290,47 @@ void QCC_PR_EmitFieldsForMembers(QCC_type_t *clas) 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, 0, true); + 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++; } } } -void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_def_t *ed, QCC_def_t **constructor) +void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_def_t *ed) { //go through clas, do the virtual thing only if the child class does not override. char membername[2048]; QCC_type_t *type; QCC_type_t *oc; - int p; + unsigned int p; QCC_def_t *point, *member; QCC_def_t *virt; if (clas->parentclass) - QCC_PR_EmitClassFunctionTable(clas->parentclass, childclas, ed, constructor); + QCC_PR_EmitClassFunctionTable(clas->parentclass, childclas, ed); - type = clas->param; - for (p = 0; p < clas->num_parms; p++, type = type->next) + for (p = 0; p < clas->num_parms; p++) { + type = clas->params[p].type; for (oc = childclas; oc != clas; oc = oc->parentclass) { - sprintf(membername, "%s::"MEMBERFIELDNAME, oc->name, type->name); + sprintf(membername, "%s::"MEMBERFIELDNAME, oc->name, clas->params[p].paramname); if (QCC_PR_GetDef(NULL, membername, NULL, false, 0, false)) break; //a child class overrides. } @@ -4247,20 +4339,27 @@ 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, 0, false); + member = NULL; + for (oc = childclas; oc && !member; oc = oc->parentclass) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, oc->name, clas->params[p].paramname); + member = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); + } if (!member) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, clas->name, clas->params[p].paramname); + QCC_PR_Warning(ERR_INTERNAL, NULL, 0, "Member function %s was not defined", membername); + continue; + } + sprintf(membername, "%s::%s", clas->name, clas->params[p].paramname); + virt = QCC_PR_GetDef(type, membername, NULL, false, 0, false); + if (!virt) { QCC_PR_Warning(0, NULL, 0, "Member function %s was not defined", membername); continue; } - if (!strcmp(type->name, clas->name)) - { - *constructor = member; - } 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, 0, false); + type_pointer->aux_type = virt->type; QCC_PR_Statement(&pr_opcodes[OP_STOREP_FNC], virt, point, NULL); } } @@ -4269,13 +4368,15 @@ void QCC_PR_EmitClassFunctionTable(QCC_type_t *clas, QCC_type_t *childclas, QCC_ //take all functions in the type, and parent types, and make sure the links all work properly. void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) { - QCC_type_t *basetype; + QCC_type_t *basetype, *parenttype; QCC_dfunction_t *df; QCC_def_t *virt; QCC_def_t *ed, *oself, *self; QCC_def_t *constructor = NULL; + pbool constructed = false; + int basictypefield[ev_union+1]; // int func; @@ -4288,7 +4389,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) pr_scope = NULL; memset(basictypefield, 0, sizeof(basictypefield)); - QCC_PR_EmitFieldsForMembers(basetype); + QCC_PR_EmitFieldsForMembers(basetype, basictypefield); @@ -4298,7 +4399,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) df = &functions[numfunctions]; numfunctions++; - df->s_file = 0; + df->s_file = scope->s_file; df->s_name = 0; df->first_statement = numstatements; df->parm_size[0] = 1; @@ -4310,27 +4411,42 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) //locals here... ed = QCC_PR_GetDef(type_entity, "ent", pr_scope, true, 0, false); - virt = QCC_PR_GetDef(type_function, "spawn", NULL, false, 0, false); + virt = QCC_PR_GetDef(NULL, "spawn", NULL, false, 0, false); if (!virt) QCC_Error(ERR_INTERNAL, "spawn function was not defined\n"); QCC_PR_SimpleStatement(OP_CALL0, virt->ofs, 0, 0, false); //calling convention doesn't come into it. + def_ret.type = ed->type; QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], &def_ret, ed, NULL)); ed->references = 1; //there may be no functions. - QCC_PR_EmitClassFunctionTable(basetype, basetype, ed, &constructor); + QCC_PR_EmitClassFunctionTable(basetype, basetype, ed); - if (constructor) - { //self = ent; - self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, 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); - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], oself, self, NULL)); + //FIXME: these constructors are called in the wrong order + constructor = NULL; + for (parenttype = basetype; parenttype; parenttype = parenttype->parentclass) + { + char membername[2048]; + sprintf(membername, "%s::%s", parenttype->name, parenttype->name); + constructor = QCC_PR_GetDef(NULL, membername, NULL, false, 0, false); + + if (constructor) + { //self = ent; + self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false); + oself = QCC_PR_GetDef(type_entity, "oself", scope, true, 0, false); + if (!constructed) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL)); + constructed = true; + } + 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); + } } + if (constructed) + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], oself, self, NULL)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], ed, NULL, NULL)); //apparently we do actually have to return something. *sigh*... QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_DONE], NULL, NULL, NULL)); @@ -4344,6 +4460,104 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, char *tname) df->numparms = locals_end - locals_start; } +QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign); +/*checks for .foo an expands in a class-aware fashion +normally invoked via QCC_PR_ParseArrayPointer +*/ +static QCC_def_t *QCC_PR_ParseField(QCC_def_t *d) +{ + QCC_def_t *tmp; + QCC_type_t *t; + t = d->type; + if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || 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) + { + QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type"); + d = 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"); + break; + case ev_integer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL); + break; + case ev_pointer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_P], 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_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_ParseError(ERR_INTERNAL, "Bad field type"); + } + return d; +} + +/*checks for: +[X] +[X].foo +.foo +within types which are a contiguous block, expanding to an array index. + +Also calls QCC_PR_ParseField, which does fields too. +*/ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) { QCC_type_t *t; @@ -4351,21 +4565,25 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) QCC_def_t *tmp; QCC_dstatement_t *st; pbool allowarray; + unsigned int arraysize; t = d->type; + arraysize = d->arraysize; idx = NULL; while(1) { allowarray = false; if (idx) - allowarray = t->arraysize>0 || - (t->type == ev_vector); + allowarray = arraysize>0 || + (t->type == ev_vector) || + (t->type == ev_field && t->aux_type->type == ev_vector); else if (!idx) { - allowarray = d->arraysize || + allowarray = arraysize>0 || (d->type->type == ev_pointer) || (d->type->type == ev_string) || - (d->type->type == ev_vector); + (d->type->type == ev_vector) || + (d->type->type == ev_field && d->type->aux_type->type == ev_vector); } if (allowarray && QCC_PR_CheckToken("[")) @@ -4374,19 +4592,20 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) QCC_PR_Expect("]"); /*if its a pointer that got dereferenced, follow the type*/ - if (!idx && t->type == ev_pointer && !d->arraysize) + if (!idx && t->type == ev_pointer && !arraysize) t = t->aux_type; if (!idx && d->type->type == ev_pointer) { /*no bounds checks on pointer dereferences*/ } - else if (!idx && d->type->type == ev_string && !d->arraysize) + else if (!idx && d->type->type == ev_string && !arraysize) { /*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) || (idx && t->type == ev_vector && !t->arraysize)) + else if ((!idx && d->type->type == ev_vector && !arraysize) || (idx && t->type == ev_vector && !arraysize)) { + /*array notation on vector*/ if (tmp->constant) { unsigned int i; @@ -4406,7 +4625,29 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) } t = type_float; } - else if (!((!idx)?d->arraysize:t->arraysize)) + else if ((!idx && d->type->type == ev_field && d->type->aux_type->type == ev_vector && !arraysize) || (idx && t->type == ev_field && t->aux_type->type && !arraysize)) + { + /*array notation on vector field*/ + 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); + else + i = -1; + if (i < 0 || i >= 3) + QCC_PR_ParseErrorPrintDef(0, d, "(vector) array index out of bounds"); + } + else if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK])) + { + tmp = QCC_SupplyConversion(tmp, ev_integer, true); + QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, 3, 0, false); + } + t = type_floatfield; + } + else if (!arraysize) { QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array"); } @@ -4419,7 +4660,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) i = G_FLOAT(tmp->ofs); else i = -1; - if (i < 0 || i >= ((!idx)?d->arraysize:t->arraysize)) + if (i < 0 || i >= arraysize) QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds"); } else @@ -4427,9 +4668,10 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK])) { tmp = QCC_SupplyConversion(tmp, ev_integer, true); - QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ((!idx)?d->arraysize:t->arraysize), 0, false); + QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, arraysize, 0, false); } } + arraysize = 0; if (t->size != 1) /*don't multiply by type size if the instruction/emulation will do that instead*/ { @@ -4449,23 +4691,30 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) } else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))) { - if (!idx && t->type == ev_pointer && !d->arraysize) + char *tname; + unsigned int i; + if (!idx && t->type == ev_pointer && !arraysize) t = t->aux_type; + tname = t->name; - for (t = t->param; t; t = t->next) + if (t->type == ev_struct || t->type == ev_union) { - if (QCC_PR_CheckName(t->name)) - { - break; - } - + if (!t->size) + QCC_PR_ParseError(0, "%s was not defined yet", tname); } - if (!t) - QCC_PR_ParseError(0, "%s is not a member", pr_token); + else + QCC_PR_ParseError(0, "indirection in something that is not a struct or union", tname); + for (i = 0; i < t->num_parms; i++) + { + if (QCC_PR_CheckName(t->params[i].paramname)) + break; + } + if (i == t->num_parms) + QCC_PR_ParseError(0, "%s is not a member of %s", pr_token, tname); if (QCC_OPCodeValid(&pr_opcodes[OP_ADD_I])) { - tmp = QCC_MakeIntConst(t->ofs); + tmp = QCC_MakeIntConst(t->params[i].ofs); if (idx) idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); else @@ -4473,12 +4722,14 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) } else { - tmp = QCC_MakeFloatConst(t->ofs); + tmp = QCC_MakeFloatConst(t->params[i].ofs); if (idx) idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, tmp, NULL); else idx = tmp; } + t = t->params[i].type; + arraysize = t->params[i].arraysize; } else break; @@ -4525,14 +4776,20 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) d->type = t; } else if (d->type->type == ev_string && d->arraysize == 0) - { + { //array notation on strings d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL); + //d->type = type_float; } else if (d->type->type == ev_vector && d->arraysize == 0) - { + { //array notation on vectors (non-field) d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), (QCC_dstatement_t **)0xffffffff); d->type = type_float; } + else if (d->type->type == ev_field && d->type->aux_type->type == ev_vector && d->arraysize == 0) + { //array notation on vectors (fields) + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), (QCC_dstatement_t **)0xffffffff); + d->type = type_floatfield; + } 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*/ @@ -4585,7 +4842,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) tmp->arraysize = 0; tmp->ofs = d->ofs + cidx; d = tmp; - + d->type = t; //d can be assigned to freely } else if (allowarrayassign && QCC_PR_CheckToken("=")) @@ -4603,7 +4860,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) args[0] = QCC_SupplyConversion(idx, ev_float, true); args[1] = rhs; qcc_usefulstatement=true; - d = QCC_PR_GenerateFunctionCall(funcretr, args, 2); + d = QCC_PR_GenerateFunctionCall(funcretr, args, NULL, 2); d->type = t; return d; @@ -4668,7 +4925,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 0, false); args[0] = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], QCC_SupplyConversion(idx, ev_float, true), QCC_MakeFloatConst(3), NULL); - d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + d = QCC_PR_GenerateFunctionCall(funcretr, args, NULL, 1); d->type = t; } else @@ -4693,7 +4950,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) args[0] = idx; opt_assignments = false; } - r = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + r = QCC_PR_GenerateFunctionCall(funcretr, args, &type_float, 1); opt_assignments = old_op; QCC_UnFreeTemp(idx); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], r, d, (QCC_dstatement_t **)0xffffffff)); @@ -4706,7 +4963,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) else { args[0] = QCC_SupplyConversion(idx, ev_float, true); - d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + d = QCC_PR_GenerateFunctionCall(funcretr, args, &type_float, 1); } d->type = t; } @@ -4716,6 +4973,7 @@ QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign) d = QCC_PR_ParseArrayPointer(d, allowarrayassign); } + d = QCC_PR_ParseField(d); return d; } @@ -4728,7 +4986,7 @@ 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_def_t *d, *od; QCC_type_t *t; char *name; @@ -4819,29 +5077,66 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) QCC_UnFreeTemp(d); return d; } + + if (QCC_PR_CheckToken("::")) + assumeclass = NULL; 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) + if (QCC_PR_CheckToken("::")) + { + if (assumeclass && !strcmp(name, "super")) + t = assumeclass->parentclass; + else + t = QCC_TypeForName(name); + if (!t || t->type != ev_entity) { - sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); - d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); - if (d) - break; - - type = type->parentclass; + QCC_PR_ParseError (ERR_NOTATYPE, "Not a class \"%s\"", name); + d = NULL; + } + else + { + QCC_type_t *p; + char membername[1024]; + name = QCC_PR_ParseName (); + //walk up the parents if needed, to find one that has that field + for(d = NULL, p = t; !d && p; p = p->parentclass) + { + sprintf(membername, "%s::%s", p->name, name); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + if (!d) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, p->name, name); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + if (d) + { + d = d; + } + } + } + if (!d) + { + QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s::%s\"", t->name, name); + } } - 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); + + // 'testvar' becomes 'self::testvar' + if (assumeclass && assumeclass->parentclass) + { //try getting a member. + QCC_type_t *type; + type = assumeclass; + while(!d && type) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + + type = type->parentclass; + } + } } if (!d) @@ -4864,10 +5159,12 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) } else if (keyword_class && !strcmp(name, "super")) { - if (!pr_classtype) + if (!assumeclass) QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n"); + if (!assumeclass->parentclass) + QCC_PR_ParseError(ERR_NOTANAME, "class %s has no super\n", pr_classtype->name); od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false); - d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 0, od->ofs, true, GDF_CONST); + d = QCC_PR_DummyDef(assumeclass->parentclass, "super", pr_scope, 0, od->ofs, true, GDF_CONST); } else { @@ -4881,76 +5178,23 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) } } + if (pr_classtype && !strcmp(name, "self")) + { + QCC_PR_ParseWarning (WARN_SELFNOTTHIS, "'self' used inside OO function, use 'this'.", pr_scope->name); + + if (!pr_classtype) + QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n"); + d = QCC_PR_GetDef(NULL, "this", pr_scope, false, 0, false); + if (!d) + { + od = QCC_PR_GetDef(NULL, "self", NULL, true, 0, false); + d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 0, od->ofs, true, GDF_CONST); + } + } + d = QCC_PR_ParseArrayPointer(d, allowarrayassign); - t = d->type; - if (keyword_class && t->type == ev_entity && t->parentclass && (QCC_PR_CheckToken(".") || 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) - { - QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type"); - d = 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"); - 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); - } + d = QCC_PR_ParseField(d); return d; } @@ -5067,7 +5311,7 @@ QCC_def_t *QCC_PR_Term (int exprflags) 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) + else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I || statements[numstatements-1].op == OP_LOADA_STRUCT) { statements[numstatements-1].op = OP_GLOBALADDRESS; e->type = QCC_PR_PointerType(e->type); @@ -5227,6 +5471,8 @@ QCC_def_t *QCC_PR_Term (int exprflags) ((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) + //functions can be explicitly cast from one to another + || (newtype->type == ev_function && e->type->type == ev_function) //variants are fine too || (newtype->type == ev_variant || e->type->type == ev_variant) ) @@ -5244,86 +5490,15 @@ QCC_def_t *QCC_PR_Term (int exprflags) 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(); - if (e->type->type == ev_float) - return e; - else if (e->type->type == ev_integer) - return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL); - else if (e->type->type == ev_function) - return e; - // else - // QCC_PR_ParseError ("invalid typecast"); - - QCC_PR_ParseWarning (0, "Not all vars make sence as floats"); - - e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - memset (e2, 0, sizeof(QCC_def_t)); - e2->type = type_float; - e2->ofs = e->ofs; - e2->constant = true; - e2->temp = e->temp; - return e2; - } - else if (QCC_PR_CheckKeyword(keyword_class, "class")) - { - QCC_type_t *classtype = QCC_TypeForName(QCC_PR_ParseName()); - if (!classtype) - QCC_PR_ParseError(ERR_NOTANAME, "Class not defined for cast"); - - QCC_PR_Expect (")"); - e = QCC_PR_Term(); - e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); - memset (e2, 0, sizeof(QCC_def_t)); - e2->type = classtype; - e2->ofs = e->ofs; - e2->constant = true; - e2->temp = e->temp; - return e2; - } - else if (QCC_PR_CheckKeyword(keyword_integer, "integer")) //check for type casts - { - QCC_PR_Expect (")"); - e = QCC_PR_Term(); - if (e->type->type == ev_integer) - return e; - else if (e->type->type == ev_float) - return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL); - else - QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast"); - } - else if (QCC_PR_CheckKeyword(keyword_int, "int")) //check for type casts - { - QCC_PR_Expect (")"); - e = QCC_PR_Term(); - if (e->type->type == ev_integer) - return e; - else if (e->type->type == ev_float) - return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL); - else - QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast"); - } -*/ else + else { pbool oldcond = conditional; conditional = conditional?2:0; e = QCC_PR_Expression (TOP_PRIORITY, 0); QCC_PR_Expect (")"); conditional = oldcond; + + QCC_PR_ParseArrayPointer(e, true); } return e; } @@ -5400,6 +5575,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) { qcc_usefulstatement=true; e = QCC_PR_ParseFunctionCall (e); + e = QCC_PR_ParseArrayPointer(e, true); } if (QCC_PR_CheckToken ("?")) { @@ -5460,14 +5636,14 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) { qcc_usefulstatement=true; statements[numstatements-1].op = OP_ADDRESS; - type_pointer->aux_type->type = e->type->type; + type_pointer->aux_type = e->type; e->type = type_pointer; } //if last statement retrieved a value, switch it to retrieve a usable pointer. if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADA_F) < 7)// || statements[numstatements-1].op == OP_LOADA_C) { statements[numstatements-1].op = OP_GLOBALADDRESS; - type_pointer->aux_type->type = e->type->type; + type_pointer->aux_type = e->type; e->type = type_pointer; } if ( !simplestore && (unsigned)(statements[numstatements-1].op - OP_LOADP_F) < 7 && statements[numstatements-1].c == e->ofs) @@ -5485,7 +5661,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) } if (e->type != type_pointer) { - type_pointer->aux_type->type = e->type->type; + type_pointer->aux_type = e->type; e->type = type_pointer; } } @@ -5572,14 +5748,14 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) } else { - if (op->type_a == &type_pointer) //ent var + /*if (op->type_a == &type_pointer) //ent var { if (e2->type->type != ev_pointer || e2->type->aux_type->type != (*op->type_b)->type) //if e isn't a pointer to a type_b c = -200; //don't let the conversion work else c = 0; } - else + else*/ { c=QCC_canConv(e, (*op->type_a)->type); c+=QCC_canConv(e2, (*op->type_b)->type); @@ -6025,7 +6201,10 @@ void QCC_PR_ParseStatement (void) } QCC_PR_Expect (";"); if (pr_scope->type->aux_type->type != e->type->type) - QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); + { + e = QCC_SupplyConversion(e, e->type->type, true); +// QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); + } QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], e, 0, NULL)); return; } @@ -6243,27 +6422,37 @@ void QCC_PR_ParseStatement (void) if (QCC_PR_CheckKeyword(keyword_local, "local")) { - QCC_type_t *functionsclasstype = pr_classtype; // if (locals_end != numpr_globals) //is this breaking because of locals? // QCC_PR_ParseWarning("local vars after temp vars\n"); QCC_PR_ParseDefs (NULL); - pr_classtype = functionsclasstype; return; } if (pr_token_type == tt_name) - if ((keyword_var && !STRCMP ("var", pr_token)) || - (keyword_string && !STRCMP ("string", pr_token)) || - (keyword_float && !STRCMP ("float", pr_token)) || - (keyword_entity && !STRCMP ("entity", pr_token)) || - (keyword_vector && !STRCMP ("vector", pr_token)) || - (keyword_integer && !STRCMP ("integer", pr_token)) || - (keyword_int && !STRCMP ("int", pr_token)) || - (keyword_class && !STRCMP ("class", pr_token)) || - (keyword_const && !STRCMP ("const", pr_token))) { - QCC_PR_ParseDefs (NULL); - return; + QCC_type_t *type = QCC_TypeForName(pr_token); + if (type && type->typedefed) + { + if (strncmp(pr_file_p, "::", 2)) + { + QCC_PR_ParseDefs (NULL); + return; + } + } + + if ((keyword_var && !STRCMP ("var", pr_token)) || + (keyword_string && !STRCMP ("string", pr_token)) || + (keyword_float && !STRCMP ("float", pr_token)) || + (keyword_entity && !STRCMP ("entity", pr_token)) || + (keyword_vector && !STRCMP ("vector", pr_token)) || + (keyword_integer && !STRCMP ("integer", pr_token)) || + (keyword_int && !STRCMP ("int", pr_token)) || + (keyword_class && !STRCMP ("class", pr_token)) || + (keyword_const && !STRCMP ("const", pr_token))) + { + QCC_PR_ParseDefs (NULL); + return; + } } if (QCC_PR_CheckKeyword(keyword_state, "state")) @@ -7450,7 +7639,7 @@ void QCC_CommonSubExpressionRemoval(int first, int last) //follow branches (by recursing). //stop on first read(error, return statement) or write(no error, return -1) //end-of-block returns 0, done/return/goto returns -2 -int QCC_CheckOneUninitialised(int firststatement, int laststatement, int min, int max) +int QCC_CheckOneUninitialised(int firststatement, int laststatement, unsigned int min, unsigned int max) { int ret; int i; @@ -7553,15 +7742,17 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, int min, in pbool QCC_CheckUninitialised(int firststatement, int laststatement) { QCC_def_t *local; - int i; + unsigned int i; int min,max; pbool result = false; - int paramend = FIRST_LOCAL; + unsigned int paramend = FIRST_LOCAL; QCC_type_t *type = pr_scope->type; int err; - for (type = pr_scope->type, i = type->num_parms, type = type->param; i > 0; i--, type = type->next) - paramend += type->size; + for (i = 0; i < type->num_parms; i++) + { + paramend += type->params[i].type->size; + } for (local = pr.localvars; local; local = local->nextlocal) { @@ -7678,7 +7869,6 @@ void QCC_Marshal_Locals(int firststatement, int laststatement) void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm) { unsigned int i; - unsigned int p; gofs_t o; QCC_type_t *type; QCC_def_t *param; @@ -7689,8 +7879,7 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir type = sc->type; fprintf(asmfile, "%s(", TypeName(type->aux_type, typebuf, sizeof(typebuf))); - p = type->num_parms; - for (o = firstparm, i = 0, type = type->param; i < p; i++, type = type->next) + for (o = firstparm, i = 0; i < type->num_parms; i++) { if (i) fprintf(asmfile, ", "); @@ -7701,11 +7890,11 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir break; } if (param) - fprintf(asmfile, "%s %s", TypeName(type, typebuf, sizeof(typebuf)), param->name); + fprintf(asmfile, "%s %s", TypeName(param->type, typebuf, sizeof(typebuf)), param->name); else - fprintf(asmfile, "%s", TypeName(type, typebuf, sizeof(typebuf))); + fprintf(asmfile, "%s", TypeName(type->params[i].type, typebuf, sizeof(typebuf))); - o += type->size; + o += type->params[i].type->size; } fprintf(asmfile, ") %s = asm\n{\n", sc->name); @@ -7776,11 +7965,9 @@ Parse a function body */ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) { - int i; + unsigned int u; QCC_function_t *f; QCC_def_t *defs[MAX_PARMS+MAX_EXTRA_PARMS], *e2; - - QCC_type_t *parm; pbool needsdone=false; conditional = 0; @@ -7834,43 +8021,41 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) locals_start = locals_end = FIRST_LOCAL; - parm = type->param; - for (i=0 ; inum_parms ; i++) + for (u=0 ; unum_parms ; u++) { - if (!*pr_parm_names[i]) + if (!*pr_parm_names[u]) QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named"); - defs[i] = QCC_PR_GetDef (parm, pr_parm_names[i], pr_scope, true, 0, false); + defs[u] = QCC_PR_GetDef (type->params[u].type, pr_parm_names[u], pr_scope, true, 0, false); - defs[i]->references++; - if (i < MAX_PARMS) + defs[u]->references++; + if (u < MAX_PARMS) { - f->parm_ofs[i] = defs[i]->ofs; - if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1]) + f->parm_ofs[u] = defs[u]->ofs; + if (u > 0 && f->parm_ofs[u] < f->parm_ofs[u-1]) QCC_Error (ERR_BADPARAMORDER, "bad parm order"); - if (i > 0 && f->parm_ofs[i] != f->parm_ofs[i-1]+defs[i-1]->type->size) + if (u > 0 && f->parm_ofs[u] != f->parm_ofs[u-1]+defs[u-1]->type->size) QCC_Error (ERR_BADPARAMORDER, "parms not packed"); } - parm = parm->next; } f->code = numstatements; if (type->num_parms > MAX_PARMS) { - for (i = MAX_PARMS; i < type->num_parms; i++) + for (u = MAX_PARMS; u < type->num_parms; u++) { - if (!extra_parms[i - MAX_PARMS]) + if (!extra_parms[u - MAX_PARMS]) { e2 = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t)); e2->name = "extra parm"; e2->ofs = QCC_GetFreeGlobalOffsetSpace(3); - extra_parms[i - MAX_PARMS] = e2; + extra_parms[u - MAX_PARMS] = e2; } - extra_parms[i - MAX_PARMS]->type = defs[i]->type; - if (defs[i]->type->type != ev_vector) - QCC_PR_Statement (&pr_opcodes[OP_STORE_F], extra_parms[i - MAX_PARMS], defs[i], NULL); + extra_parms[u - MAX_PARMS]->type = defs[u]->type; + if (defs[u]->type->type != ev_vector) + QCC_PR_Statement (&pr_opcodes[OP_STORE_F], extra_parms[u - MAX_PARMS], defs[u], NULL); else - QCC_PR_Statement (&pr_opcodes[OP_STORE_V], extra_parms[i - MAX_PARMS], defs[i], NULL); + QCC_PR_Statement (&pr_opcodes[OP_STORE_V], extra_parms[u - MAX_PARMS], defs[u], NULL); } } @@ -7933,7 +8118,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) if (num_gotos) { - int j; + int i, j; for (i = 0; i < num_gotos; i++) { for (j = 0; j < num_labels; j++) @@ -8475,23 +8660,23 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a if (type->type == ev_struct) { - int partnum; + unsigned int partnum; QCC_type_t *parttype; - parttype = type->param; for (partnum = 0; partnum < type->num_parms; partnum++) { + parttype = type->params[partnum].type; switch (parttype->type) { case ev_vector: - sprintf(newname, "%s%s.%s", name, array, parttype->name); - QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, flags | GDF_CONST); + sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs, false, flags | GDF_CONST); - sprintf(newname, "%s%s.%s_x", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs, false, flags | GDF_CONST); - sprintf(newname, "%s%s.%s_y", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+1, false, flags | GDF_CONST); - sprintf(newname, "%s%s.%s_z", name, array, parttype->name); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + parttype->ofs+2, false, flags | GDF_CONST); + sprintf(newname, "%s%s.%s_x", name, array, type->params[partnum].paramname); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs, false, flags | GDF_CONST); + sprintf(newname, "%s%s.%s_y", name, array, type->params[partnum].paramname); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs+1, false, flags | GDF_CONST); + sprintf(newname, "%s%s.%s_z", name, array, type->params[partnum].paramname); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs+2, false, flags | GDF_CONST); break; case ev_float: @@ -8503,28 +8688,27 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a case ev_struct: 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, 0, ofs + type->size*a + parttype->ofs, false, flags); + sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs, false, flags); break; case ev_function: sprintf(newname, "%s%s.%s", name, array, parttype->name); - QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a +parttype->ofs, false, flags)->initialized = true; + QCC_PR_DummyDef(parttype, newname, scope, 0, ofs + type->size*a + type->params[partnum].ofs, false, flags)->initialized = true; break; case ev_void: break; } - parttype=parttype->next; } } else if (type->type == ev_vector) { //do the vector thing. sprintf(newname, "%s%s_x", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+0, referable, flags); sprintf(newname, "%s%s_y", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+1, referable, flags); sprintf(newname, "%s%s_z", name, array); - QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_float, newname, scope, 0, ofs + type->size*a+2, referable, flags); } else if (type->type == ev_field) { @@ -8532,11 +8716,11 @@ 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, 0, ofs + type->size*a+0, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+0, referable, flags); sprintf(newname, "%s%s_y", name, array); - QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+1, referable, flags); sprintf(newname, "%s%s_z", name, array); - QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, flags | GDF_CONST); + QCC_PR_DummyDef(type_floatfield, newname, scope, 0, ofs + type->size*a+2, referable, flags); } } first->deftail = pr.def_tail; @@ -8638,18 +8822,14 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool else { int d=0, t=0; - QCC_type_t *p; QCC_PR_ParseWarning (WARN_LAXCAST, "Optional arguments differ on redeclaration of %s. %s, should be %s",name, TypeName(type, typebuf1, sizeof(typebuf1)), TypeName(def->type, typebuf2, sizeof(typebuf2))); QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def); if (type->type == ev_function) { //update the def's type to the new one if the mandatory argument count is longer - for (p = def->type->param; p; p = p->next) - d++; - for (p = type->param; p; p = p->next) - t++; - if (t > d) + //FIXME: don't change the param names! + if (type->num_parms > def->type->num_parms) def->type = type; } } @@ -8868,16 +9048,16 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, QCC_type_t *parttype; if (def) def->references++; - parttype = (type)->param; isunion = ((type)->type == ev_union); for (partnum = 0, parms = (type)->num_parms; partnum < parms; partnum++) { + parttype = type->params[partnum].type; switch (parttype->type) { case ev_union: case ev_struct: if (*name) - sprintf(newname, "%s%s.%s", name, array, parttype->name); + sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); else sprintf(newname, "%s%s", parttype->name, array); def = QCC_PR_DummyFieldDef(parttype, newname, scope, 1, fieldofs, saved); @@ -8891,7 +9071,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, case ev_integer: case ev_variant: if (*name) - sprintf(newname, "%s%s.%s", name, array, parttype->name); + sprintf(newname, "%s%s.%s", name, array, type->params[partnum].paramname); else sprintf(newname, "%s%s", parttype->name, array); ftype = QCC_PR_NewType("FIELD TYPE", ev_field, false); @@ -8931,7 +9111,6 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, char *name, QCC_def_t *scope, *fieldofs = startfield; type = parttype; - parttype=parttype->next; } } } @@ -8974,7 +9153,6 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type QCC_def_t *parentfunc = pr_scope; QCC_function_t *f; QCC_dfunction_t *df; - QCC_type_t *parm; tmp = NULL; @@ -9040,9 +9218,9 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type 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) + for (i=0 ; inumparms ; i++) { - df->parm_size[i] = parm->size; + df->parm_size[i] = type->params[i].type->size; } /*end function special case*/ } @@ -9070,16 +9248,14 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type else if (type->type == ev_struct || type->type == ev_union) { //structs go recursive - QCC_type_t *parttype; - int partnum; - int parms; + unsigned int partnum; 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) + for (partnum = 0; partnum < (type)->num_parms; partnum++) { - QCC_PR_ParseInitializerType(parttype->arraysize, def, parttype, offset + parttype->ofs); + QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, def, (type)->params[partnum].type, offset + (type)->params[partnum].ofs); if (isunion || !QCC_PR_CheckToken(",")) break; } @@ -9095,6 +9271,10 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs)) { } + /*universal pointers can assign without casts*/ + else if (type->type == ev_pointer && tmp->type->type == ev_pointer && (type->aux_type->type == ev_void || tmp->type->aux_type->type == ev_void || type->aux_type->type == ev_variant || tmp->type->aux_type->type == ev_variant)) + { + } /*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); @@ -9102,7 +9282,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type 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"); + QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type for %s. got %s, needed %s", def->name, tmp->type->name, type->name); } } @@ -9175,7 +9355,7 @@ Called at the outer layer and when a local statement is hit void QCC_PR_ParseDefs (char *classname) { char *name; - QCC_type_t *type, *parm; + QCC_type_t *type, *defclass; QCC_def_t *def, *d; QCC_function_t *f; QCC_dfunction_t *df; @@ -9415,7 +9595,17 @@ void QCC_PR_ParseDefs (char *classname) { QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens"); } - type->name = QCC_CopyString(pr_token)+strings; + if (QCC_PR_CheckToken("*")) + { + QCC_type_t *ptr; + ptr = QCC_PR_NewType(QCC_CopyString(pr_token)+strings, ev_pointer, false); + ptr->aux_type = type; + type = ptr; + } + else + { + type->name = QCC_CopyString(pr_token)+strings; + } type->typedefed = true; QCC_PR_Lex(); QCC_PR_Expect(";"); @@ -9671,9 +9861,9 @@ void QCC_PR_ParseDefs (char *classname) 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) + for (i=0 ; inumparms ; i++) { - df->parm_size[i] = parm->size; + df->parm_size[i] = type->params[i].type->size; } return; @@ -9691,6 +9881,8 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_ExpandUnionToFields(type, &pr.size_fields); return; } + if (type->type == ev_struct && strcmp(type->name, "struct")) + return; //allow named structs // if (type->type == ev_union) // { // return; @@ -9714,10 +9906,12 @@ void QCC_PR_ParseDefs (char *classname) if ( QCC_PR_CheckToken ("[") ) { char *oldprfile = pr_file_p; + int oldline = pr_source_line; int depth; arraysize = 0; if (QCC_PR_CheckToken("]")) { + //FIXME: preprocessor will hate this with a passion. QCC_PR_Expect("="); QCC_PR_Expect("{"); arraysize++; @@ -9743,6 +9937,7 @@ void QCC_PR_ParseDefs (char *classname) QCC_PR_Lex(); } pr_file_p = oldprfile; + pr_source_line = oldline; QCC_PR_Lex(); } else @@ -9770,20 +9965,15 @@ void QCC_PR_ParseDefs (char *classname) if (classname) { - char typebuf[1024]; char *membername = name; name = qccHunkAlloc(strlen(classname) + strlen(name) + 3); - sprintf(name, "%s::"MEMBERFIELDNAME, classname, membername); - if (!QCC_PR_GetDef(NULL, name, NULL, false, 0, false)) - QCC_PR_ParseError(ERR_NOTANAME, "%s %s is not a member of class %s\n", TypeName(type, typebuf, sizeof(typebuf)), membername, classname); sprintf(name, "%s::%s", classname, membername); - - pr_classtype = QCC_TypeForName(classname); - if (!pr_classtype || !pr_classtype->parentclass) + defclass = QCC_TypeForName(classname); + if (!defclass || !defclass->parentclass) QCC_PR_ParseError(ERR_NOTANAME, "%s is not a class\n", classname); } else - pr_classtype = NULL; + defclass = NULL; gd_flags = 0; if (isstatic) @@ -9847,6 +10037,7 @@ void QCC_PR_ParseDefs (char *classname) } else if ( QCC_PR_CheckToken ("=") || ((type->type == ev_function) && (pr_token[0] == '{' || pr_token[0] == '[' || pr_token[0] == ':'))) //this is an initialisation (or a function) { + QCC_type_t *parentclass; if (def->shared) QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name); if (def->initialized == 1) @@ -9896,8 +10087,11 @@ void QCC_PR_ParseDefs (char *classname) continue; } + parentclass = pr_classtype; + pr_classtype = defclass?defclass:pr_classtype; def->constant = (isconstant || (!isvar && !pr_scope)); QCC_PR_ParseInitializerDef(def); + pr_classtype = parentclass; } else { diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index d8df67b8a..845c44cb9 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -909,9 +909,16 @@ pbool QCC_PR_Precompiler(void) { fclose(asmfile); asmfile = NULL; - } + } if (!asmfile && on) - asmfile = fopen("qc.asm", "wb"); + { + if (asmfilebegun) + asmfile = fopen("qc.asm", "ab"); + else + asmfile = fopen("qc.asm", "wb"); + if (asmfile) + asmfilebegun = true; + } } else if (!strncmp(qcc_token, "sourcefile", 10)) { @@ -2632,7 +2639,7 @@ int QCC_PR_CheckCompConst(void) if (!strncmp(pr_file_p, "__FUNC__", 8)) { static char retbuf[256]; - sprintf(retbuf, "\"%s\"",pr_scope->name); + sprintf(retbuf, "\"%s\"",pr_scope?pr_scope->name:""); pr_file_p = retbuf; QCC_PR_Lex(); //translate the macro's value pr_file_p = oldpr_file_p+8; @@ -3240,6 +3247,7 @@ a new one and copies it out. //0 if same int typecmp(QCC_type_t *a, QCC_type_t *b) { + int i; if (a == b) return 0; if (!a || !b) @@ -3248,31 +3256,29 @@ 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->vargs != b->vargs) + return 1; if (a->size != b->size) return 1; -// if (STRCMP(a->name, b->name)) //This isn't 100% clean. -// return 1; + + if ((a->type == ev_entity && a->parentclass) || a->type == ev_struct || a->type == ev_union) + { + if (STRCMP(a->name, b->name)) + return 1; + } if (typecmp(a->aux_type, b->aux_type)) return 1; - if (a->param || b->param) + i = a->num_parms; + while(i-- > 0) { - a = a->param; - b = b->param; - - while(a || b) - { - if (typecmp(a, b)) - return 1; - - a=a->next; - b=b->next; - } + if (a->type != ev_function && STRCMP(a->params[i].paramname, b->params[i].paramname)) + return 1; + if (typecmp(a->params[i].type, b->params[i].type)) + return 1; } return 0; @@ -3281,8 +3287,8 @@ int typecmp(QCC_type_t *a, QCC_type_t *b) //compares the types, but doesn't complain if there are optional arguments which differ int typecmp_lax(QCC_type_t *a, QCC_type_t *b) { - int numargs = 0; - int t; + unsigned int minargs = 0; + unsigned int t; if (a == b) return 0; if (!a || !b) @@ -3297,14 +3303,10 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b) return 1; t = a->num_parms; - if (t < 0) - t = (t * -1) - 1; - numargs = t; + minargs = t; t = b->num_parms; - if (t < 0) - t = (t * -1) - 1; - if (numargs > t) - numargs = t; + if (minargs > t) + minargs = t; // if (STRCMP(a->name, b->name)) //This isn't 100% clean. // return 1; @@ -3312,18 +3314,38 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b) if (typecmp_lax(a->aux_type, b->aux_type)) return 1; - if (numargs) + //optional arg types must match, even if they're not specified in one. + for (t = 0; t < minargs; t++) { - a = a->param; - b = b->param; - - while(numargs-->0 || (a&&b)) + if (a->params[t].type->type != b->params[t].type->type) + return 1; + //classes/structs/unions are matched on class names rather than the contents of the class + //it gets too painful otherwise, with recursive definitions. + if (a->params[t].type->type == ev_entity || a->params[t].type->type == ev_struct || a->params[t].type->type == ev_union) { - if (typecmp_lax(a, b)) + if (STRCMP(a->params[t].type->name, b->params[t].type->name)) + return 1; + } + else + { + if (typecmp_lax(a->params[t].type, b->params[t].type)) + return 1; + } + } + if (a->num_parms > minargs) + { + for (t = 0; t < a->num_parms; t++) + { + if (!a->params[t].optional) + return 1; + } + } + if (b->num_parms > minargs) + { + for (t = 0; t < b->num_parms; t++) + { + if (!b->params[t].optional) return 1; - - a=a->next; - b=b->next; } } @@ -3331,43 +3353,46 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b) } -QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in) +QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in, pbool recurse) { - QCC_type_t *out, *op, *ip; + QCC_type_t *out; if (!in) return NULL; 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; - op = NULL; - while(ip) - { - if (!op) - out->param = op = QCC_PR_DuplicateType(ip); - else - op = (op->next = QCC_PR_DuplicateType(ip)); - ip = ip->next; - } - out->arraysize = in->arraysize; + out->aux_type = recurse?QCC_PR_DuplicateType(in->aux_type, recurse):in->aux_type; + out->num_parms = in->num_parms; + out->params = qccHunkAlloc(sizeof(*out->params) * out->num_parms); + memcpy(out->params, in->params, sizeof(*out->params) * out->num_parms); out->size = in->size; out->num_parms = in->num_parms; - out->ofs = in->ofs; out->name = in->name; out->parentclass = in->parentclass; return out; } +static void Q_strlcat(char *dest, const char *src, int sizeofdest) +{ + if (sizeofdest) + { + int dlen = strlen(dest); + int slen = strlen(src)+1; + memcpy(dest+dlen, src, min((sizeofdest-1)-dlen, slen)); + dest[sizeofdest - 1] = 0; + } +} + char *TypeName(QCC_type_t *type, char *buffer, int buffersize) { char *ret; if (type->type == ev_pointer) { + if (buffersize < 0) + return buffer; TypeName(type->aux_type, buffer, buffersize-2); - strcat(buffer, " *"); + Q_strlcat(buffer, " *", buffersize); return buffer; } @@ -3381,42 +3406,37 @@ char *TypeName(QCC_type_t *type, char *buffer, int buffersize) 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) + pbool vargs = type->vargs; + unsigned int i; + Q_strlcat(buffer, type->aux_type->name, buffersize); + Q_strlcat(buffer, "(", buffersize); + for (i = 0; i < type->num_parms; ) { - if (args<=0) - strcat(ret, "optional "); + if (type->params[i].optional) + Q_strlcat(buffer, "optional ", buffersize); args--; - strcat(ret, type->name); - if (type->aname) + Q_strlcat(buffer, type->params[i].type->name, buffersize); + if (type->params[i].paramname) { - strcat(ret, " "); - strcat(ret, type->aname); + Q_strlcat(buffer, " ", buffersize); + Q_strlcat(buffer, type->params[i].paramname, buffersize); } - type = type->next; - if (type || varg) - strcat(ret, ", "); + if (++i < type->num_parms || vargs) + Q_strlcat(buffer, ", ", buffersize); } - if (varg) - { - strcat(ret, "..."); - } - strcat(ret, ")"); + if (vargs) + Q_strlcat(buffer, "...", buffersize); + Q_strlcat(buffer, ")", buffersize); } else if (type->type == ev_entity && type->parentclass) { ret = buffer; *ret = 0; - strcat(ret, "class "); - strcat(ret, type->name); + Q_strlcat(buffer, "class ", buffersize); + Q_strlcat(buffer, type->name, buffersize); /* strcat(ret, " {"); type = type->param; while(type) @@ -3431,7 +3451,7 @@ char *TypeName(QCC_type_t *type, char *buffer, int buffersize) */ } else - strcpy(ret, type->name); + Q_strlcat(buffer, type->name, buffersize); return buffer; } @@ -3493,7 +3513,7 @@ QCC_type_t *QCC_TypeForName(char *name) for (i = 0; i < numtypeinfos; i++) { - if (!STRCMP(qcc_typeinfo[i].name, name)) + if (qcc_typeinfo[i].typedefed && !STRCMP(qcc_typeinfo[i].name, name)) { return &qcc_typeinfo[i]; } @@ -3538,11 +3558,12 @@ pbool recursivefunctiontype; //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; + QCC_type_t *ftype, *ptype; char *name; int definenames = !recursivefunctiontype; int optional = 0; int numparms = 0; + struct QCC_typeparam_s paramlist[MAX_PARMS+MAX_EXTRA_PARMS]; recursivefunctiontype++; @@ -3555,67 +3576,62 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) if (!QCC_PR_CheckToken (")")) { - if (QCC_PR_CheckToken ("...")) - ftype->num_parms = -1; // variable args - else - do + do + { + if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS) + QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS); + + if (QCC_PR_CheckToken ("...")) { - if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS) - QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS); + ftype->vargs = true; + break; + } - if (QCC_PR_CheckToken ("...")) - { - if (optional) - numparms = optional-1; - ftype->num_parms = (numparms * -1) - 1; - break; - } - - 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; - if (!ptype) - { - ptype = nptype; - ftype->param = ptype; - } - else - { - ptype->next = nptype; - ptype = ptype->next; - } -// type->name = "FUNC PARAMETER"; - - - if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")")) - { - newtype = true; - name = QCC_PR_ParseName (); - nptype->aname = qccHunkAlloc(strlen(name)+1); - strcpy(nptype->aname, name); - if (definenames) - strcpy (pr_parm_names[numparms], name); - } - else if (definenames) - strcpy (pr_parm_names[numparms], ""); - numparms++; + if (QCC_PR_CheckKeyword(keyword_optional, "optional")) + { + paramlist[numparms].optional = true; + optional = true; + } + else + { if (optional) - ftype->num_parms = optional-1; + { + QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n"); + paramlist[numparms].optional = true; + } else - ftype->num_parms = numparms; - } while (QCC_PR_CheckToken (",")); + paramlist[numparms].optional = false; + } + + paramlist[numparms].ofs = 0; + paramlist[numparms].arraysize = 0; + paramlist[numparms].type = QCC_PR_ParseType(false, false); + + if (paramlist[numparms].type->type == ev_void) + break; + +// type->name = "FUNC PARAMETER"; + + paramlist[numparms].paramname = ""; + if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")")) + { + newtype = true; + name = QCC_PR_ParseName (); + paramlist[numparms].paramname = qccHunkAlloc(strlen(name)+1); + strcpy(paramlist[numparms].paramname, name); + if (definenames) + strcpy (pr_parm_names[numparms], name); + } + else if (definenames) + strcpy (pr_parm_names[numparms], ""); + numparms++; + } while (QCC_PR_CheckToken (",")); QCC_PR_Expect (")"); } + ftype->num_parms = numparms; + ftype->params = qccHunkAlloc(sizeof(*ftype->params) * numparms); + memcpy(ftype->params, paramlist, sizeof(*ftype->params) * numparms); recursivefunctiontype--; if (newtype) return ftype; @@ -3623,9 +3639,9 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) } QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) { - QCC_type_t *ftype, *ptype, *nptype; - char *name; - char argname[64]; + QCC_type_t *ftype, *ptype; +// char *name; +// char argname[64]; int definenames = !recursivefunctiontype; recursivefunctiontype++; @@ -3639,6 +3655,9 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) if (!QCC_PR_CheckToken (")")) { +#if 1 +#pragma message("I broke reacc support") +#else if (QCC_PR_CheckToken ("...")) ftype->num_parms = -1; // variable args else @@ -3690,7 +3709,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) strcpy (pr_parm_names[ftype->num_parms], name); ftype->num_parms++; } while (QCC_PR_CheckToken (";")); - +#endif QCC_PR_Expect (")"); } recursivefunctiontype--; @@ -3734,6 +3753,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) QCC_type_t *type; char *name; int i; + etype_t structtype; type_inlinefunction = false; //doesn't really matter so long as its not from an inline function type @@ -3768,6 +3788,17 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) return newt; return QCC_PR_FindType (newt); } + if (QCC_PR_CheckToken ("*")) + { + newt = QCC_PR_NewType("POINTER TYPE", ev_pointer, false); + newt->aux_type = QCC_PR_ParseType (false, false); + + newt->size = newt->aux_type->size; + + if (newtype) + return newt; + return QCC_PR_FindType (newt); + } name = QCC_PR_CheckCompConstString(pr_token); @@ -3776,8 +3807,16 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) // int parms; QCC_type_t *fieldtype; char membername[2048]; - char *classname = QCC_PR_ParseName(); + char *classname; int forwarddeclaration; + int numparms = 0; + struct QCC_typeparam_s *parms = NULL; + char *parmname; + int arraysize; + + parmname = QCC_PR_ParseName(); + classname = qccHunkAlloc(strlen(parmname)+1); + strcpy(classname, parmname); newt = 0; @@ -3801,6 +3840,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) if (newt && newt->num_parms != 0) QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname); + if (pr_scope && !forwarddeclaration) + QCC_PR_ParseError(ERR_REDECLARATION, "Declaration of class %s within function", classname); if (!newt) newt = QCC_PR_NewType(classname, ev_entity, true); @@ -3833,56 +3874,200 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) QCC_PR_ParseError(ERR_NOTANAME, "member missing name"); while (!QCC_PR_CheckToken("}")) { -// if (QCC_PR_CheckToken(",")) -// type->next = QCC_PR_NewType(type->name, type->type); -// else - newparm = QCC_PR_ParseType(true, false); + pbool isstatic = false, isvirt = false; + if (QCC_PR_CheckKeyword(1, "static")) + isstatic = true; + if (QCC_PR_CheckKeyword(1, "virtual")) + isvirt = true; + newparm = QCC_PR_ParseType(false, 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); - if (!QCC_PR_CheckToken(";")) + parmname = qccHunkAlloc(strlen(pr_token)+1); + strcpy(parmname, pr_token); + QCC_PR_Lex(); + if (QCC_PR_CheckToken("[")) { - newparm->name = QCC_CopyString(pr_token)+strings; - QCC_PR_Lex(); - if (QCC_PR_CheckToken("[")) - { - type->next->size*=atoi(pr_token); - QCC_PR_Lex(); - QCC_PR_Expect("]"); - } - QCC_PR_CheckToken(";"); + arraysize=QCC_PR_IntConstExpr(); + QCC_PR_Expect("]"); } - else - newparm->name = QCC_CopyString("")+strings; - sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name); - fieldtype = QCC_PR_NewType(newparm->name, ev_field, false); + if (isvirt && newparm->type != ev_function) + { + QCC_Error(ERR_INTERNAL, "virtual keyword on member that is not a function"); + } + + if (QCC_PR_CheckToken("=")) + { + QCC_def_t *def; + QCC_function_t *f; + QCC_dfunction_t *df; + if (pr_scope) + QCC_Error(ERR_INTERNAL, "Nested function declaration"); + + sprintf(membername, "%s::%s", classname, parmname); + def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST); + + if (newparm->type != ev_function) + QCC_Error(ERR_INTERNAL, "Can only initialise member functions"); + else + { + extern int locals_end, locals_start; + extern QCC_type_t *pr_classtype; + QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type); + + pr_scope = def; + pr_classtype = newt; + f = QCC_PR_ParseImmediateStatements (newparm); + pr_classtype = NULL; + pr_scope = NULL; + G_FUNCTION(def->ofs) = numfunctions; + f->def = def; + def->initialized = 1; + + 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_file; + df->numparms = f->def->type->num_parms; + df->locals = locals_end - locals_start; + df->parm_start = locals_start; + for (i=0 ; inumparms ; i++) + { + df->parm_size[i] = newparm->params[i].type->size; + } + } + + if (!isvirt && !isstatic) + { + QCC_type_t *pc; + unsigned int i; + isstatic = true; //assume static if its initialised inside the function. + for (pc = newt->parentclass; pc; pc = pc->parentclass) + { + for (i = 0; i < pc->num_parms; i++) + { + if (!strcmp(pc->params[i].paramname, parmname)) + { + QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s::%s is virtual inside parent class %s. Did you forget the 'virtual' keyword?", newt->name, parmname, pc->name); + break; + } + } + if (i < pc->num_parms) + break; + } + } + } + + QCC_PR_Expect(";"); + + //static members are technically funny-named globals, and do not generate fields. + if (isstatic || (newparm->type == ev_function && !arraysize)) + { + QCC_def_t *def; + sprintf(membername, "%s::%s", classname, parmname); + def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST); + + if (isstatic) + continue; + } + + + parms = realloc(parms, sizeof(*parms) * (numparms+1)); + parms[numparms].ofs = 0; + parms[numparms].optional = false; + parms[numparms].paramname = parmname; + parms[numparms].arraysize = arraysize; + parms[numparms].type = newparm; + numparms++; + + fieldtype = QCC_PR_NewType(parmname, ev_field, false); fieldtype->aux_type = newparm; fieldtype->size = newparm->size; - QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false); - - - newparm->ofs = 0;//newt->size; - newt->num_parms++; - - if (type) - type->next = newparm; - else - newt->param = newparm; - - type = newparm; + { + QCC_type_t *pc; + QCC_def_t *d; + pc = newt; + d = NULL; + while(pc && !d) + { + sprintf(membername, "%s::"MEMBERFIELDNAME, pc->name, parmname); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, 0); + if (d && typecmp(d->type, fieldtype)) + { + char bufc[256]; + char bufp[256]; + TypeName(((d->type->type==ev_field)?d->type->aux_type:d->type), bufp, sizeof(bufp)); + TypeName(newparm, bufc, sizeof(bufc)); + QCC_PR_ParseError(0, "%s defined as %s in %s, but %s in %s\n", parmname, bufc, newt->name, bufp, pc->name); + break; + } + pc = pc->parentclass; + } + if (d) + continue; + } + sprintf(membername, "%s::"MEMBERFIELDNAME, classname, parmname); + QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, 0); } + newt->num_parms = numparms; + newt->params = qccHunkAlloc(sizeof(*type->params) * numparms); + memcpy(newt->params, parms, sizeof(*type->params) * numparms); + free(parms); QCC_PR_Expect(";"); return NULL; } - if (QCC_PR_CheckKeyword (keyword_struct, "struct")) + + structtype = ev_void; + if (QCC_PR_CheckKeyword (keyword_union, "union")) + structtype = ev_union; + else if (QCC_PR_CheckKeyword (keyword_struct, "struct")) + structtype = ev_struct; + if (structtype != ev_void) { - newt = QCC_PR_NewType("struct", ev_struct, false); + struct QCC_typeparam_s *parms = NULL; + int numparms = 0; + int arraysize; + char *parmname; + + if (QCC_PR_CheckToken("{")) + { + //nameless struct + newt = QCC_PR_NewType(structtype==ev_union?"union":"struct", structtype, false); + } + else + { + newt = QCC_TypeForName(pr_token); + if (!newt) + newt = QCC_PR_NewType(QCC_CopyString(pr_token)+strings, ev_struct, true); + QCC_PR_Lex(); + if (newt->size) + { + if (QCC_PR_CheckToken("{")) + QCC_PR_ParseError(ERR_NOTANAME, "%s %s is already defined", structtype==ev_union?"union":"struct", newt->name); + return newt; + } + + //struct declaration only, not definition. + if (!QCC_PR_CheckToken("{")) + return newt; + } newt->size=0; - QCC_PR_Expect("{"); type = NULL; if (QCC_PR_CheckToken(",")) @@ -3900,81 +4085,53 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) else newparm = QCC_PR_ParseType(true, false); + arraysize = 1; + if (!QCC_PR_CheckToken(";")) { - newparm->name = QCC_CopyString(pr_token)+strings; + parmname = qccHunkAlloc(strlen(pr_token)+1); + strcpy(parmname, pr_token); QCC_PR_Lex(); if (QCC_PR_CheckToken("[")) { - newparm->arraysize=QCC_PR_IntConstExpr(); + arraysize=QCC_PR_IntConstExpr(); QCC_PR_Expect("]"); } QCC_PR_CheckToken(";"); } else - newparm->name = QCC_CopyString("")+strings; - newparm->ofs = newt->size; - newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1); - newt->num_parms++; + parmname = ""; - if (type) - type->next = newparm; - else - newt->param = newparm; - type = newparm; - } - return newt; - } - if (QCC_PR_CheckKeyword (keyword_union, "union")) - { - newt = QCC_PR_NewType("union", ev_union, false); - newt->size=0; - QCC_PR_Expect("{"); - type = NULL; - if (QCC_PR_CheckToken(",")) - QCC_PR_ParseError(ERR_NOTANAME, "element missing name"); - newparm = NULL; - while (!QCC_PR_CheckToken("}")) - { - int arraysize; - if (QCC_PR_CheckToken(",")) + parms = realloc(parms, sizeof(*parms) * (numparms+1)); + if (structtype == ev_union) { - if (!newparm) - QCC_PR_ParseError(ERR_NOTANAME, "element missing type"); - newparm = QCC_PR_NewType(newparm->name, newparm->type, false); + parms[numparms].ofs = 0; + if (newparm->size*arraysize > newt->size) + newt->size = newparm->size*arraysize; } - else - 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(";"); + parms[numparms].ofs = newt->size; + newt->size += newparm->size*arraysize; } - newparm->ofs = 0; - arraysize = newparm->arraysize; - if (!arraysize) - arraysize = 1; - if (newparm->size*arraysize > newt->size) - newt->size = newparm->size*arraysize; - newt->num_parms++; - - if (type) - type->next = newparm; - else - newt->param = newparm; - type = newparm; + parms[numparms].arraysize = arraysize; + parms[numparms].optional = false; + parms[numparms].paramname = parmname; + parms[numparms].type = newparm; + numparms++; } + if (!numparms) + QCC_PR_ParseError(ERR_NOTANAME, "%s %s has no members", structtype==ev_union?"union":"struct", newt->name); + + newt->num_parms = numparms; + newt->params = qccHunkAlloc(sizeof(*type->params) * numparms); + memcpy(newt->params, parms, sizeof(*type->params) * numparms); + free(parms); + return newt; } + type = NULL; for (i = 0; i < numtypeinfos; i++) { @@ -3991,6 +4148,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) { if (!*name) return NULL; + + //some reacc types... if (!stricmp("Void", name)) type = type_void; else if (!stricmp("Real", name)) @@ -4026,7 +4185,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) { if (newtype) { - type = QCC_PR_DuplicateType(type); + type = QCC_PR_DuplicateType(type, false); } } return type; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 1a26757b1..f8c4c8a46 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -95,6 +95,7 @@ hashtable_t globalstable; hashtable_t localstable; #ifdef WRITEASM FILE *asmfile; +pbool asmfilebegun; #endif hashtable_t floatconstdefstable; hashtable_t stringconstdefstable; @@ -835,6 +836,7 @@ pbool QCC_WriteData (int crc) if (def->references<=0) { int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED; + pr_scope = def->scope; if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references", def->name)) { if (!warnedunref) @@ -843,6 +845,7 @@ pbool QCC_WriteData (int crc) warnedunref = true; } } + pr_scope = NULL; if (opt_unreferenced && def->type->type != ev_field) { @@ -860,7 +863,7 @@ pbool QCC_WriteData (int crc) } if (!def->timescalled) { - if (def->references<=1) + if (def->references<=1 && strncmp(def->name, "spawnfunc_", 10)) QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called or referenced (spawn function or dead code)", def->name); // else // QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name); @@ -1714,9 +1717,8 @@ QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed) qcc_typeinfo[numtypeinfos].type = basictype; qcc_typeinfo[numtypeinfos].name = name; qcc_typeinfo[numtypeinfos].num_parms = 0; - qcc_typeinfo[numtypeinfos].param = NULL; + qcc_typeinfo[numtypeinfos].params = NULL; qcc_typeinfo[numtypeinfos].size = type_size[basictype]; - qcc_typeinfo[numtypeinfos].arraysize = 0; qcc_typeinfo[numtypeinfos].typedefed = typedefed; @@ -2754,6 +2756,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void) qccwarningaction[WARN_EXTRAPRECACHE] = WA_IGNORE; qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE; qccwarningaction[WARN_NOTUTF8] = WA_IGNORE; + qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE; } else { @@ -2899,6 +2902,7 @@ void QCC_SetDefaultProperties (void) qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE; qccwarningaction[WARN_NOTUTF8] = WA_IGNORE; qccwarningaction[WARN_UNINITIALIZED] = WA_IGNORE; //not sure about this being ignored by default. + qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE; if (QCC_CheckParm("-h2")) qccwarningaction[WARN_CASEINSENSATIVEFRAMEMACRO] = WA_IGNORE; @@ -3278,6 +3282,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string)); if (!asmfile) QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output."); } + asmfilebegun = !!asmfile; #endif newstylesource = false;