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

@ -54,7 +54,7 @@ void PostCompile(void)
{
fclose(asmfile);
asmfile = NULL;
}
}
}
pbool PreCompile(void)
{

View file

@ -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));

View file

@ -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
};

View file

@ -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

View file

@ -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.

File diff suppressed because it is too large Load diff

View file

@ -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:"<NO FUNCTION>");
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 ; 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->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;

View file

@ -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;