Implement double constants

This commit is contained in:
Bill Currie 2020-02-14 20:08:59 +09:00
parent 2cd62fe01b
commit 533fb8acc9
11 changed files with 132 additions and 10 deletions

View file

@ -692,7 +692,12 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val)
case ev_uinteger:
dsprintf (line, "$%08x", val->uinteger_var);
break;
default:
case ev_double:
dsprintf (line, "%g", *(double *)val);
break;
case ev_short:
case ev_invalid:
case ev_type_count:
//dsprintf (line, "bad type %i", type);
dsprintf (line, "<%x %x %x %x>",
val[0].integer_var, val[1].integer_var,

View file

@ -174,7 +174,7 @@ typedef struct ex_value_s {
etype_t lltype;
union {
const char *string_val; ///< string constant
float double_val; ///< double constant
double double_val; ///< double constant
float float_val; ///< float constant
float vector_val[3]; ///< vector constant
int entity_val; ///< entity constant

View file

@ -97,6 +97,9 @@ dump_def (progs_t *pr, ddef_t *def, int indent)
case ev_float:
comment = va (" %g", G_FLOAT (pr, offset));
break;
case ev_double:
comment = va (" %.17g", G_DOUBLE (pr, offset));
break;
case ev_vector:
comment = va (" '%g %g %g'",
G_VECTOR (pr, offset)[0],

View file

@ -2273,6 +2273,14 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
e = e1->e.expr.e2;
break;
}
if (e1->e.expr.op == 'A') {
if (!t)
t = e1->e.expr.type;
if (e2) {
e2 = binary_expr ('+', e1->e.expr.e2, e2);
}
return address_expr (e1->e.expr.e1, e2, t);
}
return error (e1, "invalid type for unary &");
case ex_uexpr:
if (e1->e.expr.op == '.') {

View file

@ -93,6 +93,8 @@ B [01]
X [0-9a-fA-F]
ID [a-zA-Z_][a-zA-Z_0-9]*
FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)?
FLOATf {FLOAT}[fF]
FLOATd {FLOAT}[dD]
INT ({D}+|0[xX]{X}+|0[bB]{B})
RANGE \.\.
ELLIPSIS \.\.\.
@ -136,10 +138,35 @@ STRING \"(\\.|[^"\\])*\"
}
{FLOAT} {
// advanced code defaults to double, but traditional
// and extended code defaults to float
if (options.traditional < 1) {
double d = strtod (yytext, 0);
qc_yylval.expr = new_double_expr (d);
} else {
float f = strtof (yytext, 0);
qc_yylval.expr = new_float_expr (f);
}
return VALUE;
}
{FLOATf} {
float f = strtof (yytext, 0);
qc_yylval.expr = new_float_expr (f);
return VALUE;
}
{FLOATd} {
// advanced code defaults to double, but traditional
// and extended code defaults to float
if (options.traditional < 1) {
double d = strtod (yytext, 0);
qc_yylval.expr = new_double_expr (d);
} else {
float f = strtof (yytext, 0);
qc_yylval.expr = new_float_expr (f);
warning (0, "truncating double constant to float");
}
return VALUE;
}
{ID} {
int tok = keyword_or_id(yytext);

View file

@ -69,6 +69,7 @@ typedef struct {
ex_pointer_t pointer;
float quaternion_val[4];
int integer_val;
double double_val;
} i;
} immediate_t;
@ -275,6 +276,7 @@ static hashtab_t *func_imm_defs;
static hashtab_t *pointer_imm_defs;
static hashtab_t *quaternion_imm_defs;
static hashtab_t *integer_imm_defs;
static hashtab_t *double_imm_defs;
static void
imm_free (void *_imm, void *unused)
@ -306,6 +308,8 @@ imm_get_hash (const void *_imm, void *_tab)
} else if (tab == &quaternion_imm_defs) {
return Hash_Buffer (&imm->i.quaternion_val,
sizeof (&imm->i.quaternion_val));
} else if (tab == &double_imm_defs) {
return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val));
} else if (tab == &integer_imm_defs) {
return imm->i.integer_val;
} else {
@ -340,6 +344,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab)
sizeof (imm1->i.pointer));
} else if (tab == &quaternion_imm_defs) {
return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val);
} else if (tab == &double_imm_defs) {
return imm1->i.double_val == imm2->i.double_val;
} else if (tab == &integer_imm_defs) {
return imm1->i.integer_val == imm2->i.integer_val;
} else {
@ -362,6 +368,24 @@ value_as_float (ex_value_t *value)
return value->v.integer_val;
if (value->lltype == ev_short)
return value->v.short_val;
if (value->lltype == ev_double)
return value->v.double_val;
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
}
static double
value_as_double (ex_value_t *value)
{
if (value->lltype == ev_uinteger)
return value->v.uinteger_val;
if (value->lltype == ev_integer)
return value->v.integer_val;
if (value->lltype == ev_short)
return value->v.short_val;
if (value->lltype == ev_double)
return value->v.double_val;
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
@ -376,6 +400,8 @@ value_as_int (ex_value_t *value)
return value->v.integer_val;
if (value->lltype == ev_short)
return value->v.short_val;
if (value->lltype == ev_double)
return value->v.double_val;
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
@ -390,6 +416,8 @@ value_as_uint (ex_value_t *value)
return value->v.integer_val;
if (value->lltype == ev_short)
return value->v.short_val;
if (value->lltype == ev_double)
return value->v.double_val;
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
@ -405,6 +433,9 @@ convert_value (ex_value_t *value, type_t *type)
if (is_float (type)) {
float val = value_as_float (value);
return new_float_val (val);
} else if (is_double (type)) {
double val = value_as_double (value);
return new_double_val (val);
} else if (type->type == ev_short) {
int val = value_as_int (value);
return new_short_val (val);
@ -504,6 +535,10 @@ emit_value (ex_value_t *value, def_t *def)
tab = quaternion_imm_defs;
type = &type_quaternion;
break;
case ev_double:
tab = double_imm_defs;
type = &type_double;
break;
default:
internal_error (0, 0);
}
@ -601,6 +636,7 @@ clear_immediates (void)
Hash_FlushTable (pointer_imm_defs);
Hash_FlushTable (quaternion_imm_defs);
Hash_FlushTable (integer_imm_defs);
Hash_FlushTable (double_imm_defs);
} else {
value_table = Hash_NewTable (16381, 0, 0, 0);
Hash_SetHashCompare (value_table, value_get_hash, value_compare);
@ -634,6 +670,10 @@ clear_immediates (void)
integer_imm_defs =
Hash_NewTable (16381, 0, imm_free, &integer_imm_defs);
Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare);
double_imm_defs =
Hash_NewTable (16381, 0, imm_free, &double_imm_defs);
Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare);
}
def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def;

View file

@ -33,6 +33,7 @@ test_progs_dat=\
chewed-return.dat \
comma-expr.dat \
deadbool.dat \
double.dat \
enum.dat \
fordecl.dat \
func-expr.dat \
@ -111,6 +112,15 @@ deadbool.run: Makefile build-run
include ./$(DEPDIR)/deadbool.Qo # am--include-marker
r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo
double_dat_SOURCES=double.r
double_obj=$(double_dat_SOURCES:.r=.qfo)
double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP)
$(QFCC) $(QCFLAGS) -o $@ $(double_obj)
double.run: Makefile build-run
$(srcdir)/build-run $@
include ./$(DEPDIR)/double.Qo # am--include-marker
r_depfiles_remade += ./$(DEPDIR)/double.Qo
enum_dat_SOURCES=enum.r
enum_obj=$(enum_dat_SOURCES:.r=.qfo)
enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP)

View file

@ -9,7 +9,7 @@ void foo (void)
return;
if (!time) {
ent = spawn ();
ent.f = time + 0.1;
ent.f = time + 0.1f;
}
}

25
tools/qfcc/test/double.r Normal file
View file

@ -0,0 +1,25 @@
void printf (string fmt, ...) = #0;
# define M_PI 3.14159265358979323846
union {
double d;
int i[2];
} type_pun;
int
test_format ()
{
int fail = 0;
type_pun.d = M_PI;
printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]);
//printf ("%08x%08x\n", type_pun.i[1], type_pun.i[0]);
return fail;
}
int
main ()
{
int fail = 0;
fail |= test_format ();
return fail;
}

View file

@ -13,7 +13,7 @@ state0 (void)
[$frame1, state1]
{
if (self.frame != $frame1 || self.think != state1
|| self.nextthink != 0.1) {
|| self.nextthink != 0.1f) {
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
exit (1);
}
@ -21,10 +21,10 @@ state0 (void)
void
state1 (void)
[$frame2, state2, 0.2]
[$frame2, state2, 0.2f]
{
if (self.frame != $frame2 || self.think != state2
|| self.nextthink != 0.2) {
|| self.nextthink != 0.2f) {
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
exit (1);
}
@ -32,10 +32,10 @@ state1 (void)
void
state2 (void)
[$frame0, state0, 0.5]
[$frame0, state0, 0.5f]
{
if (self.frame != $frame0 || self.think != state0
|| self.nextthink != 0.5) {
|| self.nextthink != 0.5f) {
printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink);
exit (1);
}

View file

@ -135,9 +135,13 @@ init_qf (void)
Memory_Init (malloc (1024 * 1024), 1024 * 1024);
Cvar_Get ("pr_debug", "2", 0, 0, 0);
cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0);
Cvar_Get ("pr_boundscheck", "2", 0, 0, 0);
if (options.trace > 1) {
Cvar_SetValue (debug, 4);
}
pr.edicts = &edicts;
pr.num_edicts = &num_edicts;
pr.reserved_edicts = &reserved_edicts;
@ -207,7 +211,7 @@ parse_options (int argc, char **argv)
options.flote = 1;
break;
case 't':
options.trace = 1;
options.trace++;
break;
case 'h':
usage (0);