aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/disp.c77
-rw-r--r--src/disp.h20
2 files changed, 75 insertions, 22 deletions
diff --git a/src/disp.c b/src/disp.c
index 18b6168..c0294fe 100644
--- a/src/disp.c
+++ b/src/disp.c
@@ -25,10 +25,6 @@
#include "disp.h"
-/* Reserved return values for the read_input function. */
-#define DISP_ERR INT_MAX
-#define DISP_RELOAD (INT_MAX - 1)
-
#define dlsym_and_check(dest, name) \
dest->name = dlsym(dest->dl_handle, #name); \
if ((!dest->name) || (dest->name == dest->dl_handle)) { \
@@ -36,42 +32,85 @@
fprintf(stderr, "calculer: %s\n", msg); \
dlclose(dest->dl_handle); \
free(dest); \
- return NULL; \
+ return -1; \
}
-struct disp *
-get_disp(char *disp_name)
+static int
+load_symbols(struct disp *disp)
{
-#ifndef NDEBUG
- /* displays are shared libraries */
- char so_path[64] = {0};
- strcpy(so_path, "./src/.libs/");
- strcat(so_path, disp_name);
- strcat(so_path, ".so.0.0.0");
- void *handle = dlopen(so_path, RTLD_LAZY);
+ void *handle = dlopen(disp->so_path, RTLD_LAZY);
if (!handle)
{
- char *msg = dlerror();
- fprintf(stderr, "calculer: %s\n", msg);
+ fprintf(stderr, "calculer: %s\n", dlerror());
exit(1);
}
- printf("INFO: successfully loaded symbols from \"%s\"\n", so_path);
+#ifndef NDEBUG
+ printf("INFO: successfully loaded symbols from \"%s\"\n", disp->so_path);
+#endif
- struct disp *disp = malloc(sizeof(*disp));
disp->dl_handle = handle;
dlsym_and_check(disp, init);
dlsym_and_check(disp, display_calc);
dlsym_and_check(disp, read_input);
dlsym_and_check(disp, display_res);
dlsym_and_check(disp, destroy);
+#ifndef NDEBUG
dlsym_and_check(disp, pre_reload);
dlsym_and_check(disp, post_reload);
+#endif
+ return 0;
+}
- return disp;
+struct disp *
+get_disp(char *disp_name)
+{
+#ifndef NDEBUG
+ /* displays are shared libraries */
+ char so_path[64] = {0};
+ strcpy(so_path, "./src/.libs/");
+ strcat(so_path, disp_name);
+ strcat(so_path, ".so.0.0.0");
+ struct disp *disp = malloc(sizeof(*disp));
+ disp->so_path = strdup(so_path);
+
+ return load_symbols(disp) == 0 ? disp : NULL;
#else
# error "not available yet"
#endif
return NULL;
}
+
+void
+destroy_disp(struct disp *disp)
+{
+ disp->destroy();
+ dlclose(disp->dl_handle);
+ free(disp->so_path);
+ free(disp);
+}
+
+#ifndef NDEBUG
+void
+disp_reload(struct disp *disp)
+{
+ int status;
+ printf("INFO: saving state\n");
+ void *state = disp->pre_reload();
+ printf("INFO: closing shared library\n");
+ dlclose(disp->dl_handle);
+ printf("INFO: reloading symbols\n");
+ status = load_symbols(disp);
+
+ if (status == -1)
+ {
+ printf("calculer: %s\n", dlerror());
+ exit(1);
+ }
+
+ printf("INFO: loading state\n");
+ disp->post_reload(state);
+ printf("INFO: reloading done\n");
+}
+#endif
diff --git a/src/disp.h b/src/disp.h
index d0b2d19..454378d 100644
--- a/src/disp.h
+++ b/src/disp.h
@@ -18,11 +18,19 @@
#define DISP_H
#include <stdbool.h>
+#include <limits.h>
/* Available display types. */
#define DISP_CLI "cli"
#define DISP_RAY "ray"
+/* Reserved return values for the read_input function. */
+#ifndef NDEBUG
+# define DISP_RELOAD INT_MAX
+#endif
+#define DISP_QUIT (INT_MAX - 1)
+#define DISP_ERR (INT_MAX - 2)
+
struct disp {
void *dl_handle;
void (*init)(void);
@@ -30,13 +38,19 @@ struct disp {
int (*read_input)(void);
void (*display_res)(bool, int);
void (*destroy)(void);
+#ifndef NDEBUG
+ char *so_path;
void *(*pre_reload)(void);
void (*post_reload)(void *);
+#endif
};
/* Get a display handler for the given display type. */
-struct disp *get_disp(char *disp_name);
+struct disp *get_disp(char *);
+void destroy_disp(struct disp *);
-void destroy_disp(void);
+#ifndef NDEBUG
+void disp_reload(struct disp *);
+#endif /* NDEBUG */
-#endif
+#endif /* DISP_H */