/* * Copyright (C) 2024 Tristan Riehs * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include #include #include #include "disp.h" #define dlsym_and_check(dest, name) \ dest->name = dlsym(dest->dl_handle, #name); \ if ((!dest->name) || (dest->name == dest->dl_handle)) { \ char *msg = dlerror(); \ fprintf(stderr, "calculer: %s\n", msg); \ dlclose(dest->dl_handle); \ free(dest); \ return -1; \ } static int load_symbols(struct disp *disp) { void *handle = dlopen(disp->so_path, RTLD_LAZY); if (!handle) { fprintf(stderr, "calculer: %s\n", dlerror()); exit(1); } #ifndef NDEBUG printf("INFO: successfully loaded symbols from \"%s\"\n", disp->so_path); #endif 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; } 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