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
This commit is contained in:
Spoike 2013-06-02 06:03:54 +00:00
parent cb8e23709a
commit fc82e561be
8 changed files with 1107 additions and 726 deletions

View file

@ -489,7 +489,7 @@ reeval:
//get a pointer to a field var //get a pointer to a field var
case OP_ADDRESS: case OP_ADDRESS:
if ((unsigned)OPA->edict >= (unsigned)maxedicts) if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
{ {
pr_xstatement = st-pr_statements; 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))) 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_ENT:
case OP_LOAD_S: case OP_LOAD_S:
case OP_LOAD_FNC: case OP_LOAD_FNC:
if ((unsigned)OPA->edict >= (unsigned)maxedicts) if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
{ {
pr_xstatement = st-pr_statements; 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); ed = PROG_TO_EDICT(progfuncs, OPA->edict);
#ifdef PARANOID #ifdef PARANOID
@ -552,7 +558,7 @@ reeval:
break; break;
case OP_LOAD_V: case OP_LOAD_V:
if ((unsigned)OPA->edict >= (unsigned)maxedicts) if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
{ {
pr_xstatement = st-pr_statements; 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)); PR_RunError (&progfuncs->funcs, "OP_LOAD_V references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));

View file

@ -355,6 +355,13 @@ enum qcop_e {
OP_BINARYNOT_F, OP_BINARYNOT_F,
OP_BINARYNOT_I, OP_BINARYNOT_I,
OP_EQ_P,
OP_NE_P,
OP_LE_P,
OP_GE_P,
OP_LT_P,
OP_GT_P,
OP_NUMOPS OP_NUMOPS
}; };

View file

@ -10,7 +10,7 @@ typedef vec_t vec3_t[3];
#ifndef t_bool #ifndef t_bool
#define t_bool #define t_bool
typedef int pbool; typedef unsigned int pbool;
#else #else
#define t_bool #define t_bool

View file

@ -284,6 +284,7 @@ extern hashtable_t globalstable, localstable;
#ifdef WRITEASM #ifdef WRITEASM
extern FILE *asmfile; extern FILE *asmfile;
extern pbool asmfilebegun;
#endif #endif
//============================================================================= //=============================================================================
@ -293,22 +294,30 @@ typedef struct QCC_function_s QCC_function_t;
#define MAX_PARMS 8 #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 typedef struct QCC_type_s
{ {
etype_t type; etype_t type;
struct QCC_type_s *parentclass; //type_entity... struct QCC_type_s *parentclass; //type_entity...
struct QCC_type_s *next; // struct QCC_type_s *next;
// function types are more complex // function types are more complex
struct QCC_type_s *aux_type; // return type or field type 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
unsigned int ofs; //inside a structure. struct QCC_typeparam_s *params; //[num_parms]
unsigned int num_parms;
unsigned int size; unsigned int size;
unsigned int arraysize; pbool typedefed:1;
pbool typedefed; pbool vargs:1;
char *name; char *name;
char *aname; char *aname;
} QCC_type_t; } QCC_type_t;
@ -638,6 +647,7 @@ enum {
WARN_MISSINGOPTIONAL, WARN_MISSINGOPTIONAL,
WARN_SYSTEMCRC, WARN_SYSTEMCRC,
WARN_CONDITIONALTYPEMISMATCH, 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. ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.

File diff suppressed because it is too large Load diff

View file

@ -911,7 +911,14 @@ pbool QCC_PR_Precompiler(void)
asmfile = NULL; asmfile = NULL;
} }
if (!asmfile && on) if (!asmfile && on)
{
if (asmfilebegun)
asmfile = fopen("qc.asm", "ab");
else
asmfile = fopen("qc.asm", "wb"); asmfile = fopen("qc.asm", "wb");
if (asmfile)
asmfilebegun = true;
}
} }
else if (!strncmp(qcc_token, "sourcefile", 10)) else if (!strncmp(qcc_token, "sourcefile", 10))
{ {
@ -2632,7 +2639,7 @@ int QCC_PR_CheckCompConst(void)
if (!strncmp(pr_file_p, "__FUNC__", 8)) if (!strncmp(pr_file_p, "__FUNC__", 8))
{ {
static char retbuf[256]; static char retbuf[256];
sprintf(retbuf, "\"%s\"",pr_scope->name); sprintf(retbuf, "\"%s\"",pr_scope?pr_scope->name:"<NO FUNCTION>");
pr_file_p = retbuf; pr_file_p = retbuf;
QCC_PR_Lex(); //translate the macro's value QCC_PR_Lex(); //translate the macro's value
pr_file_p = oldpr_file_p+8; pr_file_p = oldpr_file_p+8;
@ -3240,6 +3247,7 @@ a new one and copies it out.
//0 if same //0 if same
int typecmp(QCC_type_t *a, QCC_type_t *b) int typecmp(QCC_type_t *a, QCC_type_t *b)
{ {
int i;
if (a == b) if (a == b)
return 0; return 0;
if (!a || !b) if (!a || !b)
@ -3248,31 +3256,29 @@ int typecmp(QCC_type_t *a, QCC_type_t *b)
if (a->type != b->type) if (a->type != b->type)
return 1; return 1;
if (a->num_parms != b->num_parms) if (a->num_parms != b->num_parms)
{
return 1; return 1;
} if (a->vargs != b->vargs)
return 1;
if (a->size != b->size) if (a->size != b->size)
return 1; 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)) if (typecmp(a->aux_type, b->aux_type))
return 1; return 1;
if (a->param || b->param) i = a->num_parms;
while(i-- > 0)
{ {
a = a->param; if (a->type != ev_function && STRCMP(a->params[i].paramname, b->params[i].paramname))
b = b->param; return 1;
if (typecmp(a->params[i].type, b->params[i].type))
while(a || b)
{
if (typecmp(a, b))
return 1; return 1;
a=a->next;
b=b->next;
}
} }
return 0; 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 //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 typecmp_lax(QCC_type_t *a, QCC_type_t *b)
{ {
int numargs = 0; unsigned int minargs = 0;
int t; unsigned int t;
if (a == b) if (a == b)
return 0; return 0;
if (!a || !b) if (!a || !b)
@ -3297,14 +3303,10 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b)
return 1; return 1;
t = a->num_parms; t = a->num_parms;
if (t < 0) minargs = t;
t = (t * -1) - 1;
numargs = t;
t = b->num_parms; t = b->num_parms;
if (t < 0) if (minargs > t)
t = (t * -1) - 1; minargs = t;
if (numargs > t)
numargs = t;
// if (STRCMP(a->name, b->name)) //This isn't 100% clean. // if (STRCMP(a->name, b->name)) //This isn't 100% clean.
// return 1; // 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)) if (typecmp_lax(a->aux_type, b->aux_type))
return 1; 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; if (a->params[t].type->type != b->params[t].type->type)
b = b->param; return 1;
//classes/structs/unions are matched on class names rather than the contents of the class
while(numargs-->0 || (a&&b)) //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; 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) if (!in)
return NULL; return NULL;
out = QCC_PR_NewType(in->name, in->type, false); out = QCC_PR_NewType(in->name, in->type, false);
out->aux_type = QCC_PR_DuplicateType(in->aux_type); out->aux_type = recurse?QCC_PR_DuplicateType(in->aux_type, recurse):in->aux_type;
out->param = QCC_PR_DuplicateType(in->param); out->num_parms = in->num_parms;
ip = in->param; out->params = qccHunkAlloc(sizeof(*out->params) * out->num_parms);
op = NULL; memcpy(out->params, in->params, sizeof(*out->params) * out->num_parms);
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->size = in->size; out->size = in->size;
out->num_parms = in->num_parms; out->num_parms = in->num_parms;
out->ofs = in->ofs;
out->name = in->name; out->name = in->name;
out->parentclass = in->parentclass; out->parentclass = in->parentclass;
return out; 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 *TypeName(QCC_type_t *type, char *buffer, int buffersize)
{ {
char *ret; char *ret;
if (type->type == ev_pointer) if (type->type == ev_pointer)
{ {
if (buffersize < 0)
return buffer;
TypeName(type->aux_type, buffer, buffersize-2); TypeName(type->aux_type, buffer, buffersize-2);
strcat(buffer, " *"); Q_strlcat(buffer, " *", buffersize);
return buffer; return buffer;
} }
@ -3381,42 +3406,37 @@ char *TypeName(QCC_type_t *type, char *buffer, int buffersize)
if (type->type == ev_function) if (type->type == ev_function)
{ {
pbool varg = type->num_parms < 0;
int args = type->num_parms; int args = type->num_parms;
if (args < 0) pbool vargs = type->vargs;
args = -(args+1); unsigned int i;
strcat(ret, type->aux_type->name); Q_strlcat(buffer, type->aux_type->name, buffersize);
strcat(ret, " ("); Q_strlcat(buffer, "(", buffersize);
type = type->param; for (i = 0; i < type->num_parms; )
while(type)
{ {
if (args<=0) if (type->params[i].optional)
strcat(ret, "optional "); Q_strlcat(buffer, "optional ", buffersize);
args--; args--;
strcat(ret, type->name); Q_strlcat(buffer, type->params[i].type->name, buffersize);
if (type->aname) if (type->params[i].paramname)
{ {
strcat(ret, " "); Q_strlcat(buffer, " ", buffersize);
strcat(ret, type->aname); Q_strlcat(buffer, type->params[i].paramname, buffersize);
} }
type = type->next;
if (type || varg) if (++i < type->num_parms || vargs)
strcat(ret, ", "); Q_strlcat(buffer, ", ", buffersize);
} }
if (varg) if (vargs)
{ Q_strlcat(buffer, "...", buffersize);
strcat(ret, "..."); Q_strlcat(buffer, ")", buffersize);
}
strcat(ret, ")");
} }
else if (type->type == ev_entity && type->parentclass) else if (type->type == ev_entity && type->parentclass)
{ {
ret = buffer; ret = buffer;
*ret = 0; *ret = 0;
strcat(ret, "class "); Q_strlcat(buffer, "class ", buffersize);
strcat(ret, type->name); Q_strlcat(buffer, type->name, buffersize);
/* strcat(ret, " {"); /* strcat(ret, " {");
type = type->param; type = type->param;
while(type) while(type)
@ -3431,7 +3451,7 @@ char *TypeName(QCC_type_t *type, char *buffer, int buffersize)
*/ */
} }
else else
strcpy(ret, type->name); Q_strlcat(buffer, type->name, buffersize);
return buffer; return buffer;
} }
@ -3493,7 +3513,7 @@ QCC_type_t *QCC_TypeForName(char *name)
for (i = 0; i < numtypeinfos; i++) 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]; return &qcc_typeinfo[i];
} }
@ -3538,11 +3558,12 @@ pbool recursivefunctiontype;
//expects a ( to have already been parsed. //expects a ( to have already been parsed.
QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) 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; char *name;
int definenames = !recursivefunctiontype; int definenames = !recursivefunctiontype;
int optional = 0; int optional = 0;
int numparms = 0; int numparms = 0;
struct QCC_typeparam_s paramlist[MAX_PARMS+MAX_EXTRA_PARMS];
recursivefunctiontype++; recursivefunctiontype++;
@ -3555,9 +3576,6 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
if (!QCC_PR_CheckToken (")")) 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) if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS)
@ -3565,57 +3583,55 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
if (QCC_PR_CheckToken ("...")) if (QCC_PR_CheckToken ("..."))
{ {
if (optional) ftype->vargs = true;
numparms = optional-1;
ftype->num_parms = (numparms * -1) - 1;
break; break;
} }
if (QCC_PR_CheckKeyword(keyword_optional, "optional")) if (QCC_PR_CheckKeyword(keyword_optional, "optional"))
{ {
if (!optional) paramlist[numparms].optional = true;
optional = numparms+1; optional = true;
}
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 else
{ {
ptype->next = nptype; if (optional)
ptype = ptype->next; {
QCC_PR_ParseWarning(WARN_MISSINGOPTIONAL, "optional not specified on all optional args\n");
paramlist[numparms].optional = true;
} }
else
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"; // type->name = "FUNC PARAMETER";
paramlist[numparms].paramname = "";
if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")")) if (STRCMP(pr_token, ",") && STRCMP(pr_token, ")"))
{ {
newtype = true; newtype = true;
name = QCC_PR_ParseName (); name = QCC_PR_ParseName ();
nptype->aname = qccHunkAlloc(strlen(name)+1); paramlist[numparms].paramname = qccHunkAlloc(strlen(name)+1);
strcpy(nptype->aname, name); strcpy(paramlist[numparms].paramname, name);
if (definenames) if (definenames)
strcpy (pr_parm_names[numparms], name); strcpy (pr_parm_names[numparms], name);
} }
else if (definenames) else if (definenames)
strcpy (pr_parm_names[numparms], ""); strcpy (pr_parm_names[numparms], "");
numparms++; numparms++;
if (optional)
ftype->num_parms = optional-1;
else
ftype->num_parms = numparms;
} while (QCC_PR_CheckToken (",")); } while (QCC_PR_CheckToken (","));
QCC_PR_Expect (")"); QCC_PR_Expect (")");
} }
ftype->num_parms = numparms;
ftype->params = qccHunkAlloc(sizeof(*ftype->params) * numparms);
memcpy(ftype->params, paramlist, sizeof(*ftype->params) * numparms);
recursivefunctiontype--; recursivefunctiontype--;
if (newtype) if (newtype)
return ftype; 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 *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
{ {
QCC_type_t *ftype, *ptype, *nptype; QCC_type_t *ftype, *ptype;
char *name; // char *name;
char argname[64]; // char argname[64];
int definenames = !recursivefunctiontype; int definenames = !recursivefunctiontype;
recursivefunctiontype++; recursivefunctiontype++;
@ -3639,6 +3655,9 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
if (!QCC_PR_CheckToken (")")) if (!QCC_PR_CheckToken (")"))
{ {
#if 1
#pragma message("I broke reacc support")
#else
if (QCC_PR_CheckToken ("...")) if (QCC_PR_CheckToken ("..."))
ftype->num_parms = -1; // variable args ftype->num_parms = -1; // variable args
else 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); strcpy (pr_parm_names[ftype->num_parms], name);
ftype->num_parms++; ftype->num_parms++;
} while (QCC_PR_CheckToken (";")); } while (QCC_PR_CheckToken (";"));
#endif
QCC_PR_Expect (")"); QCC_PR_Expect (")");
} }
recursivefunctiontype--; recursivefunctiontype--;
@ -3734,6 +3753,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_type_t *type; QCC_type_t *type;
char *name; char *name;
int i; int i;
etype_t structtype;
type_inlinefunction = false; //doesn't really matter so long as its not from an inline function type 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 newt;
return QCC_PR_FindType (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); name = QCC_PR_CheckCompConstString(pr_token);
@ -3776,8 +3807,16 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
// int parms; // int parms;
QCC_type_t *fieldtype; QCC_type_t *fieldtype;
char membername[2048]; char membername[2048];
char *classname = QCC_PR_ParseName(); char *classname;
int forwarddeclaration; 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; newt = 0;
@ -3801,6 +3840,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (newt && newt->num_parms != 0) if (newt && newt->num_parms != 0)
QCC_PR_ParseError(ERR_REDECLARATION, "Redeclaration of class %s", classname); 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) if (!newt)
newt = QCC_PR_NewType(classname, ev_entity, true); 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"); QCC_PR_ParseError(ERR_NOTANAME, "member missing name");
while (!QCC_PR_CheckToken("}")) while (!QCC_PR_CheckToken("}"))
{ {
// if (QCC_PR_CheckToken(",")) pbool isstatic = false, isvirt = false;
// type->next = QCC_PR_NewType(type->name, type->type); if (QCC_PR_CheckKeyword(1, "static"))
// else isstatic = true;
newparm = QCC_PR_ParseType(true, false); 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. 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); 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);
newparm->name = QCC_CopyString(pr_token)+strings;
QCC_PR_Lex(); QCC_PR_Lex();
if (QCC_PR_CheckToken("[")) if (QCC_PR_CheckToken("["))
{ {
type->next->size*=atoi(pr_token); arraysize=QCC_PR_IntConstExpr();
QCC_PR_Lex();
QCC_PR_Expect("]"); QCC_PR_Expect("]");
} }
QCC_PR_CheckToken(";");
}
else
newparm->name = QCC_CopyString("")+strings;
sprintf(membername, "%s::"MEMBERFIELDNAME, classname, newparm->name); if (isvirt && newparm->type != ev_function)
fieldtype = QCC_PR_NewType(newparm->name, ev_field, false); {
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 ; i<df->numparms ; 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->aux_type = newparm;
fieldtype->size = newparm->size; fieldtype->size = newparm->size;
QCC_PR_GetDef(fieldtype, membername, pr_scope, 2, 0, false); {
QCC_type_t *pc;
QCC_def_t *d;
newparm->ofs = 0;//newt->size; pc = newt;
newt->num_parms++; d = NULL;
while(pc && !d)
if (type) {
type->next = newparm; sprintf(membername, "%s::"MEMBERFIELDNAME, pc->name, parmname);
else d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, 0);
newt->param = newparm; if (d && typecmp(d->type, fieldtype))
{
type = newparm; 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(";"); QCC_PR_Expect(";");
return NULL; 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; newt->size=0;
QCC_PR_Expect("{");
type = NULL; type = NULL;
if (QCC_PR_CheckToken(",")) if (QCC_PR_CheckToken(","))
@ -3900,81 +4085,53 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
else else
newparm = QCC_PR_ParseType(true, false); newparm = QCC_PR_ParseType(true, false);
arraysize = 1;
if (!QCC_PR_CheckToken(";")) if (!QCC_PR_CheckToken(";"))
{ {
newparm->name = QCC_CopyString(pr_token)+strings; parmname = qccHunkAlloc(strlen(pr_token)+1);
strcpy(parmname, pr_token);
QCC_PR_Lex(); QCC_PR_Lex();
if (QCC_PR_CheckToken("[")) if (QCC_PR_CheckToken("["))
{ {
newparm->arraysize=QCC_PR_IntConstExpr(); arraysize=QCC_PR_IntConstExpr();
QCC_PR_Expect("]"); QCC_PR_Expect("]");
} }
QCC_PR_CheckToken(";"); QCC_PR_CheckToken(";");
} }
else else
newparm->name = QCC_CopyString("")+strings; parmname = "";
newparm->ofs = newt->size;
newt->size += newparm->size*(newparm->arraysize?newparm->arraysize:1);
newt->num_parms++;
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; parms = realloc(parms, sizeof(*parms) * (numparms+1));
if (QCC_PR_CheckToken(",")) if (structtype == ev_union)
QCC_PR_ParseError(ERR_NOTANAME, "element missing name");
newparm = NULL;
while (!QCC_PR_CheckToken("}"))
{ {
int arraysize; parms[numparms].ofs = 0;
if (QCC_PR_CheckToken(","))
{
if (!newparm)
QCC_PR_ParseError(ERR_NOTANAME, "element missing type");
newparm = QCC_PR_NewType(newparm->name, newparm->type, false);
}
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(";");
}
newparm->ofs = 0;
arraysize = newparm->arraysize;
if (!arraysize)
arraysize = 1;
if (newparm->size*arraysize > newt->size) if (newparm->size*arraysize > newt->size)
newt->size = newparm->size*arraysize; newt->size = newparm->size*arraysize;
newt->num_parms++;
if (type)
type->next = newparm;
else
newt->param = newparm;
type = newparm;
} }
else
{
parms[numparms].ofs = newt->size;
newt->size += newparm->size*arraysize;
}
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; return newt;
} }
type = NULL; type = NULL;
for (i = 0; i < numtypeinfos; i++) for (i = 0; i < numtypeinfos; i++)
{ {
@ -3991,6 +4148,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{ {
if (!*name) if (!*name)
return NULL; return NULL;
//some reacc types...
if (!stricmp("Void", name)) if (!stricmp("Void", name))
type = type_void; type = type_void;
else if (!stricmp("Real", name)) else if (!stricmp("Real", name))
@ -4026,7 +4185,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{ {
if (newtype) if (newtype)
{ {
type = QCC_PR_DuplicateType(type); type = QCC_PR_DuplicateType(type, false);
} }
} }
return type; return type;

View file

@ -95,6 +95,7 @@ hashtable_t globalstable;
hashtable_t localstable; hashtable_t localstable;
#ifdef WRITEASM #ifdef WRITEASM
FILE *asmfile; FILE *asmfile;
pbool asmfilebegun;
#endif #endif
hashtable_t floatconstdefstable; hashtable_t floatconstdefstable;
hashtable_t stringconstdefstable; hashtable_t stringconstdefstable;
@ -835,6 +836,7 @@ pbool QCC_WriteData (int crc)
if (def->references<=0) if (def->references<=0)
{ {
int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED; 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 (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s no references", def->name))
{ {
if (!warnedunref) if (!warnedunref)
@ -843,6 +845,7 @@ pbool QCC_WriteData (int crc)
warnedunref = true; warnedunref = true;
} }
} }
pr_scope = NULL;
if (opt_unreferenced && def->type->type != ev_field) if (opt_unreferenced && def->type->type != ev_field)
{ {
@ -860,7 +863,7 @@ pbool QCC_WriteData (int crc)
} }
if (!def->timescalled) 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); 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 // else
// QCC_PR_Warning(WARN_DEADCODE, strings + def->s_file, def->s_line, "%s is never directly called", def->name); // 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].type = basictype;
qcc_typeinfo[numtypeinfos].name = name; qcc_typeinfo[numtypeinfos].name = name;
qcc_typeinfo[numtypeinfos].num_parms = 0; 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].size = type_size[basictype];
qcc_typeinfo[numtypeinfos].arraysize = 0;
qcc_typeinfo[numtypeinfos].typedefed = typedefed; qcc_typeinfo[numtypeinfos].typedefed = typedefed;
@ -2754,6 +2756,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
qccwarningaction[WARN_EXTRAPRECACHE] = WA_IGNORE; qccwarningaction[WARN_EXTRAPRECACHE] = WA_IGNORE;
qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE; qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE;
qccwarningaction[WARN_NOTUTF8] = WA_IGNORE; qccwarningaction[WARN_NOTUTF8] = WA_IGNORE;
qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE;
} }
else else
{ {
@ -2899,6 +2902,7 @@ void QCC_SetDefaultProperties (void)
qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE; qccwarningaction[WARN_CORRECTEDRETURNTYPE] = WA_IGNORE;
qccwarningaction[WARN_NOTUTF8] = WA_IGNORE; qccwarningaction[WARN_NOTUTF8] = WA_IGNORE;
qccwarningaction[WARN_UNINITIALIZED] = WA_IGNORE; //not sure about this being ignored by default. qccwarningaction[WARN_UNINITIALIZED] = WA_IGNORE; //not sure about this being ignored by default.
qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE;
if (QCC_CheckParm("-h2")) if (QCC_CheckParm("-h2"))
qccwarningaction[WARN_CASEINSENSATIVEFRAMEMACRO] = WA_IGNORE; qccwarningaction[WARN_CASEINSENSATIVEFRAMEMACRO] = WA_IGNORE;
@ -3278,6 +3282,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
if (!asmfile) if (!asmfile)
QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output."); QCC_Error (ERR_INTERNAL, "Couldn't open file for asm output.");
} }
asmfilebegun = !!asmfile;
#endif #endif
newstylesource = false; newstylesource = false;