Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / fltcstoper.c
1 /*
2  * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: fltcstoper.c,v 1.7 1994/06/27 08:00:02 ceriel Exp $ */
6 /*      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         */
7 /*        F O R   F L O A T I N G   P O I N T   N U M B E R S           */
8
9 #include        "debug.h"
10 #include        "assert.h"
11 #include        <alloc.h>
12 #include        "trgt_sizes.h"
13 #include        "idf.h"
14 #include        <flt_arith.h>
15 #include        "arith.h"
16 #include        "type.h"
17 #include        "label.h"
18 #include        "expr.h"
19 #include        "sizes.h"
20 #include        "Lpars.h"
21
22 extern int ResultKnown;
23 extern char *symbol2str();
24
25 fltcstbin(expp, oper, expr)
26         register struct expr **expp, *expr;
27 {
28         /*      The operation oper is performed on the constant
29                 expressions *expp(ld) and expr(ct), and the result restored in
30                 *expp.
31         */
32         flt_arith o1, o2;
33         int compar = 0;
34         int cmpval = 0;
35
36         o1 = (*expp)->FL_ARITH;
37         o2 = expr->FL_ARITH;
38
39         ASSERT(is_fp_cst(*expp) && is_fp_cst(expr));
40         switch (oper)   {
41         case '*':
42                 flt_mul(&o1, &o2, &o1);
43                 break;
44         case '/':
45                 flt_div(&o1, &o2, &o1);
46                 break;
47         case '+':
48                 flt_add(&o1, &o2, &o1);
49                 break;
50         case '-':
51                 flt_sub(&o1, &o2, &o1);
52                 break;
53         case '<':
54         case '>':
55         case LESSEQ:
56         case GREATEREQ:
57         case EQUAL:
58         case NOTEQUAL:
59                 compar++;
60                 cmpval = flt_cmp(&o1, &o2);
61                 switch(oper) {
62                 case '<':       cmpval = (cmpval < 0);  break;
63                 case '>':       cmpval = (cmpval > 0);  break;
64                 case LESSEQ:    cmpval = (cmpval <= 0); break;
65                 case GREATEREQ: cmpval = (cmpval >= 0); break;
66                 case EQUAL:     cmpval = (cmpval == 0); break;
67                 case NOTEQUAL:  cmpval = (cmpval != 0); break;
68                 }
69                 break;
70         default:
71                 /* in case of situations like a += 3.0; where a undefined */
72                 flt_status = 0;
73                 break;
74         }
75
76         switch (flt_status) {
77                 case 0:
78                 case FLT_UNFL:                  /* ignore underflow */
79                         break;
80                 case FLT_OVFL:
81                         if (!ResultKnown)
82                             expr_warning(expr,"floating point overflow on %s"
83                                         , symbol2str(oper));
84                         break;
85                 case FLT_DIV0:
86                         if (!ResultKnown)
87                                 expr_error(expr,"division by 0.0");
88                         else
89                                 expr_warning(expr,"division by 0.0");
90                         break;
91                 default:        /* there can't be another status */
92                         crash("(fltcstoper) bad status");
93         }
94         if (compar) {
95                 fill_int_expr(*expp, (arith)cmpval, INT);
96         } else {
97                 (*expp)->FL_ARITH = o1;
98         }
99         (*expp)->ex_flags |= expr->ex_flags;
100         (*expp)->ex_flags &= ~EX_PARENS;
101         free_expression(expr);
102 }