]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdtoa/gethex.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / contrib / gdtoa / gethex.c
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         unsigned char decimalpoint = *localeconv()->decimal_point;
53 #else
54 #define decimalpoint '.'
55 #endif
56
57         if (!hexdig['0'])
58                 hexdig_init_D2A();
59         *bp = 0;
60         havedig = 0;
61         s0 = *(CONST unsigned char **)sp + 2;
62         while(s0[havedig] == '0')
63                 havedig++;
64         s0 += havedig;
65         s = s0;
66         decpt = 0;
67         zret = 0;
68         e = 0;
69         if (!hexdig[*s]) {
70                 zret = 1;
71                 if (*s != decimalpoint)
72                         goto pcheck;
73                 decpt = ++s;
74                 if (!hexdig[*s])
75                         goto pcheck;
76                 while(*s == '0')
77                         s++;
78                 if (hexdig[*s])
79                         zret = 0;
80                 havedig = 1;
81                 s0 = s;
82                 }
83         while(hexdig[*s])
84                 s++;
85         if (*s == decimalpoint && !decpt) {
86                 decpt = ++s;
87                 while(hexdig[*s])
88                         s++;
89                 }
90         if (decpt)
91                 e = -(((Long)(s-decpt)) << 2);
92  pcheck:
93         s1 = s;
94         big = esign = 0;
95         switch(*s) {
96           case 'p':
97           case 'P':
98                 switch(*++s) {
99                   case '-':
100                         esign = 1;
101                         /* no break */
102                   case '+':
103                         s++;
104                   }
105                 if ((n = hexdig[*s]) == 0 || n > 0x19) {
106                         s = s1;
107                         break;
108                         }
109                 e1 = n - 0x10;
110                 while((n = hexdig[*++s]) !=0 && n <= 0x19) {
111                         if (e1 & 0xf8000000)
112                                 big = 1;
113                         e1 = 10*e1 + n - 0x10;
114                         }
115                 if (esign)
116                         e1 = -e1;
117                 e += e1;
118           }
119         *sp = (char*)s;
120         if (!havedig)
121                 *sp = s0 - 1;
122         if (zret)
123                 return STRTOG_Zero;
124         if (big) {
125                 if (esign) {
126                         switch(fpi->rounding) {
127                           case FPI_Round_up:
128                                 if (sign)
129                                         break;
130                                 goto ret_tiny;
131                           case FPI_Round_down:
132                                 if (!sign)
133                                         break;
134                                 goto ret_tiny;
135                           }
136                         goto retz;
137  ret_tiny:
138                         b = Balloc(0);
139                         b->wds = 1;
140                         b->x[0] = 1;
141                         goto dret;
142                         }
143                 switch(fpi->rounding) {
144                   case FPI_Round_near:
145                         goto ovfl1;
146                   case FPI_Round_up:
147                         if (!sign)
148                                 goto ovfl1;
149                         goto ret_big;
150                   case FPI_Round_down:
151                         if (sign)
152                                 goto ovfl1;
153                         goto ret_big;
154                   }
155  ret_big:
156                 nbits = fpi->nbits;
157                 n0 = n = nbits >> kshift;
158                 if (nbits & kmask)
159                         ++n;
160                 for(j = n, k = 0; j >>= 1; ++k);
161                 *bp = b = Balloc(k);
162                 b->wds = n;
163                 for(j = 0; j < n0; ++j)
164                         b->x[j] = ALL_ON;
165                 if (n > n0)
166                         b->x[j] = ULbits >> (ULbits - (nbits & kmask));
167                 *exp = fpi->emin;
168                 return STRTOG_Normal | STRTOG_Inexlo;
169                 }
170         n = s1 - s0 - 1;
171         for(k = 0; n > 7; n >>= 1)
172                 k++;
173         b = Balloc(k);
174         x = b->x;
175         n = 0;
176         L = 0;
177         while(s1 > s0) {
178                 if (*--s1 == decimalpoint)
179                         continue;
180                 if (n == 32) {
181                         *x++ = L;
182                         L = 0;
183                         n = 0;
184                         }
185                 L |= (hexdig[*s1] & 0x0f) << n;
186                 n += 4;
187                 }
188         *x++ = L;
189         b->wds = n = x - b->x;
190         n = 32*n - hi0bits(L);
191         nbits = fpi->nbits;
192         lostbits = 0;
193         x = b->x;
194         if (n > nbits) {
195                 n -= nbits;
196                 if (any_on(b,n)) {
197                         lostbits = 1;
198                         k = n - 1;
199                         if (x[k>>kshift] & 1 << (k & kmask)) {
200                                 lostbits = 2;
201                                 if (k > 0 && any_on(b,k))
202                                         lostbits = 3;
203                                 }
204                         }
205                 rshift(b, n);
206                 e += n;
207                 }
208         else if (n < nbits) {
209                 n = nbits - n;
210                 b = lshift(b, n);
211                 e -= n;
212                 x = b->x;
213                 }
214         if (e > fpi->emax) {
215  ovfl:
216                 Bfree(b);
217  ovfl1:
218 #ifndef NO_ERRNO
219                 errno = ERANGE;
220 #endif
221                 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
222                 }
223         irv = STRTOG_Normal;
224         if (e < fpi->emin) {
225                 irv = STRTOG_Denormal;
226                 n = fpi->emin - e;
227                 if (n >= nbits) {
228                         switch (fpi->rounding) {
229                           case FPI_Round_near:
230                                 if (n == nbits && (n < 2 || any_on(b,n-1)))
231                                         goto one_bit;
232                                 break;
233                           case FPI_Round_up:
234                                 if (!sign)
235                                         goto one_bit;
236                                 break;
237                           case FPI_Round_down:
238                                 if (sign) {
239  one_bit:
240                                         x[0] = b->wds = 1;
241  dret:
242                                         *bp = b;
243                                         *exp = fpi->emin;
244 #ifndef NO_ERRNO
245                                         errno = ERANGE;
246 #endif
247                                         return STRTOG_Denormal | STRTOG_Inexhi
248                                                 | STRTOG_Underflow;
249                                         }
250                           }
251                         Bfree(b);
252  retz:
253 #ifndef NO_ERRNO
254                         errno = ERANGE;
255 #endif
256                         return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
257                         }
258                 k = n - 1;
259                 if (lostbits)
260                         lostbits = 1;
261                 else if (k > 0)
262                         lostbits = any_on(b,k);
263                 if (x[k>>kshift] & 1 << (k & kmask))
264                         lostbits |= 2;
265                 nbits -= n;
266                 rshift(b,n);
267                 e = fpi->emin;
268                 }
269         if (lostbits) {
270                 up = 0;
271                 switch(fpi->rounding) {
272                   case FPI_Round_zero:
273                         break;
274                   case FPI_Round_near:
275                         if (lostbits & 2
276                          && (lostbits & 1) | x[0] & 1)
277                                 up = 1;
278                         break;
279                   case FPI_Round_up:
280                         up = 1 - sign;
281                         break;
282                   case FPI_Round_down:
283                         up = sign;
284                   }
285                 if (up) {
286                         k = b->wds;
287                         b = increment(b);
288                         x = b->x;
289                         if (irv == STRTOG_Denormal) {
290                                 if (nbits == fpi->nbits - 1
291                                  && x[nbits >> kshift] & 1 << (nbits & kmask))
292                                         irv =  STRTOG_Normal;
293                                 }
294                         else if (b->wds > k
295                          || (n = nbits & kmask) !=0
296                              && hi0bits(x[k-1]) < 32-n) {
297                                 rshift(b,1);
298                                 if (++e > fpi->emax)
299                                         goto ovfl;
300                                 }
301                         irv |= STRTOG_Inexhi;
302                         }
303                 else
304                         irv |= STRTOG_Inexlo;
305                 }
306         *bp = b;
307         *exp = e;
308         return irv;
309         }