From 7119092665e1b771b04b305813be81e9892dfc1b Mon Sep 17 00:00:00 2001 From: Tristan Riehs Date: Sat, 22 Jun 2024 16:19:05 +0900 Subject: Improve disp API and implement dynamic reload --- src/disp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++---------------- src/disp.h | 20 +++++++++++++--- 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 +#include /* 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 */ -- cgit v1.2.3