Embedded Artistry libc
C Standard Library Support for Bare-metal Systems
gethex.c File Reference
#include "gdtoaimp.h"
Include dependency graph for gethex.c:

Go to the source code of this file.

Macros

#define decimalpoint   '.'
 

Functions

int gethex (CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
 

Macro Definition Documentation

◆ decimalpoint

#define decimalpoint   '.'

Function Documentation

◆ gethex()

int gethex ( CONST char **  sp,
FPI fpi,
Long exp,
Bigint **  bp,
int  sign 
)

Definition at line 46 of file gethex.c.

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
#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
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

References any_on(), Balloc(), Bfree(), CONST, lconv::decimal_point, decimalpoint, FPI::emax, FPI::emin, FPI_Round_down, FPI_Round_near, FPI_Round_up, FPI_Round_zero, hexdig, hexdig_init_D2A(), hi0bits, increment(), kmask, kshift, localeconv(), Long, lshift(), FPI::nbits, FPI::rounding, rshift(), STRTOG_Denormal, STRTOG_Inexhi, STRTOG_Inexlo, STRTOG_Infinite, STRTOG_Normal, STRTOG_Overflow, STRTOG_Underflow, STRTOG_Zero, Bigint::wds, and Bigint::x.

Referenced by strtod(), and strtodg().