modify upstream makefile to allow hardening build flags to apply
[debian/yforth] / float.c
1 /* yForth? - A Forth interpreter written in ANSI C
2  * Copyright (C) 2012 Luca Padovani
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  * ------------------------------------------------------------------------
17  * Module name:     float.c
18  * Abstract:        floating word set
19  */
20
21 #include <math.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include "yforth.h"
27 #include "core.h"
28 #include "float.h"
29
30 /**************************************************************************/
31 /* WORDS ******************************************************************/
32 /**************************************************************************/
33
34 void _to_float() {
35         register Cell len = *sp++;
36         register Char *s = (Char *) *sp;
37         extern Char *s_tmp_buffer[];
38         Char *endptr;
39         memcpy(s_tmp_buffer, s, len);
40         if (toupper(s[len - 1]) == 'E' || toupper(s[len - 1]) == 'D') s[len++] = '0'; 
41         s[len] = '\0';
42         *--fp = (Real) strtod(s, &endptr);
43         if (!*endptr) *sp = FFLAG(1);
44         else {
45                 *sp = FFLAG(0);
46                 fp++;
47         }
48 }
49
50 void _d_to_f() {
51         register DCell d = GET_DCELL(sp);
52         *--fp = (Real) d;
53         sp += 2;
54 }
55
56 void _f_store() {
57         register Real *addr = (Real *) *sp++;
58         *addr = *fp++;
59 }
60
61 void _f_star() {
62         fp[1] *= fp[0];
63         fp++;
64 }
65
66 void _f_plus() {
67         fp[1] += fp[0];
68         fp++;
69 }
70
71 void _f_minus() {
72         fp[1] -= fp[0];
73         fp++;
74 }
75
76 void _f_slash() {
77         fp[1] /= fp[0];
78         fp++;
79 }
80
81 void _f_zero_less() {
82         sp--;
83         *sp = FFLAG(*fp < 0.0);
84         fp++;
85 }
86
87 void _f_zero_equals() {
88         sp--;
89         *sp = FFLAG(*fp == 0.0);
90         fp++;
91 }
92
93 void _f_less_than() {
94         sp--;
95         *sp = FFLAG(fp[1] < fp[0]);
96         fp += 2;
97 }
98
99 void _f_to_d() {
100         register DCell d = (DCell) *fp++;
101         sp -= 2;
102         PUT_DCELL(sp, d);
103 }
104
105 void _f_fetch() {
106         *--fp = *((Real *) *sp++);
107 }
108
109 void _f_constant() {
110         register Real r = *fp++;
111         create_definition(A_FCONSTANT);
112         compile_real(r);
113         mark_word(_last);
114 }
115
116 void _f_depth() {
117         *--sp = fp_top - fp;
118 }
119
120 void _f_drop() {
121         fp++;
122 }
123
124 void _f_dupe() {
125         fp--;
126         fp[0] = fp[1];
127 }
128
129 void _f_literal() {
130         compile_cell((Cell) _do_fliteral);
131         compile_real(fp[0]);
132         fp++;
133 }
134
135 void _float_plus() {
136         sp[0] += sizeof(Real);
137 }
138
139 void _floats() {
140         sp[0] *= sizeof(Real);
141 }
142
143 void _floor() {
144         fp[0] = floor(fp[0]);
145 }
146
147 void _f_max() {
148         if (fp[0] > fp[1]) fp[1] = fp[0];
149         fp++;
150 }
151
152 void _f_min() {
153         if (fp[0] < fp[1]) fp[1] = fp[0];
154         fp++;
155 }
156
157 void _f_negate() {
158         fp[0] = -fp[0];
159 }
160
161 void _f_over() {
162         fp--;
163         fp[0] = fp[2];
164 }
165
166 void _f_rote() {
167         register Real temp = fp[0];
168         fp[0] = fp[2];
169         fp[2] = fp[1];
170         fp[1] = temp;
171 }
172
173 void _f_round() {
174         fp[0] = floor(fp[0] + 0.5);
175 }
176
177 void _f_swap() {
178         register Real temp = fp[0];
179         fp[0] = fp[1];
180         fp[1] = temp;
181 }
182
183 void _f_variable() {
184         create_definition(A_FVARIABLE);
185         compile_real(0.0);
186         mark_word(_last);
187 }
188
189 void _represent() {
190     register Real x = *fp++;
191     register int m;
192     register int sign = 0;
193     static char buf[128];
194     if (x < 0.0) {
195         sign = 1;
196         x = -x;
197     }
198     if (x != 0.0) {
199         m = (int) floor(log10(x)) + 1;
200         x /= pow(10, m);
201         if (x >= 1.0) {
202             x /= 10;
203             m++;
204         }
205     } else m = 0;
206     sprintf(buf, "%0.*f", sp[0], x);
207     strncpy((Char *) sp[1], buf + 2, sp[0]);
208     sp--;
209     sp[2] = m;
210     sp[1] = FFLAG(sign);
211         sp[0] = FFLAG(1);
212 }
213