]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/gm2-libs-ch/ldtoa.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / gm2-libs-ch / ldtoa.cc
1 /* ldtoa.c provide long double 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 extern int dtoa_calcmaxsig (char *p, int ndigits);
43 extern int dtoa_calcdecimal (char *p, int str_size, int ndigits);
44 extern int dtoa_calcsign (char *p, int str_size);
45
46 /* maxsignicant: return a string containing max(1,ndigits)
47 significant digits. The return string contains the string
48 produced by snprintf. decimaldigits: return a string produced by
49 fcvt. The string will contain ndigits past the decimal point
50 (ndigits may be negative). */
51
52 long double
53 ldtoa_strtold (const char *s, int *error)
54 {
55 char *endp;
56 long double d;
57
58 errno = 0;
59 #if defined(HAVE_STRTOLD)
60 d = strtold (s, &endp);
61 #else
62 /* fall back to using strtod. */
63 d = (long double)strtod (s, &endp);
64 #endif
65 if (endp != NULL && (*endp == '\0'))
66 *error = (errno != 0);
67 else
68 *error = TRUE;
69 return d;
70 }
71
72 char *
73 ldtoa_ldtoa (long double d, int mode, int ndigits, int *decpt, int *sign)
74 {
75 char format[50];
76 char *p;
77 int r;
78 switch (mode)
79 {
80
81 case maxsignicant:
82 ndigits += 20; /* enough for exponent. */
83 p = (char *) malloc (ndigits);
84 snprintf (format, 50, "%s%d%s", "%.", ndigits - 20, "LE");
85 snprintf (p, ndigits, format, d);
86 *sign = dtoa_calcsign (p, ndigits);
87 *decpt = dtoa_calcmaxsig (p, ndigits);
88 return p;
89 case decimaldigits:
90 p = (char *) malloc (MAX_FP_DIGITS + 20);
91 snprintf (format, 50, "%s%d%s", "%.", MAX_FP_DIGITS, "LE");
92 snprintf (p, MAX_FP_DIGITS + 20, format, d);
93 *sign = dtoa_calcsign (p, MAX_FP_DIGITS + 20);
94 *decpt = dtoa_calcdecimal (p, MAX_FP_DIGITS + 20, ndigits);
95 return p;
96 default:
97 abort ();
98 }
99 }
100
101 /* GNU Modula-2 hooks */
102
103 void
104 _M2_ldtoa_init (int, char **, char **)
105 {
106 }
107
108 void
109 _M2_ldtoa_finish (int, char **, char **)
110 {
111 }
112
113 void
114 _M2_ldtoa_dep (void)
115 {
116 }
117
118 # ifdef __cplusplus
119 }
120
121 extern "C" void __attribute__((__constructor__))
122 _M2_ldtoa_ctor (void)
123 {
124 M2RTS_RegisterModule ("ldtoa", _M2_ldtoa_init, _M2_ldtoa_finish,
125 _M2_ldtoa_dep);
126 }
127
128 #else
129 void
130 _M2_ldtoa_ctor (void)
131 {
132 }
133
134 # endif