Second attempt at accessors. syntax is a little more usable. also supports arbitrary custom fields too, without requiring it to use lots of string compares.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4747 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-09-08 23:35:32 +00:00
parent abde2fa81b
commit 0fb5e2bc25
3 changed files with 260 additions and 132 deletions

View File

@ -302,6 +302,15 @@ struct QCC_typeparam_s
unsigned int arraysize;
char *paramname;
};
struct accessor_s
{
struct accessor_s *next;
struct QCC_type_s *type;
struct QCC_type_s *indexertype; //null if not indexer
struct QCC_def_s *get;
struct QCC_def_s *set;
char *fieldname;
};
typedef struct QCC_type_s
{
@ -321,11 +330,7 @@ typedef struct QCC_type_s
char *name;
char *aname;
struct QCC_def_s *getptr;
struct QCC_def_s *getarr;
struct QCC_def_s *setptr;
struct QCC_def_s *setarr;
struct QCC_def_s *getlength;
struct accessor_s *accessors;
} QCC_type_t;
int typecmp(QCC_type_t *a, QCC_type_t *b);
int typecmp_lax(QCC_type_t *a, QCC_type_t *b);
@ -390,6 +395,7 @@ typedef struct
QCC_def_t *base;
QCC_def_t *index;
QCC_type_t *cast; //entity.float is float, not pointer.
struct accessor_s *accessor; //the accessor field of base that we're trying to use
int postinc; //+1 or -1
pbool readonly; //for whatever reason, like base being a const
} QCC_ref_t;

View File

@ -156,6 +156,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbool allowarrayassign, pbool expandmemberfields, pbool makearraypointers);
QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *refbuf, QCC_ref_t *d, pbool allowarrayassign, pbool makestructpointers);
QCC_ref_t *QCC_PR_BuildRef(QCC_ref_t *retbuf, unsigned int reftype, QCC_def_t *base, QCC_def_t *index, QCC_type_t *cast, pbool readonly);
QCC_ref_t *QCC_PR_BuildAccessorRef(QCC_ref_t *retbuf, QCC_def_t *base, QCC_def_t *index, struct accessor_s *accessor, pbool readonly);
QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pbool preservedest);
void QCC_PR_DiscardRef(QCC_ref_t *ref);
@ -3102,19 +3103,19 @@ QCC_def_t *QCC_PR_StatementFlags (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t
case OP_ADD_FI:
numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
case OP_BITAND_FI:
numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
case OP_BITOR_FI:
numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
case OP_LT_FI:
numstatements--;
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, NULL, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_LT_F], var_a, var_c, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_LT_F], var_a, var_b, NULL, flags&STFL_PRESERVEA);
//statements where the lhs is a const int and can be swapped with a float
case OP_ADD_IF:
numstatements--;
@ -5264,26 +5265,35 @@ static QCC_ref_t *QCC_PR_ParseField(QCC_ref_t *refbuf, QCC_ref_t *lhs)
lhs = QCC_PR_ParseField(refbuf, lhs);
}
else if (t->type == ev_accessor && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
else if (t->accessors && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
{
QCC_def_t *index = NULL;
char *fieldname = QCC_PR_ParseName();
if (!t->aux_type)
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name);
else if (!strcmp(fieldname, "length"))
{
QCC_def_t *obj = QCC_RefToDef(lhs, true);
obj = QCC_PR_GenerateFunctionCall(NULL, t->getlength, &obj, &t->parentclass, 1);
lhs = QCC_PR_BuildRef(refbuf, REF_GLOBAL, obj, NULL, obj->type, true);
lhs = QCC_PR_ParseField(refbuf, lhs);
}
else
{
//these are not defs, but weird crap.
QCC_def_t *index = QCC_MakeStringConst(fieldname);
pbool noset = !t->setarr && !t->setptr;
lhs = QCC_PR_BuildRef(refbuf, REF_ACCESSOR, QCC_RefToDef(lhs, true), index, t->aux_type, lhs->readonly || noset);
lhs = QCC_PR_ParseField(refbuf, lhs);
}
struct accessor_s *acc;
for (acc = t->accessors; acc; acc = acc->next)
if (!strcmp(acc->fieldname, fieldname))
{
if (acc->indexertype)
{
QCC_PR_Expect("[");
index = QCC_PR_Expression (TOP_PRIORITY, 0);
QCC_PR_Expect("]");
}
break;
}
if (!acc)
for (acc = t->accessors; acc; acc = acc->next)
if (!*acc->fieldname && acc->indexertype)
{
index = QCC_MakeStringConst(fieldname);
break;
}
if (!acc)
QCC_PR_ParseError(ERR_INTERNAL, "%s is not a member of %s", fieldname, t->name);
lhs = QCC_PR_BuildAccessorRef(refbuf, QCC_RefToDef(lhs, true), index, acc, lhs->readonly);
lhs = QCC_PR_ParseField(refbuf, lhs);
}
return lhs;
}
@ -5325,7 +5335,7 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
(t->type == ev_string) || //strings are effectively pointers
(t->type == ev_vector) || //vectors are mini arrays
(t->type == ev_field && t->aux_type->type == ev_vector) || //as are field vectors
(t->type == ev_accessor); //custom accessors
(!arraysize&&t->accessors); //custom accessors
}
if (allowarray && QCC_PR_CheckToken("["))
@ -5333,12 +5343,17 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
tmp = QCC_PR_Expression (TOP_PRIORITY, 0);
QCC_PR_Expect("]");
if (!arraysize && t->type == ev_accessor)
if (!arraysize && t->accessors)
{
if (!t->aux_type)
QCC_PR_ParseError(ERR_INTERNAL, "Accessor %s was not defined yet", t->name);
r = QCC_PR_BuildRef(retbuf, REF_ACCESSOR, QCC_RefToDef(r, true), tmp, t->aux_type, r->readonly || (!t->setarr && !t->setptr));
return QCC_PR_ParseRefArrayPointer(retbuf, r, allowarrayassign, makearraypointers);
struct accessor_s *acc;
for (acc = t->accessors; acc; acc = acc->next)
if (!*acc->fieldname)
break;
if(acc)
{
r = QCC_PR_BuildAccessorRef(retbuf, QCC_RefToDef(r, true), tmp, acc, r->readonly);
return QCC_PR_ParseRefArrayPointer(retbuf, r, allowarrayassign, makearraypointers);
}
}
/*if its a pointer that got dereferenced, follow the type*/
@ -5930,10 +5945,14 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
if (e->type->type == ev_pointer)
return QCC_PR_BuildRef(retbuf, REF_POINTER, e, NULL, e->type->aux_type, false);
else if (e->type->type == ev_accessor)
return QCC_PR_BuildRef(retbuf, REF_ACCESSOR, e, NULL, e->type->aux_type, !e->type->setptr);
else
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type.");
else if (e->type->accessors)
{
struct accessor_s *acc;
for (acc = e->type->accessors; acc; acc = acc->next)
if (!strcmp(acc->fieldname, ""))
return QCC_PR_BuildAccessorRef(retbuf, e, NULL, acc, e->constant);
}
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCH, e, "Unable to dereference non-pointer type.");
}
if (QCC_PR_CheckToken ("-"))
{
@ -6095,6 +6114,17 @@ QCC_PR_RefExpression
==============
*/
QCC_ref_t *QCC_PR_BuildAccessorRef(QCC_ref_t *retbuf, QCC_def_t *base, QCC_def_t *index, struct accessor_s *accessor, pbool readonly)
{
retbuf->postinc = 0;
retbuf->type = REF_ACCESSOR;
retbuf->base = base;
retbuf->index = index;
retbuf->accessor = accessor;
retbuf->cast = accessor->type;
retbuf->readonly = readonly;
return retbuf;
}
QCC_ref_t *QCC_PR_BuildRef(QCC_ref_t *retbuf, unsigned int reftype, QCC_def_t *base, QCC_def_t *index, QCC_type_t *cast, pbool readonly)
{
retbuf->postinc = 0;
@ -6624,18 +6654,17 @@ QCC_def_t *QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
case REF_STRING:
return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, ref->index, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB));
case REF_ACCESSOR:
if (!ref->index && ref->base->type->getptr)
if (ref->accessor && ref->accessor->get)
{
QCC_def_t *arg[] = {ref->base};
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getptr, arg, NULL, 1);
}
else if (ref->base->type->getarr)
{
QCC_def_t *arg[] = {ref->base, ref->index?QCC_SupplyConversion(ref->index, ref->base->type->aux_type->type, true):QCC_MakeIntConst(0)};
return QCC_PR_GenerateFunctionCall(NULL, ref->base->type->getarr, arg, NULL, 2);
int args = 0;
QCC_def_t *arg[2] = {NULL, NULL};
arg[args++] = ref->base;
if (ref->accessor->indexertype)
arg[args++] = ref->index?QCC_SupplyConversion(ref->index, ref->accessor->indexertype->type, true):QCC_MakeIntConst(0);
return QCC_PR_GenerateFunctionCall(NULL, ref->accessor->get, arg, NULL, args);
}
else
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, ref->base, "Accessor has no appropriate get function");
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, ref->base, "Accessor %s has no get function", ref->accessor?ref->accessor->fieldname:"");
break;
}
if (ref->cast != ret->type)
@ -6777,18 +6806,19 @@ QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pb
}
break;
case REF_ACCESSOR:
if (!dest->index && dest->base->type->setptr)
if (dest->accessor && dest->accessor->set)
{
QCC_def_t *arg[] = {dest->base, source};
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setptr, arg, NULL/*argt*/, 2));
}
else if (dest->index && dest->base->type->setarr)
{
QCC_def_t *arg[] = {dest->base, dest->index?QCC_SupplyConversion(dest->index, dest->base->type->setarr->type->params[1].type->type, true):QCC_MakeIntConst(0), source};
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->base->type->setarr, arg, NULL/*argt*/, 2));
int args = 0;
QCC_def_t *arg[3] = {NULL, NULL, NULL};
arg[args++] = dest->base;
if (dest->accessor->indexertype)
arg[args++] = dest->index?QCC_SupplyConversion(dest->index, dest->accessor->indexertype->type, true):QCC_MakeIntConst(0);
arg[args++] = source;
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, dest->accessor->set, arg, NULL/*argt*/, args));
}
else
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, dest->base, "Accessor has no suitable set function");
QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, dest->base, "Accessor has no set function");
break;
case REF_FIELD:
// {

View File

@ -43,6 +43,11 @@ CompilerConstant_t *CompilerConstant;
int numCompilerConstants;
extern pbool expandedemptymacro;
//really these should not be in here
extern unsigned int locals_end, locals_start;
extern QCC_type_t *pr_classtype;
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type);
static void Q_strlcpy(char *dest, const char *src, int sizeofdest)
{
@ -3669,11 +3674,7 @@ int typecmp_strict(QCC_type_t *a, QCC_type_t *b)
if (a->size != b->size)
return 1;
if (a->getarr != b->getarr ||
a->getptr != b->getptr ||
a->setarr != b->setarr ||
a->setptr != b->setptr ||
a->getlength != b->getlength)
if (a->accessors != b->accessors)
return 1;
if (STRCMP(a->name, b->name))
@ -4228,6 +4229,28 @@ QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto)
ptype->size = ptype->aux_type->size;
return QCC_PR_FindType (ptype);
}
QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, QCC_type_t **args, char **argnames, int numargs)
{
int i;
struct QCC_typeparam_s *p;
QCC_type_t *ftype;
ftype = QCC_PR_NewType("$func", ev_function, false);
ftype->aux_type = rettype;
ftype->num_parms = numargs;
ftype->params = p = qccHunkAlloc(sizeof(*ftype->params)*numargs);
ftype->vargs = false;
ftype->vargcount = false;
for (i = 0; i < numargs; i++, p++)
{
p->paramname = qccHunkAlloc(strlen(argnames[i])+1);
strcpy(p->paramname, argnames[i]);
p->type = args[i];
p->optional = false;
p->ofs = 0;
p->arraysize = 0;
}
return QCC_PR_FindType (ftype);
}
extern char *basictypenames[];
extern QCC_type_t **basictypes[];
@ -4300,6 +4323,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
//accessors
if (QCC_PR_CheckKeyword (keyword_class, "accessor"))
{
char *parentname;
char *accessorname;
char *funcname;
@ -4323,12 +4347,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (QCC_PR_CheckToken(":"))
{
char *parentname = QCC_PR_ParseName();
parentname = QCC_PR_ParseName();
type = QCC_TypeForName(parentname);
if (!type || type->type == ev_struct || type->type == ev_union)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
}
else
type = NULL;
if (!newt)
{
@ -4336,93 +4362,163 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
newt->size=type->size;
}
if (!newt->parentclass)
{
newt->parentclass = type;
if (!newt->parentclass || newt->parentclass->type == ev_struct || newt->parentclass->type == ev_union || newt->size != newt->parentclass->size)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
}
else if (type != newt->parentclass)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s basic type mismatch", accessorname);
if (QCC_PR_CheckToken(":"))
if (QCC_PR_CheckToken("{"))
{
char *parentname = QCC_PR_ParseName();
if (newt->aux_type)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Accessor %s was already defined", accessorname);
newt->aux_type = QCC_TypeForName(parentname);
if (!newt->parentclass || newt->parentclass->type == ev_struct || newt->parentclass->type == ev_union || newt->size != newt->parentclass->size)
QCC_PR_ParseError(ERR_NOTANAME, "Accessor %s cannot be based upon %s", accessorname, parentname);
struct accessor_s *acc;
pbool setnotget;
char *fieldtypename;
QCC_type_t *fieldtype;
QCC_type_t *indextype;
QCC_def_t *def;
QCC_type_t *functype;
char *argname[3];
QCC_type_t *arg[3];
int args;
char *indexname;
if (QCC_PR_CheckToken("["))
{
newt->vargcount = true;
QCC_PR_Expect("]");
}
QCC_PR_Expect("{");
do
{
if (QCC_PR_CheckName("length"))
{
QCC_PR_Expect("=");
funcname = QCC_PR_ParseName();
newt->getlength = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
if (!newt->getlength)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
else if (newt->getlength->type->type != ev_function || newt->getlength->type->num_parms != 1)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "length function unsuitable \"%s\"", funcname);
}
if (QCC_PR_CheckName("set"))
setnotget = true;
else if (QCC_PR_CheckName("get"))
setnotget = false;
else
break;
fieldtypename = QCC_PR_ParseName();
fieldtype = QCC_TypeForName(fieldtypename);
if (!fieldtype)
QCC_PR_ParseError(ERR_NOTATYPE, "Invalid type: %s", fieldtypename);
if (pr_token_type != tt_punct)
{
pbool stareq = QCC_PR_CheckToken("*=");
if (stareq || QCC_PR_CheckToken("*"))
funcname = QCC_PR_ParseName();
accessorname = qccHunkAlloc(strlen(funcname)+1);
strcpy(accessorname, funcname);
}
else
accessorname = "";
indextype = NULL;
indexname = "index";
if (QCC_PR_CheckToken("["))
{
fieldtypename = QCC_PR_ParseName();
indextype = QCC_TypeForName(fieldtypename);
if (!QCC_PR_CheckToken("]"))
{
if (!stareq) QCC_PR_Expect("=");
funcname = QCC_PR_ParseName();
newt->getptr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
if (!newt->getptr)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
else if (newt->getptr->type->type != ev_function || (newt->getptr->type->num_parms != 1 && !(newt->getptr->type->num_parms > 1 && newt->getptr->type->params[1].optional)))
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "get* function unsuitable \"%s\"", funcname);
}
else
{
if (QCC_PR_CheckToken("["))
QCC_PR_Expect("]");
QCC_PR_Expect("=");
funcname = QCC_PR_ParseName();
newt->getarr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
if (!newt->getarr)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
else if (newt->getarr->type->type != ev_function || (newt->getarr->type->num_parms != 2 && !(newt->getarr->type->num_parms > 2 && newt->getarr->type->params[2].optional)))
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "get[] function unsuitable \"%s\"", funcname);
indexname = QCC_PR_ParseName();
QCC_PR_Expect("]");
}
}
else if (QCC_PR_CheckName("set"))
QCC_PR_Expect("=");
args = 0;
strcpy (pr_parm_names[args], "this");
argname[args] = "this";
arg[args++] = newt;
if (indextype)
{
pbool stareq = QCC_PR_CheckToken("*=");
if (stareq || QCC_PR_CheckToken("*"))
{
if (!stareq) QCC_PR_Expect("=");
funcname = QCC_PR_ParseName();
newt->setptr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
if (!newt->setptr)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
else if (newt->setptr->type->type != ev_function || (newt->setptr->type->num_parms != 2 && !(newt->setptr->type->num_parms > 2 && newt->setptr->type->params[2].optional)))
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "set* function unsuitable \"%s\"", funcname);
}
strcpy (pr_parm_names[args], indexname);
argname[args] = indexname;
arg[args++] = indextype;
}
if (setnotget)
{
strcpy (pr_parm_names[args], "value");
argname[args] = "value";
arg[args++] = fieldtype;
}
functype = QCC_PR_GenFunctionType(setnotget?type_void:fieldtype, arg, argname, args);
if (pr_token_type != tt_name)
{
QCC_function_t *f;
QCC_dfunction_t *df;
char funcname[256];
QC_snprintfz(funcname, sizeof(funcname), "%s::%s_%s", newt->name, setnotget?"set":"get", accessorname);
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, GDF_CONST);
pr_scope = def;
//pr_classtype = newt;
f = QCC_PR_ParseImmediateStatements (functype);
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++)
{
if (QCC_PR_CheckToken("["))
QCC_PR_Expect("]");
QCC_PR_Expect("=");
funcname = QCC_PR_ParseName();
newt->setarr = QCC_PR_GetDef(NULL, funcname, NULL, false, 0, 0);
if (!newt->setarr)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", funcname);
else if (newt->setarr->type->type != ev_function || (newt->setarr->type->num_parms != 3 && !(newt->setarr->type->num_parms > 3 && newt->setarr->type->params[3].optional)))
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "set[] function unsuitable \"%s\"", funcname);
df->parm_size[i] = functype->params[i].type->size;
}
}
else
break;
{
funcname = QCC_PR_ParseName();
def = QCC_PR_GetDef(functype, funcname, NULL, true, 0, 0);
if (!def)
QCC_Error(ERR_NOFUNC, "%s::set_%s: %s was not defined", newt->name, accessorname, funcname);
}
if (!def)
QCC_Error(ERR_NOFUNC, "%s::%s_%s function invalid", newt->name, setnotget?"set":"get", accessorname);
for (acc = newt->accessors; acc; acc = acc->next)
if (!strcmp(acc->fieldname, accessorname))
break;
if (!acc)
{
acc = qccHunkAlloc(sizeof(*acc));
acc->fieldname = accessorname;
acc->next = newt->accessors;
acc->type = fieldtype;
acc->indexertype = indextype;
newt->accessors = acc;
}
if (setnotget)
{
if (acc->set)
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::set_%s already declared", newt->name, accessorname);
acc->set = def;
}
else
{
if (acc->get)
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::get_%s already declared", newt->name, accessorname);
acc->get = def;
}
} while (QCC_PR_CheckToken(",") || QCC_PR_CheckToken(";"));
QCC_PR_Expect("}");
}
@ -4606,10 +4702,6 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_Error(ERR_INTERNAL, "Can only initialise member functions");
else
{
extern unsigned int locals_end, locals_start;
extern QCC_type_t *pr_classtype;
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type);
if (autoprototype)
{
QCC_PR_Expect("{");