ack/lang/cem/cemcom.ansi/fltcstoper.c

114 lines
2.4 KiB
C

/*
* (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */
/* F O R F L O A T I N G P O I N T N U M B E R S */
#include "debug.h"
#include "assert.h"
#include <alloc.h>
#include "trgt_sizes.h"
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "label.h"
#include "expr.h"
#include "sizes.h"
#include "Lpars.h"
extern int ResultKnown;
extern char *symbol2str();
fltcstbin(expp, oper, expr)
register struct expr **expp, *expr;
{
/* The operation oper is performed on the constant
expressions *expp(ld) and expr(ct), and the result restored in
*expp.
*/
flt_arith o1, o2;
int compar = 0;
int cmpval = 0;
o1 = (*expp)->FL_ARITH;
o2 = expr->FL_ARITH;
ASSERT(is_fp_cst(*expp) && is_fp_cst(expr));
switch (oper) {
case '*':
flt_mul(&o1, &o2, &o1);
break;
case '/':
flt_div(&o1, &o2, &o1);
break;
case '+':
flt_add(&o1, &o2, &o1);
break;
case '-':
flt_sub(&o1, &o2, &o1);
break;
case '<':
case '>':
case LESSEQ:
case GREATEREQ:
case EQUAL:
case NOTEQUAL:
compar++;
cmpval = flt_cmp(&o1, &o2);
switch(oper) {
case '<': cmpval = (cmpval < 0); break;
case '>': cmpval = (cmpval > 0); break;
case LESSEQ: cmpval = (cmpval <= 0); break;
case GREATEREQ: cmpval = (cmpval >= 0); break;
case EQUAL: cmpval = (cmpval == 0); break;
case NOTEQUAL: cmpval = (cmpval != 0); break;
}
break;
case '%':
case LEFT:
case RIGHT:
case '&':
case '|':
case '^':
/*
expr_error(*expp, "floating operand for %s", symbol2str(oper));
break;
*/
default:
crash("(fltcstoper) bad operator %s", symbol2str(oper));
/*NOTREACHED*/
}
switch (flt_status) {
case 0:
case FLT_UNFL:
break;
case FLT_OVFL:
if (!ResultKnown)
expr_warning(expr,"floating point overflow on %s"
, symbol2str(oper));
break;
case FLT_DIV0:
if (!ResultKnown)
expr_error(expr,"division by 0.0");
else
expr_warning(expr,"division by 0.0");
break;
default: /* there can't be another status */
crash("(fltcstoper) bad status");
}
if ((*expp)->FL_VALUE) free((*expp)->FL_VALUE);
(*expp)->FL_VALUE = 0;
if (compar) {
fill_int_expr(*expp, (arith)cmpval, INT);
} else {
(*expp)->FL_ARITH = o1;
}
(*expp)->ex_flags |= expr->ex_flags;
(*expp)->ex_flags &= ~EX_PARENS;
free_expression(expr);
}