gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/stdlib/gethex.cbare sourcepermlink (0.03 seconds)

Search this content:

    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:                         strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
   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:                         if (b == NULL)
  171:                                 return (STRTOG_NoMemory);
  172:                         b->wds = 1;
  173:                         b->x[0] = 1;
  174:                         goto dret;
  175:                         }
  176:                 switch(fpi->rounding) {
  177:                   case FPI_Round_near:
  178:                         goto ovfl1;
  179:                   case FPI_Round_up:
  180:                         if (!sign)
  181:                                 goto ovfl1;
  182:                         goto ret_big;
  183:                   case FPI_Round_down:
  184:                         if (sign)
  185:                                 goto ovfl1;
  186:                         goto ret_big;
  187:                   }
  188:  ret_big:
  189:                 nbits = fpi->nbits;
  190:                 n0 = n = nbits >> kshift;
  191:                 if (nbits & kmask)
  192:                         ++n;
  193:                 for(j = n, k = 0; j >>= 1; ++k);
  194:                 *bp = b = Balloc(k);
  195:                 if (*bp == NULL)
  196:                         return (STRTOG_NoMemory);
  197:                 b->wds = n;
  198:                 for(j = 0; j < n0; ++j)
  199:                         b->x[j] = ALL_ON;
  200:                 if (n > n0)
  201:                         b->x[j] = ULbits >> (ULbits - (nbits & kmask));
  202:                 *exp = fpi->emin;
  203:                 return STRTOG_Normal | STRTOG_Inexlo;
  204:                 }
  205:         n = s1 - s0 - 1;
  206:         for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
  207:                 k++;
  208:         b = Balloc(k);
  209:         if (b == NULL)
  210:                 return (STRTOG_NoMemory);
  211:         x = b->x;
  212:         n = 0;
  213:         L = 0;
  214: #ifdef USE_LOCALE
  215:         for(i = 0; decimalpoint[i+1]; ++i);
  216: #endif
  217:         while(s1 > s0) {
  218: #ifdef USE_LOCALE
  219:                 if (*--s1 == decimalpoint[i]) {
  220:                         s1 -= i;
  221:                         continue;
  222:                         }
  223: #else
  224:                 if (*--s1 == '.')
  225:                         continue;
  226: #endif
  227:                 if (n == ULbits) {
  228:                         *x++ = L;
  229:                         L = 0;
  230:                         n = 0;
  231:                         }
  232:                 L |= (hexdig[*s1] & 0x0f) << n;
  233:                 n += 4;
  234:                 }
  235:         *x++ = L;
  236:         b->wds = n = x - b->x;
  237:         n = ULbits*n - hi0bits(L);
  238:         nbits = fpi->nbits;
  239:         lostbits = 0;
  240:         x = b->x;
  241:         if (n > nbits) {
  242:                 n -= nbits;
  243:                 if (any_on(b,n)) {
  244:                         lostbits = 1;
  245:                         k = n - 1;
  246:                         if (x[k>>kshift] & 1 << (k & kmask)) {
  247:                                 lostbits = 2;
  248:                                 if (k > 0 && any_on(b,k))
  249:                                         lostbits = 3;
  250:                                 }
  251:                         }
  252:                 rshift(b, n);
  253:                 e += n;
  254:                 }
  255:         else if (n < nbits) {
  256:                 n = nbits - n;
  257:                 b = lshift(b, n);
  258:                 if (b == NULL)
  259:                         return (STRTOG_NoMemory);
  260:                 e -= n;
  261:                 x = b->x;
  262:                 }
  263:         if (e > fpi->emax) {
  264:  ovfl:
  265:                 Bfree(b);
  266:  ovfl1:
  267: #ifndef NO_ERRNO
  268:                 /*errno = ERANGE*/;
  269: #endif
  270:                 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
  271:                 }
  272:         irv = STRTOG_Normal;
  273:         if (e < fpi->emin) {
  274:                 irv = STRTOG_Denormal;
  275:                 n = fpi->emin - e;
  276:                 if (n >= nbits) {
  277:                         switch (fpi->rounding) {
  278:                           case FPI_Round_near:
  279:                                 if (n == nbits && (n < 2 || any_on(b,n-1)))
  280:                                         goto one_bit;
  281:                                 break;
  282:                           case FPI_Round_up:
  283:                                 if (!sign)
  284:                                         goto one_bit;
  285:                                 break;
  286:                           case FPI_Round_down:
  287:                                 if (sign) {
  288:  one_bit:
  289:                                         x[0] = b->wds = 1;
  290:  dret:
  291:                                         *bp = b;
  292:                                         *exp = fpi->emin;
  293: #ifndef NO_ERRNO
  294:                                         /*errno = ERANGE*/;
  295: #endif
  296:                                         return STRTOG_Denormal | STRTOG_Inexhi
  297:                                                 | STRTOG_Underflow;
  298:                                         }
  299:                           }
  300:                         Bfree(b);
  301:  retz:
  302: #ifndef NO_ERRNO
  303:                         /*errno = ERANGE*/;
  304: #endif
  305:                         return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
  306:                         }
  307:                 k = n - 1;
  308:                 if (lostbits)
  309:                         lostbits = 1;
  310:                 else if (k > 0)
  311:                         lostbits = any_on(b,k);
  312:                 if (x[k>>kshift] & 1 << (k & kmask))
  313:                         lostbits |= 2;
  314:                 nbits -= n;
  315:                 rshift(b,n);
  316:                 e = fpi->emin;
  317:                 }
  318:         if (lostbits) {
  319:                 up = 0;
  320:                 switch(fpi->rounding) {
  321:                   case FPI_Round_zero:
  322:                         break;
  323:                   case FPI_Round_near:
  324:                         if (lostbits & 2
  325:                          && (lostbits | x[0]) & 1)
  326:                                 up = 1;
  327:                         break;
  328:                   case FPI_Round_up:
  329:                         up = 1 - sign;
  330:                         break;
  331:                   case FPI_Round_down:
  332:                         up = sign;
  333:                   }
  334:                 if (up) {
  335:                         k = b->wds;
  336:                         b = increment(b);
  337:                         if (b == NULL)
  338:                                 return (STRTOG_NoMemory);
  339:                         x = b->x;
  340:                         if (irv == STRTOG_Denormal) {
  341:                                 if (nbits == fpi->nbits - 1
  342:                                  && x[nbits >> kshift] & 1 << (nbits & kmask))
  343:                                         irv =  STRTOG_Normal;
  344:                                 }
  345:                         else if (b->wds > k
  346:                          || ((n = nbits & kmask) !=0
  347:                               && hi0bits(x[k-1]) < 32-n)) {
  348:                                 rshift(b,1);
  349:                                 if (++e > fpi->emax)
  350:                                         goto ovfl;
  351:                                 }
  352:                         irv |= STRTOG_Inexhi;
  353:                         }
  354:                 else
  355:                         irv |= STRTOG_Inexlo;
  356:                 }
  357:         *bp = b;
  358:         *exp = e;
  359:         return irv;
  360:         }