📄 gbx_library.c
字号:
/*************************************************************************** library.c GAMBAS plug-in management routines (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> 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 1, 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_LIBRARY_C#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "gb_common.h"#include "gb_common_buffer.h"#include "gb_common_case.h"#include "gb_error.h"#include "gb_alloc.h"#include "gbx_list.h"#include "gb_replace.h"#include <fcntl.h>#include <stdlib.h>#include <stdarg.h>#include <time.h>#include <ctype.h>#include "gb_error.h"#include "gbx_class.h"#include "gbx_exec.h"#include "gbx_event.h"#include "gbx_stack.h"#include "gb_file.h"#include "gbx_archive.h"#include "gbx_project.h"#include "gbx_api.h"#include "gbx_string.h"#include "gbx_object.h"#include "gbx_library.h"/*#define DEBUG*//*#define DEBUG_PRELOAD*/PUBLIC LIBRARY *LIBRARY_Current;PUBLIC int LIBRARY_count = 0;PRIVATE LIBRARY *_library_list = NULL;#if 0PRIVATE lt_ptr library_malloc(size_t size){ lt_ptr ptr; ALLOC(&ptr, size, "library_malloc"); printf("library_malloc: %d -> %p\n", size, ptr); return ptr;}PRIVATE void library_free(lt_ptr ptr){ printf("library_free -> %p\n", ptr); FREE(&ptr, "library_free");}#endifPRIVATE void *get_symbol(LIBRARY *lib, const char *symbol, bool err){ void *sym; sym = lt_dlsym(lib->handle, symbol); if (sym == NULL && err) { strcpy(COMMON_buffer, lt_dlerror()); lt_dlclose(lib->handle); lib->handle = NULL; THROW(E_LIBRARY, lib->path, COMMON_buffer); } return sym;}PRIVATE void copy_interface(long *src, long *dst){ for(;;) { if (*src == 0) return; *dst++ = *src++; }}PUBLIC void LIBRARY_load_all(void){ LIBRARY *lib; if (EXEC_debug) LIBRARY_create("gb.eval"); for (lib = _library_list; lib; lib = (LIBRARY *)lib->list.next) { lib->preload = TRUE; LIBRARY_load(lib); }}PRIVATE bool read_line(int fd, char *dir, int max){ char *p; char c; ssize_t r; p = dir; for(;;) { max--; for (;;) { r = read(fd, &c, 1); if (r == 1) break; if (errno != EINTR) return TRUE; } if (c == '\n' || max == 0) { *p = 0; return FALSE; } *p++ = c; }}#if 0PRIVATE void add_preload(char **env, const char *libdir, const char *lib){ if (*env == COMMON_buffer) *env += sprintf(*env, "LD_PRELOAD="); *env += sprintf(*env, "%s/lib/lib.%s.so.0", libdir, lib);}#endifPRIVATE void add_preload(char **env, const char *lib){ char *org; if (*env == COMMON_buffer) { org = getenv("LD_PRELOAD"); if (org && *org) *env += sprintf(*env, "%s ", org); } *env += sprintf(*env, "%s ", lib);}PUBLIC void LIBRARY_preload(const char *file, char **argv){#if DO_PRELOADING const char *path; char dir[MAX_PATH]; /*char libdir[MAX_PATH];*/ int fd; char *p; char *env; bool preload; bool stop; env = getenv("GAMBAS_PRELOAD"); if (env) { #ifdef DEBUG_PRELOAD fprintf(stderr, "Preloading done.\nLD_PRELOAD=%s\nGAMBAS_PRELOAD=%s\n", getenv("LD_PRELOAD"), getenv("GAMBAS_PRELOAD")); #endif if (*env) setenv("LD_PRELOAD", env, TRUE); else unsetenv("LD_PRELOAD"); unsetenv("GAMBAS_PRELOAD"); return; } preload = FALSE; /* path = FILE_readlink("/usr/bin/gbx"); if (!path) goto _PANIC; path = FILE_get_dir(FILE_get_dir(path)); strcpy(libdir, path); */ if (!EXEC_arch) { if (file == NULL) file = "."; if (*file == '/') { strcpy(dir, file); } else { if (*file == '.' && file[1] == '/') file += 2; path = FILE_getcwd(file); if (path == NULL) goto _PANIC; chdir(path); path = FILE_getcwd(NULL); if (path == NULL) goto _PANIC; strcpy(dir, path); } file = FILE_cat(dir, ".project", NULL); } fd = open(file, O_RDONLY); /* Silently ignored */ if (fd < 0) return; if (EXEC_arch) lseek(fd, 32 + sizeof(ARCH_HEADER), SEEK_SET); read_line(fd, dir, MAX_PATH); if (strcasecmp(dir, "# Gambas Project File 1.0")) { fprintf(stderr, "Syntax error in project file.\n"); goto _PANIC; } env = COMMON_buffer; stop = FALSE; for(;;) { if (read_line(fd, dir, MAX_PATH)) break; if (strncasecmp(dir, "library=", 8) == 0) { stop = TRUE; p = &dir[8]; if (strcasecmp(p, "gb.qt") == 0) { add_preload(&env, "libqt-mt.so.3"); preload = TRUE; } #if HAVE_KDE_COMPONENT else if (strcasecmp(p, "gb.qt.kde") == 0) { /*add_preload(&env, libdir, p);*/ add_preload(&env, "libkdecore.so.4"); add_preload(&env, "libkdeui.so.4"); add_preload(&env, "libDCOP.so.4"); add_preload(&env, "libkio.so.4"); /*fprintf(stderr, "Warning: preloading KDE libraries\n");*/ preload = TRUE; } #endif } else { if (stop) break; } } close(fd); if (preload) { env = getenv("LD_PRELOAD"); if (env && *env) setenv("GAMBAS_PRELOAD", env, TRUE); else setenv("GAMBAS_PRELOAD", "", TRUE); setenv("LD_PRELOAD", COMMON_buffer, TRUE); #ifdef DEBUG_PRELOAD fprintf(stderr, "Preloading...\nLD_PRELOAD=%s\nGAMBAS_PRELOAD=%s\n", getenv("LD_PRELOAD"), getenv("GAMBAS_PRELOAD")); #endif execv("/usr/bin/gbx", argv); } return;_PANIC: fprintf(stderr, "Cannot preload libraries: %s\n", strerror(errno));#endif}PUBLIC void LIBRARY_init(void){ /*if (putenv("LD_BIND_NOW=true")) ERROR_panic("Cannot set LD_BIND_NOW: &1", strerror(errno)); if (putenv("KDE_MALLOC=0")) ERROR_panic("Cannot set KDE_MALLOC: &1", strerror(errno));*/ /*lt_dlmalloc = library_malloc; lt_dlfree = library_free;*/ #ifdef USE_LTDL if (lt_dlinit()) ERROR_panic("Cannot initialize plug-in management: %s", lt_dlerror()); #endif}PUBLIC void LIBRARY_exit(void){ LIBRARY *lib; /*for (lib = _library_list; lib; lib = (LIBRARY *)lib->list.next)*/ LIST_for_each(lib, _library_list) LIBRARY_unload(lib); while (_library_list) LIBRARY_delete(_library_list); #ifdef USE_LTDL lt_dlexit(); #endif}PUBLIC LIBRARY *LIBRARY_find(const char *name){ LIBRARY *lib; /*for (lib = _library_list; lib; lib = (LIBRARY *)lib->list.next)*/ LIST_for_each(lib, _library_list) { if (strcmp(lib->name, name) == 0) return lib; } return NULL;}PUBLIC void LIBRARY_get_interface(LIBRARY *lib, long version, void *iface){ char symbol[32]; int i, len; char c; len = strlen(lib->name); for (i = 0; i < len; i++) { c = toupper(lib->name[i]); if (!isalnum(c)) c = '_'; symbol[i] = c; } sprintf(&symbol[len], "_%ld", version); copy_interface((long *)get_symbol(lib, symbol, TRUE), (long *)iface);}PUBLIC boolean LIBRARY_get_interface_by_name(const char *name, long version, void *iface){ LIBRARY *lib; lib = LIBRARY_find(name); if (lib == NULL) return TRUE; LIBRARY_get_interface(lib, version, iface); return FALSE;}PUBLIC LIBRARY *LIBRARY_create(const char *path){ LIBRARY *lib; int len; lib = LIBRARY_find(path); if (lib) return lib; ALLOC_ZERO(&lib, sizeof(LIBRARY), "LIBRARY_create"); lib->class = CLASS_Library; lib->ref = 1; lib->handle = NULL; if (path) { STRING_new(&lib->name, FILE_get_name(path), 0); lib->free_name = TRUE; if (!FILE_is_relative(path)) ERROR_panic("Absolute path are not allowed in libraries: %s", path); len = strlen(path) + strlen(PROJECT_lib_path) + 8; STRING_new(&lib->path, NULL, len); sprintf(lib->path, LIB_PATTERN, PROJECT_lib_path, path); lib->persistent = FALSE; lib->preload = FALSE; } else { lib->name = "gb"; lib->free_name = FALSE; lib->path = NULL; lib->persistent = TRUE; lib->preload = TRUE; } LIST_insert((void **)&_library_list, lib, &lib->list); LIBRARY_count++; return lib;}PUBLIC void LIBRARY_delete(LIBRARY *lib){ LIBRARY_unload(lib); LIST_remove((void **)&_library_list, lib, &lib->list); LIBRARY_count--; if (lib->free_name) STRING_free(&lib->name); FREE(&lib, "LIBRARY_delete");}PUBLIC void LIBRARY_load(LIBRARY *lib){ int (*func)(); GB_INTERFACE *iface; GB_DESC **desc;#ifdef DEBUG clock_t t = clock(); fprintf(stderr, "Loading library %s\n", lib->path);#endif if (lib->path == NULL) return; if (lib->handle) return; #ifdef USE_LTDL lt_dlopen_flag = RTLD_LAZY; lib->handle = lt_dlopenext(lib->path); #else lib->handle = dlopen(lib->path, RTLD_LAZY); #endif if (lib->handle == NULL) THROW(E_LIBRARY, lib->path, lt_dlerror()); func = get_symbol(lib, LIB_INIT, TRUE); /* Interface de Gambas */ iface = get_symbol(lib, LIB_GAMBAS, TRUE); copy_interface((long *)GAMBAS_Api, (long *)iface); /* Initialisation */ LIBRARY_Current = lib; lib->persistent = (boolean)(*func)(); /* D閏laration des classes */ desc = get_symbol(lib, LIB_CLASS, FALSE); if (desc) LIBRARY_declare(desc);#ifdef DEBUG fprintf(stderr, "Library %s loaded ", lib->path); fprintf(stderr, "in %g s\n", ((double)(clock() - t) / CLOCKS_PER_SEC));#endif}PUBLIC void LIBRARY_declare(GB_DESC **desc){ while (*desc != NULL) { if (CLASS_register(*desc) == NULL) THROW(E_REGISTER, *((char **)desc)); desc++; }}PUBLIC void LIBRARY_unload(LIBRARY *lib){ void (*gambas_exit)(); if (lib->path == NULL) return; STRING_free(&lib->path); if (lib->handle == NULL) return; /* Pas de lib閞ation des classes pr閏harg閑 ! */ /* V閞ification qu'aucune classe de la librairie n'est instanci閑 ! */ gambas_exit = lt_dlsym(lib->handle, LIB_EXIT); if (gambas_exit != NULL) (*gambas_exit)(); if (lib->persistent) { gambas_exit = lt_dlsym(lib->handle, "_fini"); if (gambas_exit != NULL) (*gambas_exit)(); } else lt_dlclose(lib->handle); lib->handle = NULL;#ifdef DEBUG printf("Unloading library %s\n", lib->name);#endif}PUBLIC LIBRARY *LIBRARY_next(LIBRARY *lib){ if (lib) return (LIBRARY *)(lib->list.next); else return _library_list;}#if 0PUBLIC const char *LIBRARY_get_control_list(LIBRARY *lib){ void (*gambas_info)(); const char *result = NULL; gambas_info = lt_dlsym(lib->handle, LIB_INFO); if (gambas_info == NULL) return NULL; (*gambas_info)(GB_INFO_CONTROL, &result); return result;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -