rust: Implement TARGET_RUST_OS_INFO for *-*-freebsd*
[official-gcc.git] / libgm2 / libm2pim / dtoa.cc
blob509027d778d973c1975d75c4d1a91990f71d2cca
1 /* dtoa.cc convert double to ascii and visa versa.
3 Copyright (C) 2009-2022 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
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.
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.
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.
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/>. */
27 #define GM2
29 #include <config.h>
30 #include <m2rts.h>
32 #define EXPORT(FUNC) m2pim ## _dtoa_ ## FUNC
33 #define M2EXPORT(FUNC) m2pim ## _M2_dtoa_ ## FUNC
34 #define M2LIBNAME "m2pim"
36 #if defined(HAVE_STRINGS)
37 #include <strings.h>
38 #endif
40 #if defined(HAVE_STRING)
41 #include <string.h>
42 #endif
44 #if defined(HAVE_STDDEF_H)
45 /* Obtain a definition for NULL. */
46 #include <stddef.h>
47 #endif
49 #if defined(HAVE_STDIO_H)
50 /* Obtain a definition for NULL. */
51 #include <stdio.h>
52 #endif
54 #if defined(HAVE_TIME_H)
55 /* Obtain a definition for NULL. */
56 #include <time.h>
57 #endif
59 #if defined(HAVE_STRING_H)
60 /* Obtain a definition for NULL. */
61 #include <string.h>
62 #endif
64 #if defined(HAVE_WCHAR_H)
65 /* Obtain a definition for NULL. */
66 #include <wchar.h>
67 #endif
69 #if defined(HAVE_STDLIB_H)
70 /* Obtain a prototype for free and malloc. */
71 #include <stdlib.h>
72 #endif
74 #if !defined(NULL)
75 #define NULL (void *)0
76 #endif
78 #if defined(HAVE_STDLIB_H)
79 #if !defined(_ISOC99_SOURCE)
80 #define _ISOC99_SOURCE
81 #endif
82 #include <stdlib.h>
83 #endif
85 #if defined(HAVE_ERRNO_H)
86 #include <errno.h>
87 #endif
89 #if defined(HAVE_SYS_ERRNO_H)
90 #include <sys/errno.h>
91 #endif
93 #if defined(HAVE_STRING_H)
95 #define MAX_FP_DIGITS 500
97 typedef enum Mode { maxsignicant, decimaldigits } Mode;
99 /* maxsignicant: return a string containing max(1,ndigits) significant
100 digits. The return string contains the string produced by ecvt.
102 decimaldigits: return a string produced by fcvt. The string will
103 contain ndigits past the decimal point (ndigits may be negative). */
105 extern "C" double
106 EXPORT(strtod) (const char *s, bool *error)
108 char *endp;
109 double d;
111 #if defined(HAVE_ERRNO_H)
112 errno = 0;
113 #endif
114 d = strtod (s, &endp);
115 if (endp != NULL && (*endp == '\0'))
116 #if defined(HAVE_ERRNO_H)
117 *error = (errno != 0);
118 #else
119 *error = false;
120 #endif
121 else
122 *error = true;
123 return d;
126 /* dtoa_calcmaxsig calculates the position of the decimal point
127 it also removes the decimal point and exponent from string, p. */
129 extern "C" int
130 EXPORT(calcmaxsig) (char *p, int ndigits)
132 char *e;
133 char *o;
134 int x;
136 e = strchr (p, 'E');
137 if (e == NULL)
138 x = 0;
139 else
141 *e = (char)0;
142 x = atoi (e + 1);
145 o = strchr (p, '.');
146 if (o == NULL)
147 return strlen (p) + x;
148 else
150 memmove (o, o + 1, ndigits - (o - p));
151 return o - p + x;
155 /* dtoa_calcdecimal calculates the position of the decimal point
156 it also removes the decimal point and exponent from string, p.
157 It truncates the digits in p accordingly to ndigits.
158 Ie ndigits is the number of digits after the '.'. */
160 extern "C" int
161 EXPORT(calcdecimal) (char *p, int str_size, int ndigits)
163 char *e;
164 char *o;
165 int x;
166 int l;
168 e = strchr (p, 'E');
169 if (e == NULL)
170 x = 0;
171 else
173 *e = (char)0;
174 x = atoi (e + 1);
177 l = strlen (p);
178 o = strchr (p, '.');
179 if (o == NULL)
180 x += strlen (p);
181 else
183 int m = strlen (o);
184 memmove (o, o + 1, l - (o - p));
185 if (m > 0)
186 o[m - 1] = '0';
187 x += o - p;
189 if ((x + ndigits >= 0) && (x + ndigits < str_size))
190 p[x + ndigits] = (char)0;
191 return x;
194 extern "C" bool
195 EXPORT(calcsign) (char *p, int str_size)
197 if (p[0] == '-')
199 memmove (p, p + 1, str_size - 1);
200 return true;
202 else
203 return false;
206 extern "C" char *
207 EXPORT(dtoa) (double d, int mode, int ndigits, int *decpt, bool *sign)
209 char format[50];
210 char *p;
211 int r;
212 switch (mode)
215 case maxsignicant:
216 ndigits += 20; /* Enough for exponent. */
217 p = (char *) malloc (ndigits);
218 snprintf (format, 50, "%s%d%s", "%.", ndigits - 20, "E");
219 snprintf (p, ndigits, format, d);
220 *sign = EXPORT(calcsign) (p, ndigits);
221 *decpt = EXPORT(calcmaxsig) (p, ndigits);
222 return p;
223 case decimaldigits:
224 p = (char *) malloc (MAX_FP_DIGITS + 20);
225 snprintf (format, 50, "%s%d%s", "%.", MAX_FP_DIGITS, "E");
226 snprintf (p, MAX_FP_DIGITS + 20, format, d);
227 *sign = EXPORT(calcsign) (p, MAX_FP_DIGITS + 20);
228 *decpt = EXPORT(calcdecimal) (p, MAX_FP_DIGITS + 20, ndigits);
229 return p;
230 default:
231 abort ();
235 #endif
237 #if defined(GM2)
238 /* GNU Modula-2 linking hooks. */
240 extern "C" void
241 M2EXPORT(init) (int, char **, char **)
245 extern "C" void
246 M2EXPORT(fini) (int, char **, char **)
250 extern "C" void
251 M2EXPORT(dep) (void)
255 extern "C" void __attribute__((__constructor__))
256 M2EXPORT(ctor) (void)
258 m2pim_M2RTS_RegisterModule ("dtoa", M2LIBNAME,
259 M2EXPORT(init), M2EXPORT(fini),
260 M2EXPORT(dep));
262 #endif