summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fenv/__FE_DFL_ENV.c8
-rw-r--r--src/fenv/__fenv_h.c2
-rw-r--r--src/fenv/_fenv.h22
-rw-r--r--src/fenv/fegetenv.c12
-rw-r--r--src/fenv/feholdexcept.c4
-rw-r--r--src/fenv/fesetenv.c2
-rw-r--r--src/fenv/fesetexceptflag.c2
-rw-r--r--src/fenv/feupdateenv.c1
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;
}