mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[cexpr] Add a get_string function to exprtype_t
This allows for easy (and safe) printing of cexpr values where the type supports it. Types that don't support printing would be due to being too complex or possibly write-only (eg, password strings, when strings are supported directly).
This commit is contained in:
parent
db5b77c838
commit
392e032ce2
3 changed files with 77 additions and 0 deletions
|
@ -31,6 +31,7 @@
|
|||
|
||||
struct exprval_s;
|
||||
struct exprctx_s;
|
||||
struct va_ctx_s;
|
||||
|
||||
typedef struct binop_s {
|
||||
int op;
|
||||
|
@ -52,6 +53,7 @@ typedef struct unop_s {
|
|||
typedef struct exprtype_s {
|
||||
const char *name;
|
||||
size_t size;
|
||||
const char *(*get_string) (const struct exprval_s *val, struct va_ctx_s *va_ctx);
|
||||
binop_t *binops;
|
||||
unop_t *unops;
|
||||
void *data;
|
||||
|
@ -114,6 +116,7 @@ int cexpr_parse_enum (exprenum_t *enm, const char *str,
|
|||
binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribute__((pure));
|
||||
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));
|
||||
int cexpr_eval_string (const char *str, exprctx_t *context);
|
||||
void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3)));
|
||||
|
||||
|
|
|
@ -28,11 +28,14 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/cexpr.h"
|
||||
#include "QF/cmem.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
#include "libs/util/cexpr-parse.h"
|
||||
|
@ -99,6 +102,12 @@ int_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result,
|
|||
*(int *) result->value = c + (mask & b);
|
||||
}
|
||||
|
||||
static const char *
|
||||
int_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
return va (va_ctx, "%d", *(int *) val->value);
|
||||
}
|
||||
|
||||
binop_t int_binops[] = {
|
||||
{ SHL, &cexpr_int, &cexpr_int, int_shl },
|
||||
{ SHR, &cexpr_int, &cexpr_int, int_shr },
|
||||
|
@ -128,6 +137,7 @@ exprtype_t cexpr_int = {
|
|||
.size = sizeof (int),
|
||||
.binops = int_binops,
|
||||
.unops = int_unops,
|
||||
.get_string = int_get_string,
|
||||
};
|
||||
|
||||
BINOP(uint, shl, unsigned, <<)
|
||||
|
@ -153,6 +163,12 @@ UNOP(uint, neg, unsigned, -)
|
|||
UNOP(uint, tnot, unsigned, !)
|
||||
UNOP(uint, bnot, unsigned, ~)
|
||||
|
||||
static const char *
|
||||
uint_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
return va (va_ctx, "%u", *(unsigned *) val->value);
|
||||
}
|
||||
|
||||
binop_t uint_binops[] = {
|
||||
{ SHL, &cexpr_uint, &cexpr_uint, uint_shl },
|
||||
{ SHR, &cexpr_uint, &cexpr_uint, uint_shr },
|
||||
|
@ -183,6 +199,7 @@ exprtype_t cexpr_uint = {
|
|||
.size = sizeof (unsigned),
|
||||
.binops = uint_binops,
|
||||
.unops = uint_unops,
|
||||
.get_string = uint_get_string,
|
||||
};
|
||||
|
||||
BINOP(size_t, shl, unsigned, <<)
|
||||
|
@ -221,6 +238,12 @@ UNOP(size_t, neg, unsigned, -)
|
|||
UNOP(size_t, tnot, unsigned, !)
|
||||
UNOP(size_t, bnot, unsigned, ~)
|
||||
|
||||
static const char *
|
||||
size_t_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
return va (va_ctx, "%zd", *(size_t *) val->value);
|
||||
}
|
||||
|
||||
binop_t size_t_binops[] = {
|
||||
{ SHL, &cexpr_size_t, &cexpr_size_t, size_t_shl },
|
||||
{ SHR, &cexpr_size_t, &cexpr_size_t, size_t_shr },
|
||||
|
@ -252,6 +275,7 @@ exprtype_t cexpr_size_t = {
|
|||
.size = sizeof (size_t),
|
||||
.binops = size_t_binops,
|
||||
.unops = size_t_unops,
|
||||
.get_string = size_t_get_string,
|
||||
};
|
||||
|
||||
BINOP(float, add, float, +)
|
||||
|
@ -309,6 +333,12 @@ UNOP(float, pos, float, +)
|
|||
UNOP(float, neg, float, -)
|
||||
UNOP(float, tnot, float, !)
|
||||
|
||||
static const char *
|
||||
float_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
return va (va_ctx, "%.9g", *(float *) val->value);
|
||||
}
|
||||
|
||||
binop_t float_binops[] = {
|
||||
{ '+', &cexpr_float, &cexpr_float, float_add },
|
||||
{ '-', &cexpr_float, &cexpr_float, float_sub },
|
||||
|
@ -337,6 +367,7 @@ exprtype_t cexpr_float = {
|
|||
.size = sizeof (float),
|
||||
.binops = float_binops,
|
||||
.unops = float_unops,
|
||||
.get_string = float_get_string,
|
||||
};
|
||||
|
||||
BINOP(double, add, double, +)
|
||||
|
@ -375,6 +406,12 @@ UNOP(double, pos, double, +)
|
|||
UNOP(double, neg, double, -)
|
||||
UNOP(double, tnot, double, !)
|
||||
|
||||
static const char *
|
||||
double_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
return va (va_ctx, "%.17g", *(double *) val->value);
|
||||
}
|
||||
|
||||
binop_t double_binops[] = {
|
||||
{ '+', &cexpr_double, &cexpr_double, double_add },
|
||||
{ '-', &cexpr_double, &cexpr_double, double_sub },
|
||||
|
@ -401,6 +438,7 @@ exprtype_t cexpr_double = {
|
|||
.size = sizeof (double),
|
||||
.binops = double_binops,
|
||||
.unops = double_unops,
|
||||
.get_string = double_get_string,
|
||||
};
|
||||
|
||||
BINOP(vector, add, vec4f_t, +)
|
||||
|
@ -518,6 +556,13 @@ vector_swizzle (const exprval_t *val1, const exprval_t *val2,
|
|||
UNOP(vector, pos, vec4f_t, +)
|
||||
UNOP(vector, neg, vec4f_t, -)
|
||||
|
||||
static const char *
|
||||
vector_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
vec4f_t vec = *(vec4f_t *) val->value;
|
||||
return va (va_ctx, VEC4F_FMT, VEC4_EXP (vec));
|
||||
}
|
||||
|
||||
static void
|
||||
vector_tnot (const exprval_t *val, exprval_t *result, exprctx_t *ctx)
|
||||
{
|
||||
|
@ -550,6 +595,7 @@ exprtype_t cexpr_vector = {
|
|||
.size = sizeof (vec4f_t),
|
||||
.binops = vector_binops,
|
||||
.unops = vector_unops,
|
||||
.get_string = vector_get_string,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -572,6 +618,13 @@ quaternion_vector_mul (const exprval_t *val1, const exprval_t *val2,
|
|||
*c = qvmulf (a, b);
|
||||
}
|
||||
|
||||
static const char *
|
||||
quaternion_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
vec4f_t vec = *(vec4f_t *) val->value;
|
||||
return va (va_ctx, VEC4F_FMT, VEC4_EXP (vec));
|
||||
}
|
||||
|
||||
binop_t quaternion_binops[] = {
|
||||
{ '+', &cexpr_quaternion, &cexpr_quaternion, vector_add },
|
||||
{ '-', &cexpr_quaternion, &cexpr_quaternion, vector_sub },
|
||||
|
@ -592,6 +645,7 @@ exprtype_t cexpr_quaternion = {
|
|||
.size = sizeof (vec4f_t),
|
||||
.binops = quaternion_binops,
|
||||
.unops = quaternion_unops,
|
||||
.get_string = quaternion_get_string,
|
||||
};
|
||||
|
||||
exprtype_t cexpr_exprval = {
|
||||
|
@ -743,3 +797,21 @@ cexpr_parse_enum (exprenum_t *enm, const char *str, const exprctx_t *ctx,
|
|||
context.result = &result;
|
||||
return cexpr_eval_string (str, &context);
|
||||
}
|
||||
|
||||
VISIBLE const char *
|
||||
cexpr_enum_get_string (const exprval_t *val, va_ctx_t *va_ctx)
|
||||
{
|
||||
exprenum_t *enm = val->type->data;
|
||||
exprsym_t *symbols = enm->symtab->symbols;
|
||||
for (exprsym_t *sym = symbols; sym->name; sym++) {
|
||||
// if there are duplicate values, choose the *later* value
|
||||
if (sym[1].name
|
||||
&& memcmp (sym->value, sym[1].value, val->type->size) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (memcmp (sym->value, val->value, val->type->size) == 0) {
|
||||
return sym->name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -95,9 +95,11 @@ skip_value(string name)
|
|||
if (strip_bit) {
|
||||
fprintf (output_file, "\t.binops = flag_binops,\n");
|
||||
fprintf (output_file, "\t.unops = flag_unops,\n");
|
||||
fprintf (output_file, "\t.get_string = cexpr_flags_get_string,\n");
|
||||
} else {
|
||||
fprintf (output_file, "\t.binops = enum_binops,\n");
|
||||
fprintf (output_file, "\t.unops = 0,\n");
|
||||
fprintf (output_file, "\t.get_string = cexpr_enum_get_string,\n");
|
||||
}
|
||||
fprintf (output_file, "\t.data = &%s_enum,\n", [self name]);
|
||||
fprintf (output_file, "};\n");
|
||||
|
|
Loading…
Reference in a new issue