]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/gm2-libs-ch/dtoa.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / gm2-libs-ch / dtoa.cc
1 /* dtoa.c provide floating point string conversion routines.
2
3 Copyright (C) 2009-2023 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
5
6 This file is part of GNU Modula-2.
7
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
26
27 #include "config.h"
28 #include "system.h"
29 #include "ansidecl.h"
30
31 #include "gm2-libs-host.h"
32 #include "m2rts.h"
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 #define MAX_FP_DIGITS 500
39
40 typedef enum Mode { maxsignicant, decimaldigits } Mode;
41
42 /* maxsignicant: return a string containing max(1,ndigits)
43 significant digits. The return string contains the string
44 produced by ecvt. decimaldigits: return a string produced by
45 fcvt. The string will contain ndigits past the decimal point
46 (ndigits may be negative). */
47
48 double
49 dtoa_strtod (const char *s, int *error)
50 {
51 char *endp;
52 double d;
53
54 errno = 0;
55 d = strtod (s, &endp);
56 if (endp != NULL && (*endp == '\0'))
57 *error = (errno != 0);
58 else
59 *error = TRUE;
60 return d;
61 }
62
63 /* dtoa_calcmaxsig - calculates the position of the decimal point it
64 also removes the decimal point and exponent from string, p. */
65
66 int
67 dtoa_calcmaxsig (char *p, int ndigits)
68 {
69 char *e;
70 char *o;
71 int x;
72
73 e = index (p, 'E');
74 if (e == NULL)
75 x = 0;
76 else
77 {
78 *e = (char)0;
79 x = atoi (e + 1);
80 }
81
82 o = index (p, '.');
83 if (o == NULL)
84 return strlen (p) + x;
85 else
86 {
87 memmove (o, o + 1, ndigits - (o - p));
88 return o - p + x;
89 }
90 }
91
92 /* dtoa_calcdecimal - calculates the position of the decimal point it
93 also removes the decimal point and exponent from string, p. It
94 truncates the digits in p accordingly to ndigits. Ie ndigits is
95 the number of digits after the '.' */
96
97 int
98 dtoa_calcdecimal (char *p, int str_size, int ndigits)
99 {
100 char *e;
101 char *o;
102 int x;
103 int l;
104
105 e = index (p, 'E');
106 if (e == NULL)
107 x = 0;
108 else
109 {
110 *e = (char)0;
111 x = atoi (e + 1);
112 }
113
114 l = strlen (p);
115 o = index (p, '.');
116 if (o == NULL)
117 x += strlen (p);
118 else
119 {
120 int m = strlen (o);
121 memmove (o, o + 1, l - (o - p));
122 if (m > 0)
123 o[m - 1] = '0';
124 x += o - p;
125 }
126 if ((x + ndigits >= 0) && (x + ndigits < str_size))
127 p[x + ndigits] = (char)0;
128 return x;
129 }
130
131 int
132 dtoa_calcsign (char *p, int str_size)
133 {
134 if (p[0] == '-')
135 {
136 memmove (p, p + 1, str_size - 1);
137 return TRUE;
138 }
139 else
140 return FALSE;
141 }
142
143 char *
144 dtoa_dtoa (double d, int mode, int ndigits, int *decpt, int *sign)
145 {
146 char format[50];
147 char *p;
148 int r;
149 switch (mode)
150 {
151
152 case maxsignicant:
153 ndigits += 20; /* enough for exponent. */
154 p = (char *) malloc (ndigits);
155 snprintf (format, 50, "%s%d%s", "%.", ndigits - 20, "E");
156 snprintf (p, ndigits, format, d);
157 *sign = dtoa_calcsign (p, ndigits);
158 *decpt = dtoa_calcmaxsig (p, ndigits);
159 return p;
160 case decimaldigits:
161 p = (char *) malloc (MAX_FP_DIGITS + 20);
162 snprintf (format, 50, "%s%d%s", "%.", MAX_FP_DIGITS, "E");
163 snprintf (p, MAX_FP_DIGITS + 20, format, d);
164 *sign = dtoa_calcsign (p, MAX_FP_DIGITS + 20);
165 *decpt = dtoa_calcdecimal (p, MAX_FP_DIGITS + 20, ndigits);
166 return p;
167 default:
168 abort ();
169 }
170 }
171
172 /* GNU Modula-2 hooks */
173
174 void
175 _M2_dtoa_init (int, char **, char **)
176 {
177 }
178
179 void
180 _M2_dtoa_finish (int, char **, char **)
181 {
182 }
183
184 void
185 _M2_dtoa_dep (void)
186 {
187 }
188
189 #ifdef __cplusplus
190 }
191
192 extern "C" void __attribute__((__constructor__))
193 _M2_dtoa_ctor (void)
194 {
195 M2RTS_RegisterModule ("dtoa", _M2_dtoa_init, _M2_dtoa_finish,
196 _M2_dtoa_dep);
197 }
198
199 #else
200 void
201 _M2_dtoa_ctor (void)
202 {
203 }
204
205 #endif