diff options
Diffstat (limited to 'src/disp.c')
-rw-r--r-- | src/disp.c | 77 |
1 files changed, 58 insertions, 19 deletions
@@ -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 |