]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/LibC/gdtoa/gethex.c
Standard Libraries for EDK II.
[mirror_edk2.git] / StdLib / LibC / gdtoa / gethex.c
diff --git a/StdLib/LibC/gdtoa/gethex.c b/StdLib/LibC/gdtoa/gethex.c
new file mode 100644 (file)
index 0000000..02920e7
--- /dev/null
@@ -0,0 +1,249 @@
+/* $NetBSD: gethex.c,v 1.3.14.1 2008/04/08 21:10:55 jdc Exp $ */\r
+\r
+/****************************************************************\r
+\r
+The author of this software is David M. Gay.\r
+\r
+Copyright (C) 1998 by Lucent Technologies\r
+All Rights Reserved\r
+\r
+Permission to use, copy, modify, and distribute this software and\r
+its documentation for any purpose and without fee is hereby\r
+granted, provided that the above copyright notice appear in all\r
+copies and that both that the copyright notice and this\r
+permission notice and warranty disclaimer appear in supporting\r
+documentation, and that the name of Lucent or any of its entities\r
+not be used in advertising or publicity pertaining to\r
+distribution of the software without specific, written prior\r
+permission.\r
+\r
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,\r
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.\r
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY\r
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER\r
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\r
+THIS SOFTWARE.\r
+\r
+****************************************************************/\r
+\r
+/* Please send bug reports to David M. Gay (dmg at acm dot org,\r
+ * with " at " changed at "@" and " dot " changed to ".").  */\r
+#include  <LibConfig.h>\r
+\r
+#include "gdtoaimp.h"\r
+\r
+#ifdef USE_LOCALE\r
+#include "locale.h"\r
+#endif\r
+\r
+ int\r
+gethex( CONST char **sp, CONST FPI *fpi, Long *expt, Bigint **bp, int sign)\r
+{\r
+  Bigint *b;\r
+  CONST unsigned char *decpt, *s0, *s, *s1;\r
+  int esign, havedig, irv, k, n, nbits, up, zret;\r
+  ULong L, lostbits, *x;\r
+  Long e, e1;\r
+#ifdef USE_LOCALE\r
+  unsigned char decimalpoint = *localeconv()->decimal_point;\r
+#else\r
+#define decimalpoint '.'\r
+#endif\r
+\r
+  if (!hexdig['0'])\r
+    hexdig_init_D2A();\r
+  havedig = 0;\r
+  s0 = *(CONST unsigned char **)sp + 2;\r
+  while(s0[havedig] == '0')\r
+    havedig++;\r
+  s0 += havedig;\r
+  s = s0;\r
+  decpt = 0;\r
+  zret = 0;\r
+  e = 0;\r
+  if (!hexdig[*s]) {\r
+    zret = 1;\r
+    if (*s != decimalpoint)\r
+      goto pcheck;\r
+    decpt = ++s;\r
+    if (!hexdig[*s])\r
+      goto pcheck;\r
+    while(*s == '0')\r
+      s++;\r
+    if (hexdig[*s])\r
+      zret = 0;\r
+    havedig = 1;\r
+    s0 = s;\r
+    }\r
+  while(hexdig[*s])\r
+    s++;\r
+  if (*s == decimalpoint && !decpt) {\r
+    decpt = ++s;\r
+    while(hexdig[*s])\r
+      s++;\r
+    }\r
+  if (decpt)\r
+    e = -(((Long)(s-decpt)) << 2);\r
+ pcheck:\r
+  s1 = s;\r
+  switch(*s) {\r
+    case 'p':\r
+    case 'P':\r
+    esign = 0;\r
+    switch(*++s) {\r
+      case '-':\r
+      esign = 1;\r
+      /* FALLTHROUGH */\r
+      case '+':\r
+      s++;\r
+      }\r
+    if ((n = hexdig[*s]) == 0 || n > 0x19) {\r
+      s = s1;\r
+      break;\r
+      }\r
+    e1 = n - 0x10;\r
+    while((n = hexdig[*++s]) !=0 && n <= 0x19)\r
+      e1 = 10*e1 + n - 0x10;\r
+    if (esign)\r
+      e1 = -e1;\r
+    e += e1;\r
+    }\r
+  *sp = __UNCONST(s);\r
+  if (zret)\r
+    return havedig ? STRTOG_Zero : STRTOG_NoNumber;\r
+  n = (int)(s1 - s0 - 1);\r
+  for(k = 0; n > 7; n = (unsigned int)n >> 1)\r
+    k++;\r
+  b = Balloc(k);\r
+  if (b == NULL)\r
+    return STRTOG_NoMemory;\r
+  x = b->x;\r
+  n = 0;\r
+  L = 0;\r
+  while(s1 > s0) {\r
+    if (*--s1 == decimalpoint)\r
+      continue;\r
+    if (n == 32) {\r
+      *x++ = L;\r
+      L = 0;\r
+      n = 0;\r
+      }\r
+    L |= (hexdig[*s1] & 0x0f) << n;\r
+    n += 4;\r
+    }\r
+  *x++ = L;\r
+  b->wds = n = (int)(x - b->x);\r
+  n = 32*n - hi0bits(L);\r
+  nbits = fpi->nbits;\r
+  lostbits = 0;\r
+  x = b->x;\r
+  if (n > nbits) {\r
+    n -= nbits;\r
+    if (any_on(b,n)) {\r
+      lostbits = 1;\r
+      k = n - 1;\r
+      if (x[(unsigned int)k>>kshift] & 1 << (k & kmask)) {\r
+        lostbits = 2;\r
+        if (k > 1 && any_on(b,k-1))\r
+          lostbits = 3;\r
+        }\r
+      }\r
+    rshift(b, n);\r
+    e += n;\r
+    }\r
+  else if (n < nbits) {\r
+    n = nbits - n;\r
+    b = lshift(b, n);\r
+    if (b == NULL)\r
+      return STRTOG_NoMemory;\r
+    e -= n;\r
+    x = b->x;\r
+    }\r
+  if (e > fpi->emax) {\r
+ ovfl:\r
+    Bfree(b);\r
+    *bp = 0;\r
+    return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;\r
+    }\r
+  irv = STRTOG_Normal;\r
+  if (e < fpi->emin) {\r
+    irv = STRTOG_Denormal;\r
+    n = fpi->emin - e;\r
+    if (n >= nbits) {\r
+      switch (fpi->rounding) {\r
+        case FPI_Round_near:\r
+        if (n == nbits && (n < 2 || any_on(b,n-1)))\r
+          goto one_bit;\r
+        break;\r
+        case FPI_Round_up:\r
+        if (!sign)\r
+          goto one_bit;\r
+        break;\r
+        case FPI_Round_down:\r
+        if (sign) {\r
+ one_bit:\r
+          *expt = fpi->emin;\r
+          x[0] = b->wds = 1;\r
+          *bp = b;\r
+          return STRTOG_Denormal | STRTOG_Inexhi\r
+            | STRTOG_Underflow;\r
+          }\r
+        }\r
+      Bfree(b);\r
+      *bp = 0;\r
+      return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;\r
+      }\r
+    k = n - 1;\r
+    if (lostbits)\r
+      lostbits = 1;\r
+    else if (k > 0)\r
+      lostbits = any_on(b,k);\r
+    if (x[(unsigned int)k>>kshift] & 1 << (k & kmask))\r
+      lostbits |= 2;\r
+    nbits -= n;\r
+    rshift(b,n);\r
+    e = fpi->emin;\r
+    }\r
+  if (lostbits) {\r
+    up = 0;\r
+    switch(fpi->rounding) {\r
+      case FPI_Round_zero:\r
+      break;\r
+      case FPI_Round_near:\r
+      if (lostbits & 2\r
+       && (lostbits & 1) | (x[0] & 1))\r
+        up = 1;\r
+      break;\r
+      case FPI_Round_up:\r
+      up = 1 - sign;\r
+      break;\r
+      case FPI_Round_down:\r
+      up = sign;\r
+      }\r
+    if (up) {\r
+      k = b->wds;\r
+      b = increment(b);\r
+      x = b->x;\r
+      if (irv == STRTOG_Denormal) {\r
+        if (nbits == fpi->nbits - 1\r
+         && x[(unsigned int)nbits >> kshift] & 1 << (nbits & kmask))\r
+          irv =  STRTOG_Normal;\r
+        }\r
+      else if (b->wds > k\r
+       || ((n = nbits & kmask) !=0\r
+           && hi0bits(x[k-1]) < 32-n)) {\r
+        rshift(b,1);\r
+        if (++e > fpi->emax)\r
+          goto ovfl;\r
+        }\r
+      irv |= STRTOG_Inexhi;\r
+      }\r
+    else\r
+      irv |= STRTOG_Inexlo;\r
+    }\r
+  *bp = b;\r
+  *expt = e;\r
+  return irv;\r
+  }\r