master
1/****************************************************************
2
3The author of this software is David M. Gay.
4
5Copyright (C) 1998 by Lucent Technologies
6All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and
9its documentation for any purpose and without fee is hereby
10granted, provided that the above copyright notice appear in all
11copies and that both that the copyright notice and this
12permission notice and warranty disclaimer appear in supporting
13documentation, and that the name of Lucent or any of its entities
14not be used in advertising or publicity pertaining to
15distribution of the software without specific, written prior
16permission.
17
18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25THIS SOFTWARE.
26
27****************************************************************/
28
29/* Please send bug reports to David M. Gay (dmg at acm dot org,
30 * with " at " changed at "@" and " dot " changed to "."). */
31
32#include "gdtoaimp.h"
33
34#ifdef USE_LOCALE
35#include "locale.h"
36#endif
37
38#ifndef ldus_QNAN0
39#define ldus_QNAN0 0x7fff
40#endif
41#ifndef ldus_QNAN1
42#define ldus_QNAN1 0xc000
43#endif
44#ifndef ldus_QNAN2
45#define ldus_QNAN2 0
46#endif
47#ifndef ldus_QNAN3
48#define ldus_QNAN3 0
49#endif
50#ifndef ldus_QNAN4
51#define ldus_QNAN4 0
52#endif
53
54 const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" };
55 const char *NanName[3] = { "NaN", "nan", "NAN" };
56 ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff };
57 ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 };
58 ULong NanDflt_f_D2A[1] = { f_QNAN };
59 ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 };
60 UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 };
61
62char *__g__fmt (char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
63{
64 int i, j, k;
65 char *be, *s0;
66 size_t len;
67#ifdef USE_LOCALE
68#ifdef NO_LOCALE_CACHE
69 char *decimalpoint = localeconv()->decimal_point;
70 size_t dlen = strlen(decimalpoint);
71#else
72 char *decimalpoint;
73 static char *decimalpoint_cache;
74 static size_t dlen;
75 if (!(s0 = decimalpoint_cache)) {
76 s0 = localeconv()->decimal_point;
77 dlen = strlen(s0);
78 if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
79 strcpy(decimalpoint_cache, s0);
80 s0 = decimalpoint_cache;
81 }
82 }
83 decimalpoint = s0;
84#endif
85#else
86#define dlen 0
87#endif
88 s0 = s;
89 len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */
90 if (blen < len)
91 goto ret0;
92 be = b + blen - 1;
93 if (sign)
94 *b++ = '-';
95 if (decpt <= -4 || decpt > se - s + 5) {
96 *b++ = *s++;
97 if (*s) {
98#ifdef USE_LOCALE
99 while((*b = *decimalpoint++))
100 ++b;
101#else
102 *b++ = '.';
103#endif
104 while((*b = *s++) !=0)
105 b++;
106 }
107 *b++ = 'e';
108 /* sprintf(b, "%+.2d", decpt - 1); */
109 if (--decpt < 0) {
110 *b++ = '-';
111 decpt = -decpt;
112 }
113 else
114 *b++ = '+';
115 for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
116 for(;;) {
117 i = decpt / k;
118 if (b >= be)
119 goto ret0;
120 *b++ = i + '0';
121 if (--j <= 0)
122 break;
123 decpt -= i*k;
124 decpt *= 10;
125 }
126 *b = 0;
127 }
128 else if (decpt <= 0) {
129#ifdef USE_LOCALE
130 while((*b = *decimalpoint++))
131 ++b;
132#else
133 *b++ = '.';
134#endif
135 if (be < b - decpt + (se - s))
136 goto ret0;
137 for(; decpt < 0; decpt++)
138 *b++ = '0';
139 while((*b = *s++) != 0)
140 b++;
141 }
142 else {
143 while((*b = *s++) != 0) {
144 b++;
145 if (--decpt == 0 && *s) {
146#ifdef USE_LOCALE
147 while((*b = *decimalpoint++))
148 ++b;
149#else
150 *b++ = '.';
151#endif
152 }
153 }
154 if (b + decpt > be) {
155 ret0:
156 b = 0;
157 goto ret;
158 }
159 for(; decpt > 0; decpt--)
160 *b++ = '0';
161 *b = 0;
162 }
163 ret:
164 __freedtoa(s0);
165 return b;
166}
167
168 char *
169__add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb)
170{
171 ULong t;
172 char *rv;
173 int i, j;
174 size_t L;
175 static char Hexdig[16] = "0123456789abcdef";
176
177 while(!bits[--nb])
178 if (!nb)
179 return b;
180 L = 8*nb + 3;
181 t = bits[nb];
182 do ++L; while((t >>= 4));
183 if (L > blen)
184 return b;
185 b += L;
186 *--b = 0;
187 rv = b;
188 *--b = /*(*/ ')';
189 for(i = 0; i < nb; ++i) {
190 t = bits[i];
191 for(j = 0; j < 8; ++j, t >>= 4)
192 *--b = Hexdig[t & 0xf];
193 }
194 t = bits[nb];
195 do *--b = Hexdig[t & 0xf]; while(t >>= 4);
196 *--b = '('; /*)*/
197 return rv;
198 }