mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-23 10:50:58 +00:00
[cexpr] Add a flags type
Based on the flags type used in vkparse (difference is the lack of support for plists). Having this will make supporting named flags in cvars much easier (though setting up the enum type is a bit of a chore).
This commit is contained in:
parent
392e032ce2
commit
d68db74049
2 changed files with 53 additions and 0 deletions
|
@ -117,6 +117,7 @@ binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribut
|
|||
exprval_t *cexpr_value (exprtype_t *type, exprctx_t *ctx);
|
||||
exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx);
|
||||
const char *cexpr_enum_get_string (const exprval_t *val, struct va_ctx_s *va_ctx) __attribute__((pure));
|
||||
const char *cexpr_flags_get_string (const exprval_t *val, struct va_ctx_s *va_ctx) __attribute__((pure));
|
||||
int cexpr_eval_string (const char *str, exprctx_t *context);
|
||||
void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3)));
|
||||
|
||||
|
@ -151,6 +152,8 @@ extern exprtype_t cexpr_plitem;
|
|||
extern binop_t cexpr_array_binops[];
|
||||
extern binop_t cexpr_struct_binops[];
|
||||
extern binop_t cexpr_struct_pointer_binops[];
|
||||
extern binop_t cexpr_flag_binops[];
|
||||
extern unop_t cexpr_flag_unops[];
|
||||
|
||||
extern exprsym_t cexpr_lib_symbols[];
|
||||
|
||||
|
|
|
@ -815,3 +815,53 @@ cexpr_enum_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
BINOP(flag, and, int, &)
|
||||
BINOP(flag, or, int, |)
|
||||
BINOP(flag, xor, int, ^)
|
||||
|
||||
UNOP(flag, not, int, ~)
|
||||
|
||||
binop_t cexpr_flag_binops[] = {
|
||||
{ '&', 0, 0, flag_and },
|
||||
{ '|', 0, 0, flag_or },
|
||||
{ '^', 0, 0, flag_xor },
|
||||
{ '=', &cexpr_int, 0, uint_cast_int },
|
||||
{}
|
||||
};
|
||||
|
||||
unop_t cexpr_flag_unops[] = {
|
||||
{ '~', 0, flag_not },
|
||||
{}
|
||||
};
|
||||
|
||||
VISIBLE const char *
|
||||
cexpr_flags_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
exprenum_t *enm = val->type->data;
|
||||
exprsym_t *symbols = enm->symtab->symbols;
|
||||
const char *val_str = 0;
|
||||
|
||||
if (val->type->size != 4) {
|
||||
Sys_Error ("cexpr_flags_get_string: only 32-bit values supported");
|
||||
}
|
||||
uint32_t flags = *(uint32_t *) val->value;
|
||||
for (exprsym_t *sym = symbols; sym->name; sym++) {
|
||||
uint32_t sym_flags = *(uint32_t *) sym->value;
|
||||
// if there are duplicate values, choose the *later* value
|
||||
if (sym[1].name && sym_flags == *(uint32_t *) sym[1].value) {
|
||||
continue;
|
||||
}
|
||||
if ((flags & sym_flags) && !(sym_flags & ~flags)) {
|
||||
if (val_str) {
|
||||
val_str = va (va_ctx, "%s | %s", val_str, sym->name);
|
||||
} else {
|
||||
val_str = sym->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!val_str) {
|
||||
val_str = "0";
|
||||
}
|
||||
return val_str;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue