[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:
Bill Currie 2022-04-24 15:04:08 +09:00
parent db5b77c838
commit 392e032ce2
3 changed files with 77 additions and 0 deletions

View file

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

View file

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

View file

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