Embedded Artistry libc
C Standard Library Support for Bare-metal Systems
gethex.c
Go to the documentation of this file.
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) CONST char** sp;
41 FPI* fpi;
42 Long* exp;
43 Bigint** bp;
44 int sign;
45 #else
46 gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
47 #endif
48 {
49  Bigint* b;
50  CONST unsigned char *decpt, *s0, *s, *s1;
51  int esign, havedig, irv, k, n, nbits, up, zret;
52  ULong L, lostbits, *x;
53  Long e, e1;
54 #ifdef USE_LOCALE
55  unsigned char decimalpoint = *localeconv()->decimal_point;
56 #else
57 #define decimalpoint '.'
58 #endif
59 
60  if(!hexdig['0'])
61  {
62  {
64  }
65  }
66  havedig = 0;
67  s0 = *(CONST unsigned char**)sp + 2;
68  while(s0[havedig] == '0')
69  {
70  {
71  havedig++;
72  }
73  }
74  s0 += havedig;
75  s = s0;
76  decpt = 0;
77  zret = 0;
78  e = 0;
79  if(!hexdig[*s])
80  {
81  zret = 1;
82  if(*s != decimalpoint)
83  {
84  {
85  goto pcheck;
86  }
87  }
88  decpt = ++s;
89  if(!hexdig[*s])
90  {
91  {
92  goto pcheck;
93  }
94  }
95  while(*s == '0')
96  {
97  {
98  s++;
99  }
100  }
101  if(hexdig[*s])
102  {
103  {
104  zret = 0;
105  }
106  }
107  havedig = 1;
108  s0 = s;
109  }
110  while(hexdig[*s])
111  {
112  {
113  s++;
114  }
115  }
116  if(*s == decimalpoint && !decpt)
117  {
118  decpt = ++s;
119  while(hexdig[*s])
120  {
121  {
122  s++;
123  }
124  }
125  }
126  if(decpt)
127  {
128  {
129  e = -(((Long)(s - decpt)) << 2);
130  }
131  }
132 pcheck:
133  s1 = s;
134  switch(*s)
135  {
136  case 'p':
137  case 'P':
138  esign = 0;
139  switch(*++s)
140  {
141  case '-':
142  esign = 1;
143  /* no break */
144  case '+':
145  s++;
146  }
147  if((n = hexdig[*s]) == 0 || n > 0x19)
148  {
149  s = s1;
150  break;
151  }
152  e1 = n - 0x10;
153  while((n = hexdig[*++s]) != 0 && n <= 0x19)
154  {
155  {
156  e1 = 10 * e1 + n - 0x10;
157  }
158  }
159  if(esign)
160  {
161  {
162  e1 = -e1;
163  }
164  }
165  e += e1;
166  }
167  *sp = (const char*)s;
168  if(zret)
169  {
170  if(!havedig)
171  {
172  {
173  *sp = (const char*)s0 - 1;
174  }
175  }
176  return STRTOG_Zero;
177  }
178  n = (int)(s1 - s0 - 1);
179  for(k = 0; n > 7; n >>= 1)
180  {
181  {
182  k++;
183  }
184  }
185  b = Balloc(k);
186  x = b->x;
187  n = 0;
188  L = 0;
189  while(s1 > s0)
190  {
191  if(*--s1 == decimalpoint)
192  {
193  continue;
194  }
195  if(n == 32)
196  {
197  *x++ = L;
198  L = 0;
199  n = 0;
200  }
201  L |= (unsigned)((hexdig[*s1] & 0x0f) << n);
202  n += 4;
203  }
204  *x++ = L;
205  n = (int)(x - b->x);
206  b->wds = n;
207  n = 32 * n - hi0bits(L);
208  nbits = fpi->nbits;
209  lostbits = 0;
210  x = b->x;
211  if(n > nbits)
212  {
213  n -= nbits;
214  if(any_on(b, n))
215  {
216  lostbits = 1;
217  k = n - 1;
218  if(x[k >> kshift] & 1 << (k & kmask))
219  {
220  lostbits = 2;
221  if(k > 1 && any_on(b, k - 1))
222  {
223  {
224  lostbits = 3;
225  }
226  }
227  }
228  }
229  rshift(b, n);
230  e += n;
231  }
232  else if(n < nbits)
233  {
234  n = nbits - n;
235  b = lshift(b, n);
236  e -= n;
237  x = b->x;
238  }
239  if(e > fpi->emax)
240  {
241  ovfl:
242  Bfree(b);
243  *bp = 0;
245  }
246  irv = STRTOG_Normal;
247  if(e < fpi->emin)
248  {
249  irv = STRTOG_Denormal;
250  n = fpi->emin - e;
251  if(n >= nbits)
252  {
253  switch(fpi->rounding)
254  {
255  case FPI_Round_near:
256  if(n == nbits && (n < 2 || any_on(b, n - 1)))
257  {
258  {
259  goto one_bit;
260  }
261  }
262  break;
263  case FPI_Round_up:
264  if(!sign)
265  {
266  {
267  goto one_bit;
268  }
269  }
270  break;
271  case FPI_Round_down:
272  if(sign)
273  {
274  one_bit:
275  *exp = fpi->emin;
276  x[0] = b->wds = 1;
277  *bp = b;
279  }
280  }
281  Bfree(b);
282  *bp = 0;
284  }
285  k = n - 1;
286  if(lostbits)
287  {
288  {
289  lostbits = 1;
290  }
291  }
292  else if(k > 0)
293  {
294  {
295  lostbits = any_on(b, k);
296  }
297  }
298  if(x[k >> kshift] & 1 << (k & kmask))
299  {
300  {
301  lostbits |= 2;
302  }
303  }
304  nbits -= n;
305  rshift(b, n);
306  e = fpi->emin;
307  }
308  if(lostbits)
309  {
310  up = 0;
311  switch(fpi->rounding)
312  {
313  case FPI_Round_zero:
314  break;
315  case FPI_Round_near:
316  if(lostbits & 2 && ((lostbits & 1) | (x[0] & 1)))
317  {
318  {
319  up = 1;
320  }
321  }
322  break;
323  case FPI_Round_up:
324  up = 1 - sign;
325  break;
326  case FPI_Round_down:
327  up = sign;
328  }
329  if(up)
330  {
331  k = b->wds;
332  b = increment(b);
333  x = b->x;
334  if(irv == STRTOG_Denormal)
335  {
336  if(nbits == fpi->nbits - 1 && x[nbits >> kshift] & 1 << (nbits & kmask))
337  {
338  {
339  irv = STRTOG_Normal;
340  }
341  }
342  }
343  else if(b->wds > k || (((n = nbits & kmask) != 0) && (hi0bits(x[k - 1]) < (32 - n))))
344  {
345  rshift(b, 1);
346  if(++e > fpi->emax)
347  {
348  {
349  goto ovfl;
350  }
351  }
352  }
353  irv |= STRTOG_Inexhi;
354  }
355  else
356  {
357  {
358  irv |= STRTOG_Inexlo;
359  }
360  }
361  }
362  *bp = b;
363  *exp = e;
364  return irv;
365 }
int emax
Definition: gdtoa.h:90
ULong x[1]
Definition: gdtoaimp.h:488
ULong any_on(Bigint *b, int k)
Definition: smisc.c:210
int wds
Definition: gdtoaimp.h:487
#define CONST
Definition: gdtoa.h:61
Bigint * lshift(Bigint *b, int k)
Definition: misc.c:495
int rounding
Definition: gdtoa.h:91
#define hexdig
Definition: gdtoaimp.h:523
int nbits
Definition: gdtoa.h:88
Bigint * increment(Bigint *b)
Definition: strtodg.c:73
struct lconv * localeconv(void)
#define hi0bits(x)
Definition: gdtoaimp.h:525
int gethex(CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
Definition: gethex.c:46
#define decimalpoint
#define kshift
Definition: gdtoaimp.h:467
unsigned Long ULong
Definition: gdtoa.h:41
void Bfree(Bigint *v)
Definition: misc.c:92
int emin
Definition: gdtoa.h:89
void rshift(Bigint *b, int k)
Definition: gmisc.c:39
#define kmask
Definition: gdtoaimp.h:468
Definition: gdtoa.h:86
Bigint * Balloc(int k)
Definition: misc.c:47
#define Long
Definition: gdtoa.h:38
void hexdig_init_D2A(Void)
Definition: hd_init.c:52
char * decimal_point
Definition: locale.h:20