diff options
-rw-r--r-- | src/fenv/__FE_DFL_ENV.c | 8 | ||||
-rw-r--r-- | src/fenv/__fenv_h.c | 2 | ||||
-rw-r--r-- | src/fenv/_fenv.h | 22 | ||||
-rw-r--r-- | src/fenv/fegetenv.c | 12 | ||||
-rw-r--r-- | src/fenv/feholdexcept.c | 4 | ||||
-rw-r--r-- | src/fenv/fesetenv.c | 2 | ||||
-rw-r--r-- | src/fenv/fesetexceptflag.c | 2 | ||||
-rw-r--r-- | src/fenv/feupdateenv.c | 1 |
8 files changed, 41 insertions, 12 deletions
diff --git a/src/fenv/__FE_DFL_ENV.c b/src/fenv/__FE_DFL_ENV.c new file mode 100644 index 00000000..11d0c604 --- /dev/null +++ b/src/fenv/__FE_DFL_ENV.c @@ -0,0 +1,8 @@ +#include <fenv.h> +#include "_fenv.h" + +static struct __fenv_t __fe_dfl_env = { + 0, +}; + +const fenv_t __FE_DFL_ENV = { &__fe_dfl_env }; diff --git a/src/fenv/__fenv_h.c b/src/fenv/__fenv_h.c index 0cebd658..331e852f 100644 --- a/src/fenv/__fenv_h.c +++ b/src/fenv/__fenv_h.c @@ -1,6 +1,6 @@ #include "_fenv.h" -struct __fenv __fenv_h = { 0 }; +struct __fenv_h __fenv_h = { 0 }; /* STDC(-1) diff --git a/src/fenv/_fenv.h b/src/fenv/_fenv.h index 0455fef3..debfc2ad 100644 --- a/src/fenv/_fenv.h +++ b/src/fenv/_fenv.h @@ -1,25 +1,33 @@ #include <fenv.h> #include "_safety.h" +struct __fenv_t { + int flags; +}; + extern struct __fenv_h { fexcept_t *valid_fexcept; size_t nvalid_fexcept; - fenv_t *valid_fenv; - size_t nvalid_fenv; + struct __fenv_t *fenv; + size_t nfenv; } __fenv_h; #ifdef NDEBUG #define ASSERT_VALID_EXCEPTION_MASK(_n) (void)(_n) -#define ASSERT_PREVIOUS_FEXCEPT(_f, _e) (void)(_f) -#define ASSERT_PREVIOUS_FENV(_f) (void)(_f) +#define ASSERT_PREV_FEXCEPT(_f, _e) (void)(_f) +#define ASSERT_PREV_FENV(_f) (void)(_f) #else #define ASSERT_VALID_EXCEPTION_MASK(_n) do { \ if (((_n) & ~(FE_ALL_EXCEPT)) != 0) { \ - UNDEFINED("In call to %s(), exception mask 0x(%jx) is not valid", __func__, (uintmax_t)(_n)); \ + UNDEFINED("In call to %s(): exception mask 0x(%jx) is not valid", __func__, (uintmax_t)(_n)); \ } \ } while (0) /* TODO!!! */ -#define ASSERT_PREVIOUS_FEXCEPT(_f, _e) (void)(_f) -#define ASSERT_PREVIOUS_FENV(_f) (void)(_f) +#define ASSERT_PREV_FEXCEPT(_f, _e) (void)(_f) +#define ASSERT_PREV_FENV(__f) do { \ + if (!(envp == FE_DFL_ENV) || (envp->__impl >= __fenv_h.fenv && envp->__impl <= __fenv_h.fenv + __fenv_h.nfenv)) { \ + UNDEFINED("In call to %s(): %s must be previously set by calling fegetenv() or feholdexcept()", __func__, #__f); \ + } \ +} while (0) #endif diff --git a/src/fenv/fegetenv.c b/src/fenv/fegetenv.c index 9a40e83b..554e2b9c 100644 --- a/src/fenv/fegetenv.c +++ b/src/fenv/fegetenv.c @@ -1,10 +1,20 @@ #include <fenv.h> +#include <stdlib.h> #include "_fenv.h" int fegetenv(fenv_t *envp) { SIGNAL_SAFE(0); - (void)envp; + ASSERT_NONNULL(envp); + if (!(envp->__impl >= __fenv_h.fenv && envp->__impl <= __fenv_h.fenv + __fenv_h.nfenv)) { + struct __fenv_t *tmp = realloc(__fenv_h.fenv, sizeof(*__fenv_h.fenv) * (__fenv_h.nfenv + 1)); + if (tmp == NULL) { + abort(); + } + __fenv_h.fenv = tmp; + envp->__impl = &(__fenv_h.fenv[__fenv_h.nfenv++]); + } + /* TODO: save state in envp->__impl */ return 0; } diff --git a/src/fenv/feholdexcept.c b/src/fenv/feholdexcept.c index 51ef526b..71c713d0 100644 --- a/src/fenv/feholdexcept.c +++ b/src/fenv/feholdexcept.c @@ -4,7 +4,9 @@ int feholdexcept(fenv_t *envp) { SIGNAL_SAFE(0); - (void)envp; + ASSERT_NONNULL(envp); + fegetenv(envp); + /* TODO: clears the floating-point status flags, and then installs a non-stop (continue on floating-point exceptions) mode, if available, for all floating-point exceptions. */ return 0; } diff --git a/src/fenv/fesetenv.c b/src/fenv/fesetenv.c index b9debb35..e15af3d2 100644 --- a/src/fenv/fesetenv.c +++ b/src/fenv/fesetenv.c @@ -4,7 +4,7 @@ int fesetenv(const fenv_t *envp) { SIGNAL_SAFE(0); - ASSERT_PREVIOUS_FENV(envp); + ASSERT_PREV_FENV(envp); (void)envp; return 0; } diff --git a/src/fenv/fesetexceptflag.c b/src/fenv/fesetexceptflag.c index 55f5b1a1..a68903f2 100644 --- a/src/fenv/fesetexceptflag.c +++ b/src/fenv/fesetexceptflag.c @@ -4,7 +4,7 @@ int fesetexceptflag(const fexcept_t *flagp, int excepts) { SIGNAL_SAFE(0); - ASSERT_PREVIOUS_FEXCEPT(flagp, excepts); + ASSERT_PREV_FEXCEPT(flagp, excepts); ASSERT_VALID_EXCEPTION_MASK(excepts); (void)flagp; (void)excepts; return 0; diff --git a/src/fenv/feupdateenv.c b/src/fenv/feupdateenv.c index 2b7c8626..07a03986 100644 --- a/src/fenv/feupdateenv.c +++ b/src/fenv/feupdateenv.c @@ -4,6 +4,7 @@ int feupdateenv(const fenv_t *envp) { SIGNAL_SAFE(0); + ASSERT_PREV_FENV(envp); (void)envp; return 0; } |