Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/gdtoa/gethex.c
39475 views
1
/****************************************************************
2
3
The author of this software is David M. Gay.
4
5
Copyright (C) 1998 by Lucent Technologies
6
All Rights Reserved
7
8
Permission to use, copy, modify, and distribute this software and
9
its documentation for any purpose and without fee is hereby
10
granted, provided that the above copyright notice appear in all
11
copies and that both that the copyright notice and this
12
permission notice and warranty disclaimer appear in supporting
13
documentation, and that the name of Lucent or any of its entities
14
not be used in advertising or publicity pertaining to
15
distribution of the software without specific, written prior
16
permission.
17
18
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25
THIS 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
int
39
#ifdef KR_headers
40
gethex(sp, fpi, exp, bp, sign)
41
CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
42
#else
43
gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
44
#endif
45
{
46
Bigint *b;
47
CONST unsigned char *decpt, *s0, *s, *s1;
48
int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
49
ULong L, lostbits, *x;
50
Long e, e1;
51
#ifdef USE_LOCALE
52
int i;
53
#ifdef NO_LOCALE_CACHE
54
const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point;
55
#else
56
const unsigned char *decimalpoint;
57
static unsigned char *decimalpoint_cache;
58
if (!(s0 = decimalpoint_cache)) {
59
s0 = (unsigned char*)localeconv()->decimal_point;
60
if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
61
strcpy(decimalpoint_cache, s0);
62
s0 = decimalpoint_cache;
63
}
64
}
65
decimalpoint = s0;
66
#endif
67
#endif
68
69
if (!hexdig['0'])
70
hexdig_init_D2A();
71
*bp = 0;
72
havedig = 0;
73
s0 = *(CONST unsigned char **)sp + 2;
74
while(s0[havedig] == '0')
75
havedig++;
76
s0 += havedig;
77
s = s0;
78
decpt = 0;
79
zret = 0;
80
e = 0;
81
if (hexdig[*s])
82
havedig++;
83
else {
84
zret = 1;
85
#ifdef USE_LOCALE
86
for(i = 0; decimalpoint[i]; ++i) {
87
if (s[i] != decimalpoint[i])
88
goto pcheck;
89
}
90
decpt = s += i;
91
#else
92
if (*s != '.')
93
goto pcheck;
94
decpt = ++s;
95
#endif
96
if (!hexdig[*s])
97
goto pcheck;
98
while(*s == '0')
99
s++;
100
if (hexdig[*s])
101
zret = 0;
102
havedig = 1;
103
s0 = s;
104
}
105
while(hexdig[*s])
106
s++;
107
#ifdef USE_LOCALE
108
if (*s == *decimalpoint && !decpt) {
109
for(i = 1; decimalpoint[i]; ++i) {
110
if (s[i] != decimalpoint[i])
111
goto pcheck;
112
}
113
decpt = s += i;
114
#else
115
if (*s == '.' && !decpt) {
116
decpt = ++s;
117
#endif
118
while(hexdig[*s])
119
s++;
120
}/*}*/
121
if (decpt)
122
e = -(((Long)(s-decpt)) << 2);
123
pcheck:
124
s1 = s;
125
big = esign = 0;
126
switch(*s) {
127
case 'p':
128
case 'P':
129
switch(*++s) {
130
case '-':
131
esign = 1;
132
/* no break */
133
case '+':
134
s++;
135
}
136
if ((n = hexdig[*s]) == 0 || n > 0x19) {
137
s = s1;
138
break;
139
}
140
e1 = n - 0x10;
141
while((n = hexdig[*++s]) !=0 && n <= 0x19) {
142
if (e1 & 0xf8000000)
143
big = 1;
144
e1 = 10*e1 + n - 0x10;
145
}
146
if (esign)
147
e1 = -e1;
148
e += e1;
149
}
150
*sp = (char*)s;
151
if (!havedig)
152
*sp = (char*)s0 - 1;
153
if (zret)
154
return STRTOG_Zero;
155
if (big) {
156
if (esign) {
157
switch(fpi->rounding) {
158
case FPI_Round_up:
159
if (sign)
160
break;
161
goto ret_tiny;
162
case FPI_Round_down:
163
if (!sign)
164
break;
165
goto ret_tiny;
166
}
167
goto retz;
168
ret_tiny:
169
b = Balloc(0);
170
b->wds = 1;
171
b->x[0] = 1;
172
goto dret;
173
}
174
switch(fpi->rounding) {
175
case FPI_Round_near:
176
goto ovfl1;
177
case FPI_Round_up:
178
if (!sign)
179
goto ovfl1;
180
goto ret_big;
181
case FPI_Round_down:
182
if (sign)
183
goto ovfl1;
184
goto ret_big;
185
}
186
ret_big:
187
nbits = fpi->nbits;
188
n0 = n = nbits >> kshift;
189
if (nbits & kmask)
190
++n;
191
for(j = n, k = 0; j >>= 1; ++k);
192
*bp = b = Balloc(k);
193
b->wds = n;
194
for(j = 0; j < n0; ++j)
195
b->x[j] = ALL_ON;
196
if (n > n0)
197
b->x[j] = ULbits >> (ULbits - (nbits & kmask));
198
*exp = fpi->emin;
199
return STRTOG_Normal | STRTOG_Inexlo;
200
}
201
n = s1 - s0 - 1;
202
for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
203
k++;
204
b = Balloc(k);
205
x = b->x;
206
n = 0;
207
L = 0;
208
#ifdef USE_LOCALE
209
for(i = 0; decimalpoint[i+1]; ++i);
210
#endif
211
while(s1 > s0) {
212
#ifdef USE_LOCALE
213
if (*--s1 == decimalpoint[i]) {
214
s1 -= i;
215
continue;
216
}
217
#else
218
if (*--s1 == '.')
219
continue;
220
#endif
221
if (n == ULbits) {
222
*x++ = L;
223
L = 0;
224
n = 0;
225
}
226
L |= (hexdig[*s1] & 0x0f) << n;
227
n += 4;
228
}
229
*x++ = L;
230
b->wds = n = x - b->x;
231
n = ULbits*n - hi0bits(L);
232
nbits = fpi->nbits;
233
lostbits = 0;
234
x = b->x;
235
if (n > nbits) {
236
n -= nbits;
237
if (any_on(b,n)) {
238
lostbits = 1;
239
k = n - 1;
240
if (x[k>>kshift] & 1 << (k & kmask)) {
241
lostbits = 2;
242
if (k > 0 && any_on(b,k))
243
lostbits = 3;
244
}
245
}
246
rshift(b, n);
247
e += n;
248
}
249
else if (n < nbits) {
250
n = nbits - n;
251
b = lshift(b, n);
252
e -= n;
253
x = b->x;
254
}
255
if (e > fpi->emax) {
256
ovfl:
257
Bfree(b);
258
ovfl1:
259
#ifndef NO_ERRNO
260
errno = ERANGE;
261
#endif
262
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
263
}
264
irv = STRTOG_Normal;
265
if (e < fpi->emin) {
266
irv = STRTOG_Denormal;
267
n = fpi->emin - e;
268
if (n >= nbits) {
269
switch (fpi->rounding) {
270
case FPI_Round_near:
271
if (n == nbits && (n < 2 || any_on(b,n-1)))
272
goto one_bit;
273
break;
274
case FPI_Round_up:
275
if (!sign)
276
goto one_bit;
277
break;
278
case FPI_Round_down:
279
if (sign) {
280
one_bit:
281
x[0] = b->wds = 1;
282
dret:
283
*bp = b;
284
*exp = fpi->emin;
285
#ifndef NO_ERRNO
286
errno = ERANGE;
287
#endif
288
return STRTOG_Denormal | STRTOG_Inexhi
289
| STRTOG_Underflow;
290
}
291
}
292
Bfree(b);
293
retz:
294
#ifndef NO_ERRNO
295
errno = ERANGE;
296
#endif
297
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
298
}
299
k = n - 1;
300
if (lostbits)
301
lostbits = 1;
302
else if (k > 0)
303
lostbits = any_on(b,k);
304
if (x[k>>kshift] & 1 << (k & kmask))
305
lostbits |= 2;
306
nbits -= n;
307
rshift(b,n);
308
e = fpi->emin;
309
}
310
if (lostbits) {
311
up = 0;
312
switch(fpi->rounding) {
313
case FPI_Round_zero:
314
break;
315
case FPI_Round_near:
316
if (lostbits & 2
317
&& (lostbits | x[0]) & 1)
318
up = 1;
319
break;
320
case FPI_Round_up:
321
up = 1 - sign;
322
break;
323
case FPI_Round_down:
324
up = sign;
325
}
326
if (up) {
327
k = b->wds;
328
b = increment(b);
329
x = b->x;
330
if (irv == STRTOG_Denormal) {
331
if (nbits == fpi->nbits - 1
332
&& x[nbits >> kshift] & 1 << (nbits & kmask))
333
irv = STRTOG_Normal;
334
}
335
else if (b->wds > k
336
|| ((n = nbits & kmask) !=0
337
&& hi0bits(x[k-1]) < 32-n)) {
338
rshift(b,1);
339
if (++e > fpi->emax)
340
goto ovfl;
341
}
342
irv |= STRTOG_Inexhi;
343
}
344
else
345
irv |= STRTOG_Inexlo;
346
}
347
*bp = b;
348
*exp = e;
349
return irv;
350
}
351
352