added scoped enum values.
enum[flags] [class] NAME : TYPE {foo = (TYPE)val, bar=(TYPE)er}; NAME sym = NAME::foo; if (sym == sym.bar) etc; TYPE can be int or float for enumflags, while non-flags enums can be any type that be initialised comfortably (supposedly) including strings and vectors. If the class keyword is used, then expect errors if you store other values into the enum. switch statements should give warnings if a value has no equal case. also fix some compiler warnings. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5271 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
adbb1a1124
commit
a450035e80
6 changed files with 235 additions and 76 deletions
|
@ -66,7 +66,7 @@ typedef struct {
|
|||
int spare[2];
|
||||
} evalc_t;
|
||||
#define sizeofevalc sizeof(evalc_t)
|
||||
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_variant, ev_struct, ev_union, ev_accessor} etype_t;
|
||||
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_variant, ev_struct, ev_union, ev_accessor, ev_enum} etype_t;
|
||||
enum {
|
||||
DEBUG_TRACE_OFF, //debugging should be off.
|
||||
DEBUG_TRACE_INTO, //debug into functions
|
||||
|
|
|
@ -347,6 +347,7 @@ struct accessor_s
|
|||
struct QCC_type_s *type;
|
||||
struct QCC_type_s *indexertype; //null if not indexer
|
||||
QCC_sref_t getset_func[2];
|
||||
QCC_sref_t staticval;
|
||||
pbool getset_isref[2];
|
||||
char *fieldname;
|
||||
};
|
||||
|
@ -366,8 +367,8 @@ typedef struct QCC_type_s
|
|||
pbool typedefed:1;
|
||||
pbool vargs:1; //function has vargs
|
||||
pbool vargcount:1; //function has special varg count param
|
||||
char *name;
|
||||
char *aname;
|
||||
const char *name;
|
||||
const char *aname;
|
||||
|
||||
struct accessor_s *accessors;
|
||||
|
||||
|
@ -688,12 +689,12 @@ void QCC_PR_PrintStatement (QCC_statement_t *s);
|
|||
void QCC_PR_Lex (void);
|
||||
// reads the next token into pr_token and classifies its type
|
||||
|
||||
QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed);
|
||||
QCC_type_t *QCC_PR_NewType (const char *name, int basictype, pbool typedefed); //note: name must be hunk/immediate
|
||||
QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type);
|
||||
QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail);
|
||||
QCC_sref_t QCC_PR_ParseDefaultInitialiser(QCC_type_t *type);
|
||||
extern pbool type_inlinefunction;
|
||||
QCC_type_t *QCC_TypeForName(char *name);
|
||||
QCC_type_t *QCC_TypeForName(const char *name);
|
||||
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_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s *args, int numargs);
|
||||
|
@ -785,6 +786,7 @@ enum {
|
|||
WARN_DUPLICATEPRECOMPILER,
|
||||
WARN_IDENTICALPRECOMPILER,
|
||||
WARN_FORMATSTRING, //sprintf
|
||||
WARN_DEPRECACTEDSYNTAX, //triggered when syntax is used that I'm trying to kill
|
||||
WARN_GMQCC_SPECIFIC, //extension created by gmqcc that conflicts or isn't properly implemented.
|
||||
WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about.
|
||||
WARN_EXTENSION_USED, //extension that frikqcc also understands
|
||||
|
|
|
@ -47,7 +47,8 @@ char *basictypenames[] = {
|
|||
"variant",
|
||||
"struct",
|
||||
"union",
|
||||
"accessor"
|
||||
"accessor",
|
||||
"enum"
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -225,9 +225,9 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
|
|||
QCC_sref_t QCC_PR_GenerateFunctionCall1 (QCC_sref_t newself, QCC_sref_t func, QCC_sref_t a, QCC_type_t *type_a);
|
||||
QCC_sref_t QCC_PR_GenerateFunctionCall2 (QCC_sref_t newself, QCC_sref_t func, QCC_sref_t a, QCC_type_t *type_a, QCC_sref_t b, QCC_type_t *type_b);
|
||||
|
||||
QCC_sref_t QCC_MakeTranslateStringConst(char *value);
|
||||
QCC_sref_t QCC_MakeStringConst(char *value);
|
||||
QCC_sref_t QCC_MakeStringConstLength(char *value, int length);
|
||||
QCC_sref_t QCC_MakeTranslateStringConst(const char *value);
|
||||
QCC_sref_t QCC_MakeStringConst(const char *value);
|
||||
QCC_sref_t QCC_MakeStringConstLength(const char *value, int length);
|
||||
QCC_sref_t QCC_MakeFloatConst(float value);
|
||||
QCC_sref_t QCC_MakeIntConst(int value);
|
||||
QCC_sref_t QCC_MakeVectorConst(float a, float b, float c);
|
||||
|
@ -6758,15 +6758,15 @@ static QCC_sref_t QCC_MakeStringConstInternal(const char *value, size_t length,
|
|||
return QCC_MakeSRefForce(cn, 0, type_string);
|
||||
}
|
||||
|
||||
QCC_sref_t QCC_MakeStringConstLength(char *value, int length)
|
||||
QCC_sref_t QCC_MakeStringConstLength(const char *value, int length)
|
||||
{
|
||||
return QCC_MakeStringConstInternal(value, length, false);
|
||||
}
|
||||
QCC_sref_t QCC_MakeStringConst(char *value)
|
||||
QCC_sref_t QCC_MakeStringConst(const char *value)
|
||||
{
|
||||
return QCC_MakeStringConstInternal(value, strlen(value)+1, false);
|
||||
}
|
||||
QCC_sref_t QCC_MakeTranslateStringConst(char *value)
|
||||
QCC_sref_t QCC_MakeTranslateStringConst(const char *value)
|
||||
{
|
||||
return QCC_MakeStringConstInternal(value, strlen(value)+1, true);
|
||||
}
|
||||
|
@ -7463,7 +7463,7 @@ vectorarrayindex:
|
|||
QCC_FreeTemp(idx);
|
||||
return QCC_PR_BuildRef(retbuf, REF_GLOBAL, QCC_MakeIntConst(arraysize), nullsref, type_integer, true);
|
||||
}
|
||||
else if (t->type == ev_vector && !arraysize && QCC_PR_CheckToken("."))
|
||||
else if (t->type == ev_vector && !arraysize && !t->accessors && QCC_PR_CheckToken("."))
|
||||
{
|
||||
char *swizzle = QCC_PR_ParseName();
|
||||
//single-channel swizzles just result in a float. nice and easy. assignable, too.
|
||||
|
@ -7492,7 +7492,7 @@ vectorarrayindex:
|
|||
}
|
||||
else if (((t->type == ev_pointer && !arraysize) || (t->type == ev_field && (t->aux_type->type == ev_struct || t->aux_type->type == ev_union)) || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")))
|
||||
{
|
||||
char *tname;
|
||||
const char *tname;
|
||||
unsigned int ofs;
|
||||
pbool fld = t->type == ev_field;
|
||||
struct QCC_typeparam_s *p;
|
||||
|
@ -7738,6 +7738,9 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
|
|||
//fixme: namespaces should be relative
|
||||
if (QCC_PR_CheckToken("::"))
|
||||
{
|
||||
struct accessor_s *a;
|
||||
QCC_type_t *p;
|
||||
char membername[1024];
|
||||
expandmemberfields = false; //this::classname should also be available to the find builtin, etc. this won't affect self.classname::member nor classname::staticfunc
|
||||
|
||||
if (assumeclass && !strcmp(name, "super"))
|
||||
|
@ -7746,18 +7749,37 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
|
|||
t = assumeclass;
|
||||
else
|
||||
t = QCC_TypeForName(name);
|
||||
if (!t || t->type != ev_entity)
|
||||
if (!t)
|
||||
{
|
||||
QCC_PR_ParseError (ERR_NOTATYPE, "Not a class \"%s\"", name);
|
||||
d = nullsref;
|
||||
d = QCC_PR_GetSRef (pr_assumetermtype, name, pr_assumetermscope, false, 0, pr_assumetermflags);
|
||||
if (d.cast)
|
||||
{
|
||||
QCC_FreeTemp(d);
|
||||
t = d.cast;
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "\"%s\" is not a type", name);
|
||||
}
|
||||
else
|
||||
|
||||
name = QCC_PR_ParseName ();
|
||||
//walk up the parents if needed, to find one that has that field
|
||||
for(d = nullsref, p = t; ; )
|
||||
{
|
||||
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 = nullsref, p = t; !d.cast && p; p = p->parentclass)
|
||||
if (!d.cast && p->accessors)
|
||||
{
|
||||
for (a = t->accessors; a; a = a->next)
|
||||
{
|
||||
if (!strcmp(a->fieldname, name))
|
||||
{
|
||||
d = a->staticval;
|
||||
QCC_ForceUnFreeDef(d.sym);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d.cast)
|
||||
break;
|
||||
}
|
||||
if (!d.cast && t->type == ev_entity)
|
||||
{
|
||||
//use static functions in preference to virtual functions. kinda needed so you can use super::func...
|
||||
QC_snprintfz(membername, sizeof(membername), "%s::%s", p->name, name);
|
||||
|
@ -7767,11 +7789,16 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
|
|||
QC_snprintfz(membername, sizeof(membername), "%s::"MEMBERFIELDNAME, p->name, name);
|
||||
d = QCC_PR_GetSRef (NULL, membername, pr_scope, false, 0, false);
|
||||
}
|
||||
|
||||
p = p->parentclass;
|
||||
if (p)
|
||||
continue;
|
||||
}
|
||||
if (!d.cast)
|
||||
{
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s::%s\"", t->name, name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!d.cast)
|
||||
{
|
||||
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s::%s\"", t->name, name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -8506,6 +8533,7 @@ void QCC_StoreToSRef(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *type, pbool
|
|||
{
|
||||
case ev_struct:
|
||||
case ev_union:
|
||||
case ev_enum:
|
||||
//don't bother trying to optimise any temps here, its not likely to happen anyway.
|
||||
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
|
||||
{
|
||||
|
@ -9196,6 +9224,11 @@ QCC_sref_t QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
|
|||
QCC_ForceUnFreeDef(ref->accessor->getset_func[0].sym);
|
||||
return QCC_PR_GenerateFunctionCallSref(nullsref, ref->accessor->getset_func[0], arg, args);
|
||||
}
|
||||
else if (ref->accessor && ref->accessor->staticval.cast)
|
||||
{
|
||||
QCC_ForceUnFreeDef(ref->accessor->staticval.sym);
|
||||
return ref->accessor->staticval;
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseErrorPrintSRef(ERR_NOFUNC, ref->base, "Accessor %s has no get function", ref->accessor?ref->accessor->fieldname:"");
|
||||
break;
|
||||
|
@ -9473,6 +9506,16 @@ QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_sref_t lhs, QCC_sref_t rhs, QCC_opcode_t *
|
|||
type_a = lhs.cast->type;
|
||||
// type_b = rhs.cast->type;
|
||||
|
||||
if (type_a == ev_enum)
|
||||
{
|
||||
if (lhs.cast == rhs.cast)
|
||||
{
|
||||
lhs.cast = lhs.cast->aux_type;
|
||||
rhs.cast = rhs.cast->aux_type;
|
||||
// type_a = lhs.cast->type;
|
||||
}
|
||||
}
|
||||
|
||||
if (op->name[0] == '.')// field access gets type from field
|
||||
{
|
||||
if (rhs.cast->aux_type)
|
||||
|
@ -10925,6 +10968,7 @@ void QCC_PR_ParseStatement (void)
|
|||
int defaultcase = -1;
|
||||
int oldst;
|
||||
QCC_type_t *switchtype;
|
||||
struct accessor_s *acc;
|
||||
|
||||
breaks = num_breaks;
|
||||
cases = num_cases;
|
||||
|
@ -10967,7 +11011,7 @@ void QCC_PR_ParseStatement (void)
|
|||
//it should be possible to nest these.
|
||||
|
||||
switchtype = e.cast;
|
||||
switch(switchtype->type)
|
||||
switch(switchtype->type==ev_enum?switchtype->aux_type->type:switchtype->type)
|
||||
{
|
||||
case ev_float:
|
||||
op = OP_SWITCH_F;
|
||||
|
@ -11028,6 +11072,39 @@ void QCC_PR_ParseStatement (void)
|
|||
|
||||
oldst = numstatements;
|
||||
|
||||
for (acc = switchtype->accessors; acc; acc = acc->next)
|
||||
{
|
||||
const QCC_eval_t *match = QCC_SRef_EvalConst(acc->staticval);
|
||||
if (!match)
|
||||
continue; //not an enum value, ignore it.
|
||||
for (i = cases; i < num_cases; i++)
|
||||
{
|
||||
if (!pr_casesref[i].cast)
|
||||
break; //its a default
|
||||
if (pr_casesref2[i].cast)
|
||||
{ //caserange
|
||||
break; //FIXME: too lazy to check these.
|
||||
}
|
||||
else
|
||||
{ //case
|
||||
if (pr_casesref[i].type == REF_GLOBAL && pr_casesref[i].cast == switchtype)
|
||||
{
|
||||
const QCC_eval_t *eval = QCC_SRef_EvalConst(pr_casesref[i].base);
|
||||
if (!eval)
|
||||
break; //can't verify it
|
||||
if (!memcmp(eval, match, sizeof(*eval)*switchtype->size))
|
||||
break; //validated.
|
||||
}
|
||||
else
|
||||
break; //can't verify it
|
||||
}
|
||||
}
|
||||
if (i == num_cases)
|
||||
{
|
||||
QCC_PR_ParseWarning(0, "%s::%s not part of switch", switchtype->name, acc->fieldname);
|
||||
}
|
||||
}
|
||||
|
||||
QCC_ForceUnFreeDef(e.sym); //in the following code, e should still be live
|
||||
for (i = cases; i < num_cases; i++)
|
||||
{
|
||||
|
@ -11090,7 +11167,7 @@ void QCC_PR_ParseStatement (void)
|
|||
const QCC_eval_t *eval = QCC_SRef_EvalConst(dmin);
|
||||
if (!eval || eval->_int)
|
||||
{
|
||||
switch(e.cast->type)
|
||||
switch(e.cast->type==ev_enum?e.cast->aux_type->type:e.cast->type)
|
||||
{
|
||||
case ev_float:
|
||||
e2 = QCC_PR_StatementFlags (&pr_opcodes[OP_EQ_F], e, dmin, NULL, STFL_PRESERVEA);
|
||||
|
@ -14551,22 +14628,61 @@ QCC_sref_t QCC_PR_ParseDefaultInitialiser(QCC_type_t *type)
|
|||
int accglobalsblock; //0 = error, 1 = var, 2 = function, 3 = objdata
|
||||
|
||||
|
||||
void QCC_PR_ParseEnum(pbool flags)
|
||||
QCC_type_t *QCC_PR_ParseEnum(pbool flags)
|
||||
{
|
||||
const char *name;
|
||||
const char *name = NULL;
|
||||
QCC_sref_t sref;
|
||||
pbool wantint = false;
|
||||
int iv = flags?1:0;
|
||||
float fv = iv;
|
||||
int next_i = flags?1:0;
|
||||
float next_f = next_i;
|
||||
struct accessor_s *acc;
|
||||
QCC_type_t *enumtype = NULL, *basetype;
|
||||
pbool strictenum = false;
|
||||
basetype = (flag_assume_integer?type_integer:type_float);
|
||||
|
||||
if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int"))
|
||||
wantint = true;
|
||||
else if (QCC_PR_CheckKeyword(keyword_float, "float"))
|
||||
wantint = false;
|
||||
else
|
||||
wantint = flag_assume_integer;
|
||||
if (!QCC_PR_CheckToken("{"))
|
||||
{
|
||||
QCC_type_t *type;
|
||||
|
||||
strictenum = QCC_PR_CheckName("class"); //c++11 style
|
||||
|
||||
type = QCC_PR_ParseType(false, true); //legacy behaviour
|
||||
if (type)
|
||||
basetype = basetype;
|
||||
else
|
||||
{
|
||||
basetype = (flag_assume_integer?type_integer:type_float);
|
||||
if (pr_token_type == tt_name)
|
||||
name = QCC_PR_ParseName();
|
||||
else
|
||||
name = NULL;
|
||||
if (QCC_PR_CheckToken(":"))
|
||||
basetype = QCC_PR_ParseType(false, false);
|
||||
else if (strictenum)
|
||||
QCC_PR_Expect(":");
|
||||
}
|
||||
QCC_PR_Expect("{");
|
||||
}
|
||||
|
||||
if (flags && basetype->type != ev_float && basetype->type != ev_integer && basetype->type != ev_vector)
|
||||
QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - must be numeric type");
|
||||
|
||||
if (name)
|
||||
{
|
||||
enumtype = QCC_TypeForName(name);
|
||||
if (!enumtype)
|
||||
{
|
||||
if (strictenum)
|
||||
{
|
||||
enumtype = QCC_PR_NewType(name, basetype->type, true);
|
||||
enumtype->aux_type = basetype;
|
||||
enumtype->type = ev_enum;
|
||||
}
|
||||
else
|
||||
enumtype = QCC_PR_NewType(name, basetype->type, true);
|
||||
enumtype->size = basetype->size;
|
||||
}
|
||||
}
|
||||
|
||||
QCC_PR_Expect("{");
|
||||
while(1)
|
||||
{
|
||||
name = QCC_PR_ParseName();
|
||||
|
@ -14586,28 +14702,48 @@ void QCC_PR_ParseEnum(pbool flags)
|
|||
{
|
||||
const QCC_eval_t *eval;
|
||||
sref = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
sref = QCC_SupplyConversion(sref, basetype->type, true);
|
||||
eval = QCC_SRef_EvalConst(sref);
|
||||
if (eval)
|
||||
{
|
||||
if (sref.cast->type == ev_float)
|
||||
iv = fv = eval->_float;
|
||||
else
|
||||
fv = iv = eval->_int;
|
||||
next_i = next_f = eval->_float;
|
||||
else if (sref.cast->type == ev_integer)
|
||||
next_f = next_i = eval->_int;
|
||||
}
|
||||
else if (sref.sym)
|
||||
QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", sref.sym->name);
|
||||
else
|
||||
QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
|
||||
|
||||
QCC_FreeTemp(sref);
|
||||
//do this, because we can. with any luck we'll just hit the same const anyway, and if not then we may have managed to avoid hitting a global.
|
||||
if (basetype->type==ev_integer)
|
||||
{
|
||||
QCC_FreeTemp(sref);
|
||||
sref = QCC_MakeIntConst(next_i);
|
||||
}
|
||||
else if (basetype->type==ev_float)
|
||||
{
|
||||
QCC_FreeTemp(sref);
|
||||
sref = QCC_MakeFloatConst(next_i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (basetype->type==ev_integer)
|
||||
sref = QCC_MakeIntConst(next_i);
|
||||
else if (basetype->type==ev_float)
|
||||
sref = QCC_MakeFloatConst(next_f);
|
||||
else
|
||||
QCC_PR_ParseError(ERR_NOTANUMBER, "values for enums of this type must be initialised");
|
||||
}
|
||||
if (flags)
|
||||
{
|
||||
int bits = 0;
|
||||
int i = wantint?iv:(int)fv;
|
||||
if (!wantint && i != fv)
|
||||
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer value", fv);
|
||||
int i = (basetype->type==ev_integer)?next_i:(int)next_f;
|
||||
if (basetype->type!=ev_integer && i != next_f)
|
||||
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer value", next_f);
|
||||
else
|
||||
{
|
||||
while(i)
|
||||
|
@ -14617,25 +14753,42 @@ void QCC_PR_ParseEnum(pbool flags)
|
|||
i>>=1;
|
||||
}
|
||||
if (bits > 1)
|
||||
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f has multiple bits set", fv);
|
||||
QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %x(%f) has multiple bits set", next_i, next_f);
|
||||
}
|
||||
}
|
||||
if (wantint)
|
||||
sref = QCC_MakeIntConst(iv);
|
||||
if (enumtype)
|
||||
{
|
||||
for (acc = enumtype->accessors; acc; acc = acc->next)
|
||||
if (!strcmp(acc->fieldname, name))
|
||||
{
|
||||
QCC_Error(ERR_TOOMANYINITIALISERS, "%s::%s already declared", enumtype->name, name);
|
||||
break;
|
||||
}
|
||||
acc = qccHunkAlloc(sizeof(*acc));
|
||||
acc->fieldname = (char*)name;
|
||||
acc->next = enumtype->accessors;
|
||||
acc->type = enumtype;//sref.cast;
|
||||
acc->indexertype = NULL;
|
||||
enumtype->accessors = acc;
|
||||
|
||||
acc->staticval = sref;
|
||||
acc->staticval.cast = enumtype;
|
||||
}
|
||||
else
|
||||
sref = QCC_MakeFloatConst(fv);
|
||||
pHash_Add(&globalstable, name, sref.sym, qccHunkAlloc(sizeof(bucket_t)));
|
||||
{ //value gets added to global pool
|
||||
pHash_Add(&globalstable, name, sref.sym, qccHunkAlloc(sizeof(bucket_t)));
|
||||
}
|
||||
QCC_FreeTemp(sref);
|
||||
|
||||
if (flags)
|
||||
{
|
||||
fv *= 2;
|
||||
iv *= 2;
|
||||
next_f *= 2;
|
||||
next_i *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fv++;
|
||||
iv++;
|
||||
next_f++;
|
||||
next_i++;
|
||||
}
|
||||
|
||||
if (QCC_PR_CheckToken("}"))
|
||||
|
@ -14644,6 +14797,7 @@ void QCC_PR_ParseEnum(pbool flags)
|
|||
if (QCC_PR_CheckToken("}"))
|
||||
break; // accept trailing comma
|
||||
}
|
||||
return enumtype?enumtype:basetype;
|
||||
}
|
||||
/*
|
||||
================
|
||||
|
@ -14685,20 +14839,6 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal)
|
|||
while (QCC_PR_CheckToken(";"))
|
||||
fatal = false;
|
||||
|
||||
//FIXME: these should be moved into parsetype
|
||||
if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
|
||||
{
|
||||
QCC_PR_ParseEnum(false);
|
||||
QCC_PR_Expect(";");
|
||||
return;
|
||||
}
|
||||
if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags"))
|
||||
{
|
||||
QCC_PR_ParseEnum(true);
|
||||
QCC_PR_Expect(";");
|
||||
return;
|
||||
}
|
||||
|
||||
if (QCC_PR_CheckKeyword (keyword_typedef, "typedef"))
|
||||
{
|
||||
type = QCC_PR_ParseType(false, false);
|
||||
|
|
|
@ -103,7 +103,7 @@ QCC_def_t def_ret, def_parms[MAX_PARMS];
|
|||
void QCC_PR_LexWhitespace (pbool inhibitpreprocessor);
|
||||
|
||||
|
||||
|
||||
QCC_type_t *QCC_PR_ParseEnum(pbool flags);
|
||||
|
||||
//for compiler constants and file includes.
|
||||
|
||||
|
@ -4500,6 +4500,7 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in, pbool recurse)
|
|||
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->accessors = in->accessors;
|
||||
out->size = in->size;
|
||||
out->num_parms = in->num_parms;
|
||||
out->name = in->name;
|
||||
|
@ -4659,7 +4660,7 @@ QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
|
|||
}
|
||||
*/
|
||||
|
||||
QCC_type_t *QCC_TypeForName(char *name)
|
||||
QCC_type_t *QCC_TypeForName(const char *name)
|
||||
{
|
||||
return pHash_Get(&typedeftable, name);
|
||||
/*
|
||||
|
@ -4953,8 +4954,7 @@ QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto)
|
|||
{
|
||||
char name[128];
|
||||
QC_snprintfz(name, sizeof(name), "ptr to %s", pointsto->name);
|
||||
e->name = qccHunkAlloc(strlen(name)+1);
|
||||
strcpy(e->name, name);
|
||||
e->name = strcpy(qccHunkAlloc(strlen(name)+1), name);
|
||||
}
|
||||
pointsto->ptrto = e;
|
||||
return e;
|
||||
|
@ -5681,6 +5681,22 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//FIXME: these should be moved into parsetype
|
||||
if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
|
||||
{
|
||||
newt = QCC_PR_ParseEnum(false);
|
||||
if (QCC_PR_CheckToken(";"))
|
||||
return NULL;
|
||||
return newt;
|
||||
}
|
||||
if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags"))
|
||||
{
|
||||
newt = QCC_PR_ParseEnum(true);
|
||||
if (QCC_PR_CheckToken(";"))
|
||||
return NULL;
|
||||
return newt;
|
||||
}
|
||||
|
||||
structtype = ev_void;
|
||||
if (QCC_PR_CheckKeyword (keyword_union, "union"))
|
||||
structtype = ev_union;
|
||||
|
|
|
@ -3039,7 +3039,7 @@ PR_PrintDefs
|
|||
QCC_PR_PrintOfs (d->ofs);
|
||||
}*/
|
||||
|
||||
QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed)
|
||||
QCC_type_t *QCC_PR_NewType (const char *name, int basictype, pbool typedefed)
|
||||
{
|
||||
if (numtypeinfos>= maxtypeinfos)
|
||||
QCC_Error(ERR_TOOMANYTYPES, "Too many types");
|
||||
|
|
Loading…
Reference in a new issue