Fix several double-related bug

float is promoted to double through ... for non-v6 code.
PR_Sprintf has custom param access via P_*, messed up doubles.
This commit is contained in:
Bill Currie 2020-02-14 18:15:34 +09:00
parent eb7f825158
commit 2cd62fe01b
8 changed files with 27 additions and 6 deletions

View file

@ -202,6 +202,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
base -= sizeof (progs); // offsets are from file start
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
pr->float_promoted = progs.version == PROG_VERSION;
if (pr->edicts) {
*pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size);
}

View file

@ -77,6 +77,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
"integer",
"uinteger",
"short",
"double",
"invalid",
};

View file

@ -649,6 +649,8 @@ free_fmt_item (fmt_item_t *fi)
#undef P_var
#define P_var(p,n,t) (args[n]->t##_var)
#undef P_DOUBLE
#define P_DOUBLE(p,n) (*(double *) (args[n]))
VISIBLE void
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
const char *format, int count, pr_type_t **args)

View file

@ -305,6 +305,19 @@ enum {
*/
#define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var)
/** Access a double variable in the object file. Can be assigned to.
\par QC type:
\c double
\param q pointer to ::qfo_t struct
\param s space index
\param o offset into object file data space
\return double lvalue
\hideinitializer
*/
#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].d.data + o))
/** Access a float variable in the object file. Can be assigned to.
\par QC type:

View file

@ -92,6 +92,7 @@ extern pr_info_t pr;
#define GETSTR(s) (pr.strings->strings + (s))
#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var)
#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset))
#define D_FLOAT(d) D_var (float, d)
#define D_INT(d) D_var (integer, d)
#define D_VECTOR(d) D_var (vector, d)

View file

@ -867,7 +867,7 @@ expr_double (expr_t *e)
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
&& e->e.symbol->s.def->constant
&& is_double (e->e.symbol->s.def->type))
return D_FLOAT (e->e.symbol->s.def);
return D_DOUBLE (e->e.symbol->s.def);
internal_error (e, "not a double constant");
}
@ -1915,6 +1915,10 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params)
if (is_integer_val (e)
&& options.code.progsversion == PROG_ID_VERSION)
convert_int (e);
if (is_float (get_type (e))
&& options.code.progsversion != PROG_ID_VERSION) {
t = &type_double;
}
if (is_integer_val (e) && options.warnings.vararg_integer)
warning (e, "passing integer constant into ... function");
}
@ -2611,8 +2615,7 @@ cast_expr (type_t *type, expr_t *e)
e->e.value = convert_value (val, type);
e->type = ex_value;
c = e;
} else if ((is_float (type) && is_integral (e_type))
|| (is_integral (type) && is_float (e_type))) {
} else if (is_scalar (type) && is_scalar (e_type)) {
c = new_unary_expr ('C', e);
c->e.expr.type = type;
} else if (e->type == ex_uexpr && e->e.expr.op == '.') {

View file

@ -958,8 +958,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
statement_t *s;
src_type = get_type (e->e.expr.e1);
if ((src_type->type == ev_integer && type->type == ev_float)
|| (src_type->type == ev_float && type->type == ev_integer)) {
if (is_scalar (src_type) && is_scalar (type)) {
operand_t *src = 0;
sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
*op = temp_operand (e->e.expr.type);

View file

@ -1,6 +1,6 @@
void printf (string fmt, ...) = #0;
float (string s) stof = #0;
float (float x) sqrt = #0;
@overload float (float x) sqrt = #0;
float
heron (float a, float b, float c)