diff options
-rw-r--r-- | src/fenv/_fenv.h | 22 | ||||
-rw-r--r-- | src/fenv/fegetexceptflag.c | 10 | ||||
-rw-r--r-- | src/fenv/fesetexceptflag.c | 4 |
3 files changed, 28 insertions, 8 deletions
diff --git a/src/fenv/_fenv.h b/src/fenv/_fenv.h index debfc2ad..b35ec050 100644 --- a/src/fenv/_fenv.h +++ b/src/fenv/_fenv.h @@ -5,9 +5,14 @@ struct __fenv_t { int flags; }; +struct __fexcept_t { + int mask; + int set; +}; + extern struct __fenv_h { - fexcept_t *valid_fexcept; - size_t nvalid_fexcept; + struct __fexcept_t *fexcept; + size_t nfexcept; struct __fenv_t *fenv; size_t nfenv; } __fenv_h; @@ -23,10 +28,17 @@ extern struct __fenv_h { } \ } while (0) -/* TODO!!! */ -#define ASSERT_PREV_FEXCEPT(_f, _e) (void)(_f) +#define ASSERT_PREV_FEXCEPT(__f, __e) do { \ + if (!(__f->__impl >= __fenv_h.fexcept && __f->__impl <= __fenv_h.fexcept + __fenv_h.nfexcept)) { \ + UNDEFINED("In call to %s(): %s must be previously set by calling fegetexceptflag()", __func__, #__f); \ + } \ + if ((__f->__impl->mask & (__e)) != (__e)) { \ + UNDEFINED("In call to %s(): Attempting to set flags not specified by previous call to fegetexceptflag()", __func__); \ + } \ +} while (0) + #define ASSERT_PREV_FENV(__f) do { \ - if (!(envp == FE_DFL_ENV) || (envp->__impl >= __fenv_h.fenv && envp->__impl <= __fenv_h.fenv + __fenv_h.nfenv)) { \ + if (!(__f == FE_DFL_ENV) || (__f->__impl >= __fenv_h.fenv && __f->__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) diff --git a/src/fenv/fegetexceptflag.c b/src/fenv/fegetexceptflag.c index 921dc1b8..ef8517f9 100644 --- a/src/fenv/fegetexceptflag.c +++ b/src/fenv/fegetexceptflag.c @@ -5,7 +5,15 @@ int fegetexceptflag(fexcept_t *flagp, int excepts) { SIGNAL_SAFE(0); ASSERT_VALID_EXCEPTION_MASK(excepts); - (void)flagp; (void)excepts; + if (!(flagp->__impl >= __fenv_h.fexcept && flagp->__impl <= __fenv_h.fexcept + __fenv_h.nfexcept)) { + struct __fexcept_t *tmp = realloc(__fenv_h.fexcept, sizeof(*__fenv_h.fexcept) * (__fenv_h.nfexcept + 1)); + if (tmp == NULL) { + abort(); + } + __fenv_h.fexcept = tmp; + flagp->__impl = &(__fenv_h.fexcept[__fenv_h.nfexcept++]); + } + flagp->__impl->mask = excepts; return 0; } diff --git a/src/fenv/fesetexceptflag.c b/src/fenv/fesetexceptflag.c index a68903f2..4c50a76d 100644 --- a/src/fenv/fesetexceptflag.c +++ b/src/fenv/fesetexceptflag.c @@ -4,9 +4,9 @@ int fesetexceptflag(const fexcept_t *flagp, int excepts) { SIGNAL_SAFE(0); - ASSERT_PREV_FEXCEPT(flagp, excepts); ASSERT_VALID_EXCEPTION_MASK(excepts); - (void)flagp; (void)excepts; + ASSERT_PREV_FEXCEPT(flagp, excepts); + flagp->__impl->set |= excepts; return 0; } |