Loading...
stdlib/strtofp.c Libc-1725.40.4 Libc-1583.40.7
--- Libc/Libc-1725.40.4/stdlib/strtofp.c
+++ Libc/Libc-1583.40.7/stdlib/strtofp.c
@@ -285,50 +285,23 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <fenv.h>
 #include <float.h>
-#include <stdbool.h>
+#if !defined(ENABLE_LOCALE_SUPPORT) || ENABLE_LOCALE_SUPPORT
+#include <langinfo.h>
+#include <locale.h>
+#endif
+#include <math.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <strings.h>
-
-// Check whether access to the floating-point environment is supported
-#if !defined(ENABLE_FENV_ACCESS)
-#if __has_include(<fenv.h>)
-  #include <fenv.h>
-
-  #define ENABLE_FENV_ACCESS 1
-#else
-  #define ENABLE_FENV_ACCESS 0
-#endif
-#endif
-
-// Check whether precision/range of floating-point values is defined
-#if __has_include(<math.h>)
-  #include <math.h>
-#else
-#if !defined(FLT_EVAL_METHOD)
-  // Note that Clang's builtin float.h header does define this macro
-  #define FLT_EVAL_METHOD -1
-#endif
-#endif
-
-// Check whether locales are supported
-#if !defined(ENABLE_LOCALE_SUPPORT)
-#if __has_include(<langinfo.h>) && __has_include(<locale.h>)
-  #include <langinfo.h>
-  #include <locale.h>
-#if defined(__APPLE__)
-  #include <xlocale.h>
-  #include <xlocale_private.h>
-#endif
-
-  #define ENABLE_LOCALE_SUPPORT 1
-#else
-  #define ENABLE_LOCALE_SUPPORT 0
-#endif
-#endif
+#if defined(__APPLE__) && (!defined(ENABLE_LOCALE_SUPPORT) || ENABLE_LOCALE_SUPPORT)
+#include <xlocale.h>
+#include <xlocale_private.h>
+#endif
+
+// #pragma STDC FENV_ACCESS ON
 
 // ================================================================
 // Detect the floating-point formats supported on this platform
@@ -362,17 +335,17 @@
 // Is "long double" on this system the same as Float80?
 // (Example: macOS, Linux, and FreeBSD when running on x86 or x86_64 processors.)
 #if (FLT_RADIX == 2) && (LDBL_MANT_DIG == 64) && (LDBL_MIN_EXP == -16381) && (LDBL_MAX_EXP == 16384)
-  #define LONG_DOUBLE_IS_FLOAT80 1
+ #define LONG_DOUBLE_IS_FLOAT80 1
 #else
-  #define LONG_DOUBLE_IS_FLOAT80 0
+ #define LONG_DOUBLE_IS_FLOAT80 0
 #endif
 
 // Does "long double" on this system use IEEE 754 binary128 format?
 // (Example: Android on LP64 hardware.)
 #if (FLT_RADIX == 2) && (LDBL_MANT_DIG == 113) && (LDBL_MIN_EXP == -16381) && (LDBL_MAX_EXP == 16384)
-  #define LONG_DOUBLE_IS_BINARY128 1
+ #define LONG_DOUBLE_IS_BINARY128 1
 #else
-  #define LONG_DOUBLE_IS_BINARY128 0
+ #define LONG_DOUBLE_IS_BINARY128 0
 #endif
 
 // ================================================================
@@ -397,6 +370,11 @@
 // calling the standard functions:  We defer such calls until
 // we see a character that is not a digit or other known character,
 // and we handle the "C" locale specially.)
+
+// Enable locale support by default
+#ifndef ENABLE_LOCALE_SUPPORT
+ #define ENABLE_LOCALE_SUPPORT 1
+#endif
 
 // Define macros used for locale information below:
 //
@@ -436,36 +414,6 @@
  #error Need definition for strtofp_locale_decimal_point and strtofp_current_locale for this platform
 #endif
 
-// ================================================================
-// Floating-point rounding mode
-
-#if ENABLE_FENV_ACCESS
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wignored-pragmas"
-  #pragma STDC FENV_ACCESS ON
-  #pragma GCC diagnostic pop
-
-  #define FENV_ROUNDING_MODE() fegetround()
-#else
-  // By default, we use FE_TONEAREST, which rounds to the nearest representable value
-  #define FENV_ROUNDING_MODE() 0
-#endif
-
-// In certain scenarios, we require FE_TOWARDZERO, which rounds towards zero,
-// but need to provide a sentinel value if it is not defined
-#ifndef FE_TOWARDZERO
-  #define FE_TOWARDZERO 0xFE00
-#endif
-
-#if defined(FE_DOWNWARD) && FE_TOWARDZERO == FE_DOWNWARD
-  #error "Definition of FE_TOWARDZERO conflicts with FE_DOWNWARD"
-#endif
-#if defined(FE_TONEAREST) && FE_TOWARDZERO == FE_TONEAREST
-  #error "Definition of FE_TOWARDZERO conflicts with FE_TONEAREST"
-#endif
-#if defined(FE_UPWARD) && FE_TOWARDZERO == FE_UPWARD
-  #error "Definition of FE_TOWARDZERO conflicts with FE_UPWARD"
-#endif
 
 // ================================================================
 //
@@ -511,7 +459,7 @@
   #define ENABLE_FLOAT80_OPTIMIZATIONS 1
  #endif
 #else
- #define ENABLE_FLOAT80_OPTIMIZATIONS 0
+ #undef ENABLE_FLOAT80_OPTIMIZATIONS
 #endif
 
 // Enable binary128 interval optimization by default.
@@ -520,7 +468,7 @@
    #define ENABLE_BINARY128_OPTIMIZATIONS 1
  #endif
 #else
- #define ENABLE_BINARY128_OPTIMIZATIONS 0
+ #undef ENABLE_BINARY128_OPTIMIZATIONS
 #endif
 
 // At least one format must be enabled
@@ -998,7 +946,7 @@
 static const int mp_word_bits = sizeof(mp_word_t) * 8;
 // __builtin_clz() takes an `unsigned` which may be different from mp_word_t
 // This adjusts the result accordingly.
-#define CLZ_WORD(word) ((unsigned)__builtin_clz((word)) + (mp_word_bits - sizeof(unsigned) * 8))
+#define CLZ_WORD(word) (__builtin_clz((word)) + (mp_word_bits - sizeof(unsigned) * 8))
 
 // A multi-precision integer is represented as two pointers:
 // lsw - points to least-significant word (lowest address in memory)
@@ -1083,10 +1031,8 @@
 static mp_t shiftRightMPWithRounding(mp_t work,
                                      int shift,
                                      int trailingNonZero,
-                                     bool negative,
+                                     int negative,
                                      int roundingMode) {
-  (void)negative;
-
   if (shift == 0) {
     return work;
   }
@@ -1104,17 +1050,12 @@
     // words and possibly increment.
     result.lsw += wordsShift;
     switch (roundingMode) {
-#ifdef FE_TOWARDZERO
     case FE_TOWARDZERO:
       return result;
-#endif
-#ifdef FE_DOWNWARD
     case FE_DOWNWARD:
       // Upwards & downwards rounding are symmetric
       negative = !negative;
       // FALL THROUGH
-#endif
-#ifdef FE_UPWARD
     case FE_UPWARD:
       for (mp_word_t *p = work.lsw; p < result.lsw; p++) {
         trailingNonZero |= *p;
@@ -1124,15 +1065,12 @@
       } else {
         break; // Increment and return
       }
-#endif
-#ifdef FE_TONEAREST
     case FE_TONEAREST:
-#endif
     default: {
       // shift is non-zero, so result.lsw[-1] is valid
       // and is the most-significant-word of the fraction:
       mp_word_t fractionMsw = result.lsw[-1];
-      mp_word_t oneHalf = 1U << (mp_word_bits - 1);
+      mp_word_t oneHalf = 1 << (mp_word_bits - 1);
       if (fractionMsw < oneHalf) {
         return result;
       } else if (fractionMsw > oneHalf) {
@@ -1154,35 +1092,28 @@
   }
 
   result.lsw += wordsShift;
-  mp_word_t fraction = result.lsw[0] & ((1U << bitsShift) - 1);
-
-  {
-    mp_word_t *p = result.lsw;
-    mp_dword_t t = *p++ >> bitsShift;
-    for (; p < result.msw; p++) {
-      t |= (mp_dword_t)*p << (mp_word_bits - bitsShift);
-      p[-1] = (mp_word_t)t;
-      t >>= mp_word_bits;
-    }
-    if (t == 0) {
-      result.msw -= 1;
-    } else {
-      p[-1] = (mp_word_t)t;
-    }
+  mp_word_t fraction = result.lsw[0] & ((1 << bitsShift) - 1);
+
+  mp_word_t *p = result.lsw;
+  mp_dword_t t = *p++ >> bitsShift;
+  for (; p < result.msw; p++) {
+    t |= (mp_dword_t)*p << (mp_word_bits - bitsShift);
+    p[-1] = (mp_word_t)t;
+    t >>= mp_word_bits;
+  }
+  if (t == 0) {
+    result.msw -= 1;
+  } else {
+    p[-1] = (mp_word_t)t;
   }
 
   switch (roundingMode) {
-#ifdef FE_TOWARDZERO
   case FE_TOWARDZERO:
     return result;
-#endif
-#ifdef FE_DOWNWARD
   case FE_DOWNWARD:
     // Upwards & downwards rounding are symmetric
     negative = !negative;
     // FALL THROUGH
-#endif
-#ifdef FE_UPWARD
   case FE_UPWARD:
     trailingNonZero |= fraction;
     for (mp_word_t *p = work.lsw; p < result.lsw; p++) {
@@ -1193,12 +1124,9 @@
     } else {
       break; // Increment and return
     }
-#endif
-#ifdef FE_TONEAREST
   case FE_TONEAREST:
-#endif
   default: {
-    mp_word_t half = (mp_word_t)(1U << (bitsShift - 1));
+    mp_word_t half = 1 << (bitsShift - 1);
     if (fraction < half) {
       return result;
     } else if (fraction > half) {
@@ -1258,7 +1186,7 @@
       t >>= mp_word_bits;
     }
     while (t > 0) {
-      *p++ = (mp_word_t)t;
+      *p++ = t;
       t >>= mp_word_bits;
     }
     dest->msw = p;
@@ -1513,7 +1441,7 @@
   // Decimal exponent, corrected for decimal point location
   int base10Exponent;
   // True if number is negative
-  bool negative;
+  int negative;
 };
 
 // ================================================================
@@ -1524,7 +1452,6 @@
 // ================================================================
 // ================================================================
 
-// Store a suitably-signed infinity to the destination
 static void infinity(struct parseInfo *info) {
   // 16/32/64-bit formats we can hardcode the full value
   // and memcpy() it.  This is endian-safe (assuming that
@@ -1557,7 +1484,7 @@
 
   // 80- and 128-bit formats we build up incrementally.
   // TODO: Support big-endian.
-  memset(info->dest, 0, (size_t)info->bytes);
+  memset(info->dest, 0, info->bytes);
   switch(info->bytes) {
 #if ENABLE_FLOAT80_SUPPORT
   case 10: // float80
@@ -1574,78 +1501,10 @@
   }
 }
 
-// Store the max normal value to the destination, suitably signed.
-static void max_value(struct parseInfo *info) {
-  switch (info->bytes) {
-#if ENABLE_BINARY16_SUPPORT
-  case 2: { // binary16
-    uint16_t raw = info->negative ? 0xfbff : 0x7bff;
-    memcpy(info->dest, &raw, sizeof(raw));
-    return;
-  }
-#endif
-#if ENABLE_BINARY32_SUPPORT
-  case 4: { // binary32
-    uint32_t raw = info->negative ? 0xff7fffffUL : 0x7f7fffffUL;
-    memcpy(info->dest, &raw, sizeof(raw));
-    return;
-  }
-#endif
-#if ENABLE_BINARY64_SUPPORT
-  case 8: { // binary64
-    uint64_t raw = info->negative ? 0xffefffffffffffffULL : 0x7fefffffffffffffULL;
-    memcpy(info->dest, &raw, sizeof(raw));
-    return;
-  }
-#endif
-  default:
-    break;
-  }
-
-  // 80- and 128-bit formats we build up incrementally.
-  // TODO: Support big-endian.
-  memset(info->dest, 0xff, info->bytes);
-  switch(info->bytes) {
-#if ENABLE_FLOAT80_SUPPORT
-  case 10: // float80
-    info->dest[7] = 0xff;
-    info->dest[8] = 0xfe;
-    info->dest[9] = info->negative ? 0xff : 0x7f;
-#endif
-#if ENABLE_BINARY128_SUPPORT
-  case 16: // binary128
-    info->dest[14] = 0xfe;
-    info->dest[15] = info->negative ? 0xff : 0x7f;
-    break;
-#endif
-  }
-}
-
-// This gets invoked for inputs whose magnitude is greater
-// than the max normal value + 1 ulp.
-// Gdtoa returns signed INF for such values regardless of the
-// rounding mode.  Glibc rounds them correctly.
 static void overflow(struct parseInfo *info) {
   // Overflow is always an ERANGE error
   errno = ERANGE;
-  int roundingMode = FENV_ROUNDING_MODE();
-  int negative = info->negative;
-
-  if (0
-#ifdef FE_TOWARDZERO
-      || roundingMode == FE_TOWARDZERO
-#endif
-#ifdef FE_DOWNWARD
-      || (roundingMode == FE_DOWNWARD && !negative)
-#endif
-#ifdef FE_UPWARD
-      || (roundingMode == FE_UPWARD && negative)
-#endif
-      ) {
-    max_value(info);
-  } else {
-    infinity(info);
-  }
+  infinity(info);
 }
 
 // This gets invoked for inputs that are nonzero, but closer to zero
@@ -1668,15 +1527,9 @@
   // very small non-zero (such as "1e-999999").
   errno = ERANGE;
   uint8_t bottomBit = 0;
-  int roundingMode = FENV_ROUNDING_MODE();
-  if (0
-#ifdef FE_DOWNWARD
-      || (roundingMode == FE_DOWNWARD && info->negative)
-#endif
-#ifdef FE_UPWARD
-      || (roundingMode == FE_UPWARD && !info->negative)
-#endif
-    ) {
+  int roundingMode = fegetround();
+  if ((roundingMode == FE_DOWNWARD && info->negative)
+      || (roundingMode == FE_UPWARD && !info->negative)) {
     bottomBit = 1;
   }
 
@@ -1708,7 +1561,7 @@
 #if ENABLE_FLOAT80_SUPPORT || ENABLE_BINARY128_SUPPORT
   case 10: case 16: {
     // TODO: Make this endian-safe
-    memset(info->dest, 0, (size_t)info->bytes); // Initialize to +0
+    memset(info->dest, 0, info->bytes); // Initialize to +0
     info->dest[0] = bottomBit;
     info->dest[info->bytes - 1] = info->negative ? 0x80 : 0;
     break;
@@ -1768,10 +1621,10 @@
     int batchSize = remainingDigitCount > 9 ? 9 : remainingDigitCount;
     uint64_t batch = 0;
     for (int i = 0; i < batchSize; i++, p++) {
-      unsigned t = (unsigned)(*p - '0');
+      unsigned t = *p - '0';
       while (t > 9) {
         p += 1; // Skip non-digits (decimal point)
-        t = (unsigned)(*p - '0');
+        t = *p - '0';
       }
       batch = batch * 10 + t;
     }
@@ -1829,7 +1682,7 @@
                             int roundingMode,
                             mp_word_t *stackWorkArea,
                             int stackWorkAreaWords,
-                            bool heapAllocOK)
+                            int heapAllocOK)
 {
   mp_t mpSignificand;
   int binaryExponent;
@@ -1861,13 +1714,13 @@
     int totalWordsNeeded = significandWordsNeeded + exponentWordsNeeded;
     mp_t workMP;
     if (totalWordsNeeded <= stackWorkAreaWords) {
-      memset(stackWorkArea, 0, (size_t)stackWorkAreaWords * sizeof(mp_word_t));
+      memset(stackWorkArea, 0, stackWorkAreaWords * sizeof(mp_word_t));
       workMP.lsw = workMP.msw = stackWorkArea;
     } else {
       assert(heapAllocOK);
-      heapAlloc = (mp_word_t *)calloc((size_t)totalWordsNeeded, sizeof(mp_word_t));
+      heapAlloc = (mp_word_t *)calloc(totalWordsNeeded, sizeof(mp_word_t));
       if (heapAlloc == NULL) {
-        memset(info->dest, 0, (size_t)info->bytes);
+        memset(info->dest, 0, info->bytes);
         return;
       }
       workMP.lsw = workMP.msw = heapAlloc;
@@ -1923,9 +1776,9 @@
       work = stackWorkArea;
     } else {
       assert(heapAllocOK);
-      heapAlloc = (mp_word_t *)calloc((size_t)totalWordsNeeded, sizeof(mp_word_t));
+      heapAlloc = (mp_word_t *)calloc(totalWordsNeeded, sizeof(mp_word_t));
       if (heapAlloc == NULL) {
-        memset(info->dest, 0, (size_t)info->bytes);
+        memset(info->dest, 0, info->bytes);
         return;
       }
       work = heapAlloc;
@@ -2008,18 +1861,18 @@
   }
 
   // Zero-extend to sigBits and copy to dest
-  size_t mpWords = (size_t)(mpSignificand.msw - mpSignificand.lsw);
-  size_t expectedWords = (size_t)((info->sigBits + mp_word_bits - 1) / mp_word_bits);
+  size_t mpWords = mpSignificand.msw - mpSignificand.lsw;
+  size_t expectedWords = (info->sigBits + mp_word_bits - 1) / mp_word_bits;
   if (mpWords < expectedWords) {
     memset(mpSignificand.lsw + mpWords, 0, (expectedWords - mpWords) * sizeof(mp_word_t));
   }
   // TODO: Endianness.  This only works for little-endian systems.
-  memcpy(info->dest, mpSignificand.lsw, ((unsigned)info->sigBits + 7) / 8);
+  memcpy(info->dest, mpSignificand.lsw, (info->sigBits + 7) / 8);
   // Free the heap work area (if any)
   free(heapAlloc);
 
   // Set the exponent & sign bits
-  uint16_t exponentBits = (uint16_t)(binaryExponent - info->minBinaryExp);
+  uint16_t exponentBits = binaryExponent - info->minBinaryExp;
   if (info->bytes <= 8) {
     // float80 and binary128 have 16 bit exponent+sign, so no shift needed
     exponentBits <<= 16 - (info->bytes * 8 - info->sigBits + 1);
@@ -2058,7 +1911,8 @@
 // been verified to be '0x'.
 static void
 hexFloat(const unsigned char *start, struct parseInfo *info) {
-  const unsigned char *p = start + 2; // Skip leading '0x'
+  const unsigned char *p = start;
+  p += 2; // Skip leading '0x'
 
   // Two 64-bit ints that we use as a joint 128-bit accumulator
   uint64_t significand_lsw = 0, significand_msw = 0;
@@ -2151,15 +2005,15 @@
     } else {
       // Skip zeros in "0x1p+0000000000000000000000000001"
       int exp = 0;
-      unsigned t = (unsigned)(*p - '0');
+      unsigned t = *p - '0';
       while (t < 10) {
         if (exp > 99999999) {
           exp = 99999999;
         } else {
-          exp = exp * 10 + (int)t;
+          exp = exp * 10 + t;
         }
         p += 1;
-        t = (unsigned)(*p - '0');
+        t = *p - '0';
       }
       if (negativeExponent) {
         exp = -exp;
@@ -2226,12 +2080,9 @@
         significand_msw = 0;
       }
 
-      switch (FENV_ROUNDING_MODE()) {
-#ifdef FE_TOWARDZERO
+      switch (fegetround()) {
       case FE_TOWARDZERO:
         break;
-#endif
-#ifdef FE_DOWNWARD
       case FE_DOWNWARD:
         if (info->negative && (fraction != 0)) {
           significand_lsw += 1;
@@ -2240,8 +2091,6 @@
           }
         }
         break;
-#endif
-#ifdef FE_UPWARD
       case FE_UPWARD:
         if (!info->negative && (fraction != 0)) {
           significand_lsw += 1;
@@ -2250,10 +2099,7 @@
           }
         }
         break;
-#endif
-#ifdef FE_TONEAREST
       case FE_TONEAREST:
-#endif
       default: {
         const uint64_t oneHalf = (uint64_t)1 << 63;
         if (fraction > oneHalf
@@ -2280,14 +2126,13 @@
           significand_msw >>= 1;
         }
         base2Exponent += 1;
-      } else if (base2Exponent == info->minBinaryExp // Subnormal
-                 && fraction != 0) { // Not exact
-        errno = ERANGE;
-      }
-    }
-  }
-
-  if (info->end) *info->end = (char *)(uintptr_t)p;
+      } else if (base2Exponent == info->minBinaryExp) {
+        errno = ERANGE; // Subnormal did not overflow to normal, so set ERANGE
+      }
+    }
+  }
+
+  if (info->end) *info->end = (char *)p;
   if (base2Exponent > info->maxBinaryExp) {
     overflow(info);
   } else if (base2Exponent < info->minBinaryExp - info->sigBits + 1) {
@@ -2296,33 +2141,33 @@
     switch (info->bytes) {
 #if ENABLE_BINARY16_SUPPORT
     case 2: {
-      uint16_t exponentBits = (uint16_t)(base2Exponent - info->minBinaryExp);
-      uint16_t raw = (uint16_t)
-        ((info->negative ? 0x8000U : 0U)
-        | (uint16_t)(exponentBits << 10)
-        | (significand_lsw & 0x3ffU));
+      uint16_t exponentBits = base2Exponent - info->minBinaryExp;
+      uint16_t raw =
+        (info->negative ? 0x8000U : 0)
+        | (exponentBits << 10)
+        | (significand_lsw & 0x3ffU);
       memcpy(info->dest, &raw, sizeof(raw));
       break;
     }
 #endif
 #if ENABLE_BINARY32_SUPPORT
     case 4: {
-      uint32_t exponentBits = (uint32_t)(base2Exponent - info->minBinaryExp);
-      uint32_t raw = (uint32_t)
-        ((info->negative ? 0x80000000UL : 0UL)
-        | (exponentBits << 23U)
-        | (uint32_t)(significand_lsw & 0x7fffffULL));
+      uint32_t exponentBits = base2Exponent - info->minBinaryExp;
+      uint32_t raw =
+        (info->negative ? 0x80000000UL : 0)
+        | (exponentBits << 23)
+        | (significand_lsw & 0x7fffffULL);
       memcpy(info->dest, &raw, sizeof(raw));
       break;
     }
 #endif
 #if ENABLE_BINARY64_SUPPORT
     case 8: {
-      uint64_t exponentBits = (uint64_t)(base2Exponent - info->minBinaryExp);
-      uint64_t raw = (uint64_t)
-        ((info->negative ? 0x8000000000000000ULL : 0UL)
-        | (exponentBits << 52U)
-        | (significand_lsw & 0xfffffffffffffULL));
+      uint64_t exponentBits = base2Exponent - info->minBinaryExp;
+      uint64_t raw =
+        (info->negative ? 0x8000000000000000ULL : 0)
+        | (exponentBits << 52)
+        | (significand_lsw & 0xfffffffffffffULL);
       memcpy(info->dest, &raw, sizeof(raw));
       break;
     }
@@ -2330,7 +2175,7 @@
 #if ENABLE_FLOAT80_SUPPORT
     case 10: {
       // TODO: Support big-endian
-      uint16_t exponentBits = (uint16_t)(base2Exponent - info->minBinaryExp);
+      uint16_t exponentBits = base2Exponent - info->minBinaryExp;
       memcpy(info->dest, &significand_lsw, sizeof(significand_lsw));
       info->dest[8] = exponentBits & 0xff;
       info->dest[9] = (exponentBits >> 8) | (info->negative ? 0x80 : 0);
@@ -2340,7 +2185,7 @@
 #if ENABLE_BINARY128_SUPPORT
     case 16: {
       // TODO: Support big-endian
-      uint16_t exponentBits = (uint16_t)(base2Exponent - info->minBinaryExp);
+      uint16_t exponentBits = base2Exponent - info->minBinaryExp;
       memcpy(info->dest, &significand_lsw, sizeof(significand_lsw));
       memcpy(info->dest + 8, &significand_msw, sizeof(significand_msw));
       info->dest[14] = exponentBits & 0xff;
@@ -2367,19 +2212,20 @@
 
 static void parseNan(const unsigned char *start, struct parseInfo *info) {
   const unsigned char *p = start + 3; // Skip "nan"
-  unsigned char _Alignas(sizeof(mp_word_t)) stackWorkArea[20];
+
+  unsigned char stackWorkArea[20];
   memset(stackWorkArea, 0, sizeof(stackWorkArea));
   const unsigned char *endNan = p;
   if (*p == '(') {
     p += 1;
-    unsigned base = 10;
+    int base = 10;
     if (*p == '0') {
-      p += 1;
-      if (*p == 'x') {
+      if (p[1] == 'x') {
         base = 16;
-        p += 1;
+        p += 2;
       } else {
         base = 8;
+        p += 1;
       }
     }
     mp_t stackMP = { (mp_word_t *)stackWorkArea,
@@ -2406,7 +2252,7 @@
     }
   }
   // TODO: Endianness.  This only works for little-endian.
-  memcpy(info->dest, stackWorkArea, (size_t)info->bytes);
+  memcpy(info->dest, stackWorkArea, info->bytes);
   switch (info->bytes) {
 #if ENABLE_BINARY16_SUPPORT
   case 2: {
@@ -2445,7 +2291,7 @@
   }
 #endif
   }
-  if (info->end) *info->end = (char *)(uintptr_t)p;
+  if (info->end) *info->end = (char *)p;
 }
 
 // This is used as the initial parse for all formats.
@@ -2474,6 +2320,7 @@
 fastParse64(struct parseInfo *info) {
   const unsigned char *p = (const unsigned char *)info->start;
 
+  const unsigned char *firstUnparsedDigit;
   uint64_t digits = 0;
   int digitCount = 0;
   int base10Exponent = 0;
@@ -2520,7 +2367,7 @@
         p += 3;
       }
       // Matched 'inf' or 'infinity' case-insensitive
-      if (info->end) *info->end = (char *)(uintptr_t)p;
+      if (info->end) *info->end = (char *)p;
       infinity(info);
       return 0;
     }
@@ -2571,20 +2418,18 @@
   }
 
   // Collect digits before the decimal point
-  const unsigned char *firstUnparsedDigit = p;
-  {
-    uint8_t t = (uint8_t)(*p - '0');
-    if (t < 10) {
-      digits = t;
+  firstUnparsedDigit = p;
+  uint8_t t = *p - '0';
+  if (t < 10) {
+    digits = t;
+    p += 1;
+    t = *p - '0';
+    while(t < 10) {
+      digits = 10 * digits + t;
       p += 1;
-      t = (uint8_t)(*p - '0');
-      while(t < 10) {
-        digits = 10 * digits + t;
-        p += 1;
-        t = (uint8_t)(*p - '0');
-      }
-      digitCount = (int)(p - firstUnparsedDigit);
-    }
+      t = *p - '0';
+    }
+    digitCount = (int)(p - firstUnparsedDigit);
   }
 
   // Try to match an optional decimal point
@@ -2633,29 +2478,29 @@
       }
       // "0.000000001234" has 4 digits
       firstUnparsedDigit = p;
-      unsigned t = (unsigned)(*p - '0');
+      unsigned t = *p - '0';
       if (t < 10) {
         p += 1;
         digits = t;
-        t = (unsigned)(*p - '0');
+        t = *p - '0';
         while (t < 10) {
           digits = 10 * digits + t;
           p += 1;
-          t = (unsigned)(*p - '0');
+          t = *p - '0';
         }
       }
       digitCount = (int)(p - firstUnparsedDigit);
     } else {
       // Perf: For canada.txt benchmark, this loop is ~30% of total runtime
-      unsigned t = (unsigned)(*p - '0');
+      unsigned t = *p - '0';
       if (t < 10) {
         p += 1;
         digits = 10 * digits + t;
-        t = (unsigned)(*p - '0');
+        t = *p - '0';
         while (t < 10) {
           p += 1;
           digits = 10 * digits + t;
-          t = (unsigned)(*p - '0');
+          t = *p - '0';
         }
       }
       digitCount += p - firstDigitAfterDecimalPoint;
@@ -2676,15 +2521,15 @@
     } else if (*p == '+') {
       p += 1;
     }
-    uint8_t t = (uint8_t)(*p - '0');
+    uint8_t t = *p - '0';
     if (t < 10) {
-      unsigned exp = t;
+      int exp = t;
       p += 1;
-      t = (uint8_t)(*p - '0');
+      t = *p - '0';
       while (t < 10) {
         p += 1;
         exp = 10 * exp + t;
-        t = (uint8_t)(*p - '0');
+        t = *p - '0';
       }
       if (p - exponentPhraseStart > 9) {
         // The exponent text was unusually long... re-parse
@@ -2702,13 +2547,13 @@
           exp = 99999999;
         }
       }
-      base10Exponent += (int)exp * negativeExponent;
+      base10Exponent += exp * negativeExponent;
     } else {
       p = exponentPhraseStart;
     }
   }
 
-  if (info->end) *info->end = (char *)(uintptr_t)p;
+  if (info->end) *info->end = (char *)p;
 
   // No non-zero digits, must be an explicit zero:
   // "0", ".000", "0.0", "0e0", "0.0e999", etc.
@@ -2735,7 +2580,7 @@
     const unsigned char *q = firstUnparsedDigit;
     while (i < 19) {
       // Note: Skip non-digit chars (e.g., decimal point)
-      unsigned t = (unsigned)(*q - '0');
+      unsigned t = *q - '0';
       if (t < 10) {
         digits = digits * 10 + t;
         i += 1;
@@ -2757,7 +2602,7 @@
   return 1; // Regular decimal case...
 
  fail:
-  if (info->end) *info->end = (char *)(uintptr_t)info->start;
+  if (info->end) *info->end = (char *)info->start;
   memset(info->dest, 0, info->bytes);
   return 0;
 }
@@ -2779,19 +2624,18 @@
   static const int minDecimalExp = -7;
   static const int maxDecimalExp = 5;
   static const int maxDecimalMidpointDigits = 22;
-  struct parseInfo info = {
-    .bytes = bytes,
-    .sigBits = sigBits,
-    .minBinaryExp = minBinaryExp,
-    .maxBinaryExp = maxBinaryExp,
-    .minDecimalExp = minDecimalExp,
-    .maxDecimalExp = maxDecimalExp,
-    .maxDecimalMidpointDigits = maxDecimalMidpointDigits,
-    .dest = dest,
-    .start = start,
-    .end = end,
-    .loc = loc,
-  };
+  struct parseInfo info;
+  info.bytes = bytes;
+  info.sigBits = sigBits;
+  info.minBinaryExp = minBinaryExp;
+  info.maxBinaryExp = maxBinaryExp;
+  info.minDecimalExp = minDecimalExp;
+  info.maxDecimalExp = maxDecimalExp;
+  info.maxDecimalMidpointDigits = maxDecimalMidpointDigits;
+  info.dest = dest;
+  info.start = start;
+  info.end = end;
+  info.loc = loc;
 
   // ================================================================
   // Parse the input (mostly)
@@ -2807,9 +2651,9 @@
   // ================================================================
   // Slow Path (varint calculation)
   // ================================================================
-  char _Alignas(sizeof(mp_word_t)) stackWorkArea[32];
+  char stackWorkArea[32];
   static const size_t stackWorkAreaWords = sizeof(stackWorkArea) / sizeof(mp_word_t);
-  generalSlowpath(&info, FENV_ROUNDING_MODE(), (mp_word_t *)stackWorkArea, stackWorkAreaWords, false);
+  generalSlowpath(&info, fegetround(),  (mp_word_t *)stackWorkArea, stackWorkAreaWords, 0);
 }
 #endif
 
@@ -2829,19 +2673,18 @@
   static const int minDecimalExp = -46;
   static const int maxDecimalExp = 40;
   static const int maxDecimalMidpointDigits = 113;
-  struct parseInfo info = {
-    .bytes = bytes,
-    .sigBits = sigBits,
-    .minBinaryExp = minBinaryExp,
-    .maxBinaryExp = maxBinaryExp,
-    .minDecimalExp = minDecimalExp,
-    .maxDecimalExp = maxDecimalExp,
-    .maxDecimalMidpointDigits = maxDecimalMidpointDigits,
-    .dest = dest,
-    .start = start,
-    .end = end,
-    .loc = loc,
-  };
+  struct parseInfo info;
+  info.bytes = bytes;
+  info.sigBits = sigBits;
+  info.minBinaryExp = minBinaryExp;
+  info.maxBinaryExp = maxBinaryExp;
+  info.minDecimalExp = minDecimalExp;
+  info.maxDecimalExp = maxDecimalExp;
+  info.maxDecimalMidpointDigits = maxDecimalMidpointDigits;
+  info.dest = dest;
+  info.start = start;
+  info.end = end;
+  info.loc = loc;
 
   // ================================================================
   // Parse the input (mostly)
@@ -2870,7 +2713,7 @@
   }
 #endif
 
-  int roundingMode = FENV_ROUNDING_MODE();
+  int roundingMode = fegetround();
 
 #if 1
   // ================================================================
@@ -2880,12 +2723,12 @@
   // upper/lower bounds for the correct answer.  If those bounds
   // agree, then we can return the result.
   int16_t exp10;
-  unsigned upperBoundOffset;
+  int upperBoundOffset;
   if (info.digitCount <= 19) {
-    exp10 = (int16_t)info.base10Exponent;
+    exp10 = info.base10Exponent;
     upperBoundOffset = 4;
   } else {
-    exp10 = (int16_t)(info.base10Exponent + info.digitCount - 19);
+    exp10 = info.base10Exponent + info.digitCount - 19;
     upperBoundOffset = 36;
   }
 
@@ -2926,13 +2769,10 @@
   uint64_t u = l + upperBoundOffset;
   uint32_t lowerSignificand, upperSignificand;
   switch (roundingMode) {
-#ifdef FE_TOWARDZERO
   case FE_TOWARDZERO:
     lowerSignificand = (l) >> 40;
     upperSignificand = (u) >> 40;
     break;
-#endif
-#ifdef FE_DOWNWARD
   case FE_DOWNWARD:
     if (info.negative) {
       lowerSignificand = (l + 0x0ffffffffff) >> 40;
@@ -2942,8 +2782,6 @@
       upperSignificand = (l + 4) >> 40;
     }
     break;
-#endif
-#ifdef FE_UPWARD
   case FE_UPWARD:
     if (!info.negative) {
       lowerSignificand = (l + 0x0ffffffffff) >> 40;
@@ -2953,11 +2791,8 @@
       upperSignificand = (u) >> 40;
     }
     break;
-#endif
-#ifdef FE_TONEAREST
+  default:
   case FE_TONEAREST:
-#endif
-  default:
     // Instead of worrying about exact ties-round-even, round lower
     // down (adding 0x7ff...ff) and upper up (adding 0x800...00) so
     // that exact ties fall through to be handled elsewhere.
@@ -2977,12 +2812,12 @@
     }
     // TODO: ... Subnormal? ...
   } else if (upperSignificand == lowerSignificand) {
-    uint32_t exponentBits = (uint32_t)(binaryExponent - minBinaryExp) << (sigBits - 1);
+    uint32_t exponentBits = ((uint32_t)binaryExponent - minBinaryExp) << (sigBits - 1);
     uint32_t significandMask = (((uint32_t)1 << (sigBits - 1)) - 1);
     uint32_t significandBits = lowerSignificand & significandMask;
     uint32_t signbit = info.negative ? 0x80000000UL : 0ULL;
     uint32_t raw = signbit | exponentBits | significandBits;
-    memcpy(info.dest, &raw, sizeof(raw));
+    memcpy(dest, &raw, sizeof(raw));
     return;
   }
 #endif
@@ -2990,9 +2825,9 @@
   // ================================================================
   // Slow Path (varint calculation)
   // ================================================================
-  char _Alignas(sizeof(mp_word_t)) stackWorkArea[128];
+  char stackWorkArea[128];
   static const size_t stackWorkAreaWords = sizeof(stackWorkArea) / sizeof(mp_word_t);
-  generalSlowpath(&info, FENV_ROUNDING_MODE(), (mp_word_t *)stackWorkArea, stackWorkAreaWords, false);
+  generalSlowpath(&info, fegetround(),  (mp_word_t *)stackWorkArea, stackWorkAreaWords, 0);
 }
 #endif
 
@@ -3013,19 +2848,18 @@
   static const int minDecimalExp = -325;
   static const int maxDecimalExp = 310;
   static const int maxDecimalMidpointDigits = 768;
-  struct parseInfo info = {
-    .bytes = bytes,
-    .sigBits = sigBits,
-    .minBinaryExp = minBinaryExp,
-    .maxBinaryExp = maxBinaryExp,
-    .minDecimalExp = minDecimalExp,
-    .maxDecimalExp = maxDecimalExp,
-    .maxDecimalMidpointDigits = maxDecimalMidpointDigits,
-    .dest = dest,
-    .start = start,
-    .end = end,
-    .loc = loc,
-  };
+  struct parseInfo info;
+  info.bytes = bytes;
+  info.sigBits = sigBits;
+  info.minBinaryExp = minBinaryExp;
+  info.maxBinaryExp = maxBinaryExp;
+  info.minDecimalExp = minDecimalExp;
+  info.maxDecimalExp = maxDecimalExp;
+  info.maxDecimalMidpointDigits = maxDecimalMidpointDigits;
+  info.dest = dest;
+  info.start = start;
+  info.end = end;
+  info.loc = loc;
 
   // ================================================================
   // Parse the input (mostly)
@@ -3086,8 +2920,8 @@
       if (info.digitCount <= 19) {
         // We can give exact inputs to fma if we have <= 19 digits
         // and base10Exponent is in [1..18].
-        uint64_t lowMask = 0x7ff;
-        uint64_t highMask = ~lowMask;
+        int64_t lowMask = 0x7ff;
+        int64_t highMask = ~lowMask;
         // digits has <= 64 bits (19 digits)
         double highDigits = (double)(info.digits & highMask); // <= 53 bits
         double lowDigits = (double)(info.digits & lowMask); // 11 bits
@@ -3095,7 +2929,7 @@
         if (info.negative) p10 = -p10;
         double u = lowDigits * p10; // Exact (11 bits + 42 bits)
         // Inputs to fma are all exact, so result is correctly rounded
-        double result = __builtin_fma(highDigits, p10, u);
+        double result = fma(highDigits, p10, u);
         memcpy(info.dest, &result, sizeof(result));
         return;
       }
@@ -3103,7 +2937,7 @@
   }
 #endif
 
-  int roundingMode = FENV_ROUNDING_MODE();
+  int roundingMode = fegetround();
 
 #if 1
   // ================================================================
@@ -3111,9 +2945,9 @@
   // ================================================================
   int16_t exp10;
   // Total possible inaccuracy in our calculations below
-  unsigned intervalWidth;
+  int intervalWidth;
   if (info.digitCount <= 19) {
-    exp10 = (int16_t)info.base10Exponent;
+    exp10 = info.base10Exponent;
     // We have all the digits, so our upper/lower bounds
     // on the significand are the same, which makes the final
     // bounds fairly tight.
@@ -3126,7 +2960,7 @@
     // have upper/lower bounds for 10^p.
     // info.digits already has the first 19 digits, we just need to
     // adjust the effective exponent.
-    exp10 = (int16_t)(info.base10Exponent + info.digitCount - 19);
+    exp10 = info.base10Exponent + info.digitCount - 19;
     // The non-trivial significand bounds lead to a wider final interval.
     // This still gives us success ~96% of the time.
     intervalWidth = 80;
@@ -3185,36 +3019,25 @@
   // bits. For example, to precisely round away from zero, we
   // would ideally want to add 0x7ff.ffffffffffffffff.  Rounding that
   // value down/up to the nearest integer gives us 0x7ff, 0x800.
-  unsigned lowerRoundOffset, upperRoundOffset;
-  {
-    bool negative = info.negative;
-    switch (roundingMode) {
-#ifdef FE_UPWARD
-    case FE_UPWARD:
-      negative = !negative;
-      // FALL THROUGH
-#endif
-#ifdef FE_DOWNWARD
-    case FE_DOWNWARD:
-      if (negative) {
-        lowerRoundOffset = 0x7ff; upperRoundOffset = 0x800 + intervalWidth;
-        break;
-      }
-      // FALL THROUGH
-#endif
-#ifdef FE_TOWARDZERO
-    case FE_TOWARDZERO:
-      lowerRoundOffset = 0; upperRoundOffset = intervalWidth;
+  int lowerRoundOffset, upperRoundOffset;
+  int negative = info.negative;
+  switch (roundingMode) {
+  case FE_UPWARD:
+    negative = !negative;
+    // FALL THROUGH
+  case FE_DOWNWARD:
+    if (negative) {
+      lowerRoundOffset = 0x7ff; upperRoundOffset = 0x800 + intervalWidth;
       break;
-#endif
-#ifdef FE_TONEAREST
-    case FE_TONEAREST:
-#endif
-    default:
-      (void)negative;
-      lowerRoundOffset = 0x3ff; upperRoundOffset = 0x400 + intervalWidth;
-      break;
-    }
+    }
+    // FALL THROUGH
+  case FE_TOWARDZERO:
+    lowerRoundOffset = 0; upperRoundOffset = intervalWidth;
+    break;
+  default:
+  case FE_TONEAREST:
+    lowerRoundOffset = 0x3ff; upperRoundOffset = 0x400 + intervalWidth;
+    break;
   }
   uint64_t lowerSignificand = (l + lowerRoundOffset) >> 11;
   uint64_t upperSignificand = (l + upperRoundOffset) >> 11;
@@ -3239,29 +3062,20 @@
     if (shift < 64) {
       assert(0 < shift && shift < 64);
       uint64_t lro, uro;
-      bool negative = info.negative;
+      int negative = info.negative;
       switch (roundingMode) {
-#ifdef FE_UPWARD
       case FE_UPWARD:
         negative = !negative;
         // FALL THROUGH
-#endif
-#ifdef FE_DOWNWARD
       case FE_DOWNWARD:
         if (negative) {
           lro = (1ULL << (shift)) - 1; uro = lro + intervalWidth; break;
         }
         // FALL THROUGH
-#endif
-#ifdef FE_TOWARDZERO
       case FE_TOWARDZERO:
         lro = 0; uro = intervalWidth; break;
-#endif
-#ifdef FE_TONEAREST
+      default:
       case FE_TONEAREST:
-#endif
-      default:
-        (void)negative;
         lro = (1ULL << (shift - 1)) - 1; uro = (1ULL << (shift - 1)) + intervalWidth; break;
       }
       lowerSignificand = (l + lro) >> shift;
@@ -3276,18 +3090,18 @@
         if (raw != 0x0010000000000000ULL) {
           errno = ERANGE;
         }
-        memcpy(info.dest, &raw, sizeof(raw));
+        memcpy(dest, &raw, sizeof(raw));
         return;
       }
     }
   } else if (upperSignificand == lowerSignificand) {
     // Normal
-    uint64_t exponentBits = (uint64_t)(adjustedBinaryExponent - minBinaryExp) << (sigBits - 1);
+    uint64_t exponentBits = ((uint64_t)adjustedBinaryExponent - minBinaryExp) << (sigBits - 1);
     uint64_t significandMask = (((uint64_t)1 << (sigBits - 1)) - 1);
     uint64_t significandBits = lowerSignificand & significandMask;
     uint64_t signbit = info.negative ? 0x8000000000000000ULL : 0ULL;
     uint64_t raw = signbit | exponentBits | significandBits;
-    memcpy(info.dest, &raw, sizeof(raw));
+    memcpy(dest, &raw, sizeof(raw));
     return;
   }
   // TODO: If we fall through, should we try refining the
@@ -3300,9 +3114,9 @@
   // ================================================================
   // Random testing suggests this step only runs about 3% of the
   // time, so we focus here on optimizing for code size rather than perf.
-  char _Alignas(sizeof(mp_word_t)) stackWorkArea[656];
+  char stackWorkArea[656];
   static const size_t stackWorkAreaWords = sizeof(stackWorkArea) / sizeof(mp_word_t);
-  generalSlowpath(&info, roundingMode, (mp_word_t *)stackWorkArea, stackWorkAreaWords, false);
+  generalSlowpath(&info, roundingMode,  (mp_word_t *)stackWorkArea, stackWorkAreaWords, 0);
 }
 #endif
 
@@ -3341,7 +3155,7 @@
 #define extractHigh64(x) ((x).high)
 #define isZero(x) ((x).low == 0 && (x).high == 0)
 #define isEqual(lhs, rhs) ((lhs).low == (rhs).low && ((lhs).high == (rhs).high))
-static my_uint128_t shiftLeft(my_uint128_t lhs, int rhs) {
+my_uint128_t shiftLeft(my_uint128_t lhs, int rhs) {
   if (rhs > 64) {
     lhs.high = lhs.low << (rhs - 64);
     lhs.low = 0;
@@ -3354,7 +3168,7 @@
   }
   return lhs;
 }
-static my_uint128_t shiftRight(my_uint128_t lhs, int rhs) {
+my_uint128_t shiftRight(my_uint128_t lhs, int rhs) {
   if (rhs > 64) {
     lhs.low = lhs.high >> (rhs - 64);
     lhs.high = 0;
@@ -3367,18 +3181,18 @@
   }
   return lhs;
 }
-static my_uint128_t create128FromHighLow64(uint64_t high, uint64_t low) {
+my_uint128_t create128FromHighLow64(uint64_t high, uint64_t low) {
   my_uint128_t result = {low, high};
   return result;
 }
-static my_uint128_t add128x64(my_uint128_t lhs, uint64_t rhs) {
+my_uint128_t add128x64(my_uint128_t lhs, uint64_t rhs) {
   if (lhs.low > UINT64_MAX - rhs) {
     lhs.high += 1;
   }
   lhs.low += rhs;
   return lhs;
 }
-static my_uint128_t add128x128(my_uint128_t lhs, my_uint128_t rhs) {
+my_uint128_t add128x128(my_uint128_t lhs, my_uint128_t rhs) {
   if (lhs.low > UINT64_MAX - rhs.low) {
     lhs.high += 1;
   }
@@ -3386,7 +3200,7 @@
   lhs.high += rhs.high;
   return lhs;
 }
-static my_uint128_t fullMultiply64x64(uint64_t lhs, uint64_t rhs) {
+my_uint128_t fullMultiply64x64(uint64_t lhs, uint64_t rhs) {
   uint64_t a = (lhs >> 32) * (rhs >> 32);
   uint64_t b = (lhs >> 32) * (rhs & UINT32_MAX);
   uint64_t c = (lhs & UINT32_MAX) * (rhs >> 32);
@@ -3395,11 +3209,11 @@
   return create128FromHighLow64(a + (b >> 32) + (c >> 32),
                                 (b << 32) + (d & UINT32_MAX));
 }
-static my_uint128_t multiply128xInt(my_uint128_t lhs, int rhs) {
-  uint64_t a = (lhs.low & UINT32_MAX) * (uint64_t)rhs;
-  uint64_t b = (lhs.low >> 32) * (uint64_t)rhs;
+my_uint128_t multiply128xInt(my_uint128_t lhs, int rhs) {
+  uint64_t a = (lhs.low & UINT32_MAX) * rhs;
+  uint64_t b = (lhs.low >> 32) * rhs;
   b += (a >> 32);
-  lhs.high = (lhs.high * (uint64_t)rhs) + (b >> 32);
+  lhs.high = (lhs.high * rhs) + (b >> 32);
   lhs.low = (a & UINT32_MAX) + (b << 32);
   return lhs;
 }
@@ -3460,12 +3274,12 @@
 
 static int highPrecisionIntervalPath(struct parseInfo *info, int roundingMode) {
   int16_t exp10;
-  unsigned upperBoundOffset;
+  int upperBoundOffset;
   if (info->digitCount <= 38) {
-    exp10 = (int16_t)info->base10Exponent;
+    exp10 = info->base10Exponent;
     upperBoundOffset = 16; // FIXME
   } else {
-    exp10 = (int16_t)(info->base10Exponent + info->digitCount - 38);
+    exp10 = info->base10Exponent + info->digitCount - 38;
     upperBoundOffset = 272;  // FIXME
   }
 
@@ -3483,7 +3297,7 @@
         p++;
       }
       digits = multiply128xInt(digits, 10);
-      digits = add128x64(digits, (uint64_t)(*p - '0'));
+      digits = add128x64(digits, *p - '0');
       p += 1;
     }
     if (extractHigh64(digits) != 0) {
@@ -3516,14 +3330,11 @@
 
   // Upper/lower bounds for the 64-bit significand
   my_uint128_t u = add128x64(l, upperBoundOffset);
-  bool negative = info->negative;
+  int negative = info->negative;
   switch (roundingMode) {
-#ifdef FE_DOWNWARD
   case FE_DOWNWARD:
     negative = !negative;
     // FALL THROUGH
-#endif
-#ifdef FE_UPWARD
   case FE_UPWARD:
     if (!negative) {
       my_uint128_t offset = create128FromHighLow64(UINT64_MAX, UINT64_MAX);
@@ -3534,16 +3345,10 @@
       break;
     }
     // FALL THROUGH
-#endif
-#ifdef FE_TOWARDZERO
   case FE_TOWARDZERO:
     break;
-#endif
-#ifdef FE_TONEAREST
-  case FE_TONEAREST:
-#endif
-  default: {
-    (void)negative;
+  default:
+  case FE_TONEAREST: {
     my_uint128_t offset = create128FromHighLow64(UINT64_MAX, UINT64_MAX);
     offset = shiftRight(offset, info->sigBits + 1);
     l = add128x128(l, offset);
@@ -3571,7 +3376,7 @@
     switch (info->bytes) {
     case 10: {
       uint16_t signbit = info->negative ? 0x8000U : 0U;
-      uint16_t exponentBits = signbit | (uint16_t)(binaryExponent - info->minBinaryExp);
+      uint16_t exponentBits = signbit | ((uint16_t)binaryExponent - info->minBinaryExp);
       uint64_t significandBits = extractLow64(lowerSignificand);
       memcpy(info->dest, &significandBits, sizeof(significandBits));
       memcpy(info->dest + 8, &exponentBits, sizeof(exponentBits));
@@ -3579,7 +3384,7 @@
     }
     case 16: {
       uint16_t signbit = info->negative ? 0x8000U : 0U;
-      uint16_t exponentBits = signbit | (uint16_t)(binaryExponent - info->minBinaryExp);
+      uint16_t exponentBits = signbit | ((uint16_t)binaryExponent - info->minBinaryExp);
       memcpy(info->dest, &lowerSignificand, sizeof(lowerSignificand));
       memcpy(info->dest + 14, &exponentBits, sizeof(exponentBits));
       return 1;
@@ -3607,19 +3412,18 @@
   static const int minDecimalExp = -5000;
   static const int maxDecimalExp = 5000;
   static const int maxDecimalMidpointDigits = 11515;
-  struct parseInfo info = {
-    .bytes = bytes,
-    .sigBits = sigBits,
-    .minBinaryExp = minBinaryExp,
-    .maxBinaryExp = maxBinaryExp,
-    .minDecimalExp = minDecimalExp,
-    .maxDecimalExp = maxDecimalExp,
-    .maxDecimalMidpointDigits = maxDecimalMidpointDigits,
-    .dest = dest,
-    .start = start,
-    .end = end,
-    .loc = loc,
-  };
+  struct parseInfo info;
+  info.bytes = bytes;
+  info.sigBits = sigBits;
+  info.minBinaryExp = minBinaryExp;
+  info.maxBinaryExp = maxBinaryExp;
+  info.minDecimalExp = minDecimalExp;
+  info.maxDecimalExp = maxDecimalExp;
+  info.maxDecimalMidpointDigits = maxDecimalMidpointDigits;
+  info.dest = dest;
+  info.start = start;
+  info.end = end;
+  info.loc = loc;
 
   // ================================================================
   // Parse the input (mostly)
@@ -3653,7 +3457,7 @@
   }
 #endif
 
-  int roundingMode = FENV_ROUNDING_MODE();
+  int roundingMode = fegetround();
 
 #if ENABLE_FLOAT80_OPTIMIZATIONS
   if (highPrecisionIntervalPath(&info, roundingMode)) {
@@ -3664,9 +3468,9 @@
   // ================================================================
   // Slow Path (varint calculation)
   // ================================================================
-  char _Alignas(sizeof(mp_word_t)) stackWorkArea[1536];
+  char stackWorkArea[1536];
   static const size_t stackWorkAreaWords = sizeof(stackWorkArea) / sizeof(mp_word_t);
-  generalSlowpath(&info, roundingMode, (mp_word_t *)stackWorkArea, stackWorkAreaWords, true);
+  generalSlowpath(&info, roundingMode,  (mp_word_t *)stackWorkArea, stackWorkAreaWords, 1);
 }
 #endif
 
@@ -3687,19 +3491,18 @@
   static const int minDecimalExp = -5000;
   static const int maxDecimalExp = 5000;
   static const int maxDecimalMidpointDigits = 11564;
-  struct parseInfo info = {
-    .bytes = bytes,
-    .sigBits = sigBits,
-    .minBinaryExp = minBinaryExp,
-    .maxBinaryExp = maxBinaryExp,
-    .minDecimalExp = minDecimalExp,
-    .maxDecimalExp = maxDecimalExp,
-    .maxDecimalMidpointDigits = maxDecimalMidpointDigits,
-    .dest = dest,
-    .start = start,
-    .end = end,
-    .loc = loc,
-  };
+  struct parseInfo info;
+  info.bytes = bytes;
+  info.sigBits = sigBits;
+  info.minBinaryExp = minBinaryExp;
+  info.maxBinaryExp = maxBinaryExp;
+  info.minDecimalExp = minDecimalExp;
+  info.maxDecimalExp = maxDecimalExp;
+  info.maxDecimalMidpointDigits = maxDecimalMidpointDigits;
+  info.dest = dest;
+  info.start = start;
+  info.end = end;
+  info.loc = loc;
 
   // ================================================================
   // Parse the input (mostly)
@@ -3735,7 +3538,7 @@
   }
 #endif
 
-  int roundingMode = FENV_ROUNDING_MODE();
+  int roundingMode = fegetround();
 
 #if ENABLE_BINARY128_OPTIMIZATIONS
   if (highPrecisionIntervalPath(&info, roundingMode)) {
@@ -3746,9 +3549,9 @@
   // ================================================================
   // Slow Path (varint calculation)
   // ================================================================
-  char _Alignas(sizeof(mp_word_t)) stackWorkArea[1536];
+  char stackWorkArea[1536];
   static const size_t stackWorkAreaWords = sizeof(stackWorkArea) / sizeof(mp_word_t);
-  generalSlowpath(&info, roundingMode, (mp_word_t *)stackWorkArea, stackWorkAreaWords, true);
+  generalSlowpath(&info, roundingMode,  (mp_word_t *)stackWorkArea, stackWorkAreaWords, 1);
 }
 #endif
 
@@ -3772,7 +3575,7 @@
 void strtoencf16(unsigned char * restrict encptr,
                       const char * restrict nptr,
                       char ** restrict endptr) {
-  _ffpp_strtoencf16_l(encptr, nptr, endptr, strtofp_current_locale());
+ _ffpp_strtoencf16_l(encptr, nptr, endptr, strtofp_current_locale());
 }
 #endif
 
@@ -3826,7 +3629,7 @@
 #if ENABLE_BINARY64_SUPPORT && LONG_DOUBLE_IS_BINARY64
 // TS 18661-3 `strtoencf64x` API
 // If `long double` is binary64, we assume Float64x is binary64
-void strtoencf64x(unsigned char * restrict encptr,
+void strtoencf64x(unsigned char *restrict encptr,
                        const char * restrict nptr,
                        char ** restrict endptr) {
   _ffpp_strtoencf64_l(encptr, nptr, endptr, strtofp_current_locale());
@@ -3880,7 +3683,7 @@
 
 #if ENABLE_FLOAT80_SUPPORT && ENABLE_LOCALE_SUPPORT
 // Non-standard but helpful for testing.
-void strtoencf80_l(unsigned char * restrict encptr,
+void strtoencf80_l(unsigned char *restrict encptr,
                         const char * restrict nptr,
                         char ** restrict endptr,
                         strtofp_locale_t loc) {
@@ -3891,7 +3694,7 @@
 #if ENABLE_FLOAT80_SUPPORT && LONG_DOUBLE_IS_FLOAT80
 // TS 18661-3 `strtoencf64x` API
 // If `long double` is float80, assume `Float64x` is float80
-void strtoencf64x(unsigned char * restrict encptr,
+void strtoencf64x(unsigned char *restrict encptr,
                        const char * restrict nptr,
                        char ** restrict endptr) {
   _ffpp_strtoencf80_l(encptr, nptr, endptr, strtofp_current_locale());