/* * 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" #ifdef NDEBUG extern struct disp *cli_disp; extern struct disp *tui_disp; extern struct disp *ray_disp; #endif #ifndef NDEBUG static void * load_generic_symbol(struct disp *disp, char *base_name) { char full_name[64] = {0}; void *ptr; strcpy(full_name, disp->name); strcat(full_name, "_"); strcat(full_name, base_name); ptr = dlsym(disp->dl_handle, full_name); if (!ptr) { fprintf(stderr, "calculer: %s\n", dlerror()); destroy_disp(disp); exit(1); } return ptr; } #endif #ifndef NDEBUG static void load_symbols(struct disp *disp) { void *handle = dlopen(disp->so_path, RTLD_LAZY); if (!handle) { fprintf(stderr, "calculer: %s\n", dlerror()); destroy_disp(disp); exit(1); } disp->dl_handle = handle; disp->init = load_generic_symbol(disp, "init"); disp->display_calc = load_generic_symbol(disp, "display_calc"); disp->read_input = load_generic_symbol(disp, "read_input"); disp->display_res = load_generic_symbol(disp, "display_res"); disp->destroy = load_generic_symbol(disp, "destroy"); disp->pre_reload = load_generic_symbol(disp, "pre_reload"); disp->post_reload = load_generic_symbol(disp, "post_reload"); printf("INFO: successfully loaded symbols from \"%s\"\n", disp->so_path); } #endif 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); disp->name = disp_name; load_symbols(disp); return disp; #else if (strcmp(disp_name, "cli") == 0) return cli_disp; if (strcmp(disp_name, "tui") == 0) return tui_disp; if (strcmp(disp_name, "ray") == 0) return ray_disp; return NULL; #endif } void destroy_disp(struct disp *disp) { if (disp->destroy) disp->destroy(); #ifndef NDEBUG if (disp->dl_handle) dlclose(disp->dl_handle); free(disp->so_path); free(disp); #endif } #ifndef NDEBUG void disp_reload(struct disp *disp) { 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"); load_symbols(disp); printf("INFO: loading state\n"); disp->post_reload(state); printf("INFO: reloading done\n"); } #endif