1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1997-2012 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Glenn Fowler 23 * AT&T Research 24 */ 25 26 #include "dlllib.h" 27 28 typedef void* (*Dll_lib_f)(const char*, void*, const char*); 29 30 typedef struct Dll_lib_s 31 { 32 struct Dll_lib_s* next; 33 Dll_lib_f libf; 34 char* path; 35 char base[1]; 36 } Dll_lib_t; 37 38 /* 39 * split <name,base,type,opts> from name into names 40 */ 41 42 Dllnames_t* 43 dllnames(const char* id, const char* name, Dllnames_t* names) 44 { 45 char* s; 46 char* t; 47 char* b; 48 char* e; 49 size_t n; 50 51 n = strlen(id); 52 if (strneq(name, id, n) && (streq(name + n, "_s") || streq(name + n, "_t"))) 53 return 0; 54 if (!names) 55 { 56 s = fmtbuf(sizeof(Dllnames_t*) + sizeof(names) - 1); 57 if (n = (s - (char*)0) % sizeof(names)) 58 s += sizeof(names) - n; 59 names = (Dllnames_t*)s; 60 } 61 62 /* 63 * determine the base name 64 */ 65 66 if ((s = strrchr(name, '/')) || (s = strrchr(name, '\\'))) 67 s++; 68 else 69 s = (char*)name; 70 if (strneq(s, "lib", 3)) 71 s += 3; 72 b = names->base = names->data; 73 e = b + sizeof(names->data) - 1; 74 t = s; 75 while (b < e && *t && *t != '.' && *t != '-' && *t != ':') 76 *b++ = *t++; 77 *b++ = 0; 78 79 /* 80 * determine the optional type 81 */ 82 83 if (t = strrchr(s, ':')) 84 { 85 names->name = b; 86 while (b < e && s < t) 87 *b++ = *s++; 88 *b++ = 0; 89 names->type = b; 90 while (b < e && *++t) 91 *b++ = *t; 92 *b++ = 0; 93 } 94 else 95 { 96 names->name = (char*)name; 97 names->type = 0; 98 } 99 *(names->path = b) = 0; 100 names->opts = 0; 101 names->id = (char*)id; 102 return names; 103 } 104 105 /* 106 * return method pointer for <id,version> in names 107 */ 108 109 void* 110 dll_lib(Dllnames_t* names, unsigned long version, Dllerror_f dllerrorf, void* disc) 111 { 112 void* dll; 113 Dll_lib_t* lib; 114 Dll_lib_f libf; 115 ssize_t n; 116 char sym[64]; 117 118 static Dll_lib_t* loaded; 119 120 if (!names) 121 return 0; 122 123 /* 124 * check if plugin already loaded 125 */ 126 127 for (lib = loaded; lib; lib = lib->next) 128 if (streq(names->base, lib->base)) 129 { 130 libf = lib->libf; 131 goto init; 132 } 133 134 /* 135 * load 136 */ 137 138 if (!(dll = dllplugin(names->id, names->name, NiL, version, NiL, RTLD_LAZY, names->path, names->data + sizeof(names->data) - names->path)) && (streq(names->name, names->base) || !(dll = dllplugin(names->id, names->base, NiL, version, NiL, RTLD_LAZY, names->path, names->data + sizeof(names->data) - names->path)))) 139 { 140 if (dllerrorf) 141 (*dllerrorf)(NiL, disc, 2, "%s: library not found", names->name); 142 else 143 errorf("dll", NiL, -1, "dll_lib: %s version %lu library not found", names->name, version); 144 return 0; 145 } 146 147 /* 148 * init 149 */ 150 151 sfsprintf(sym, sizeof(sym), "%s_lib", names->id); 152 if (!(libf = (Dll_lib_f)dlllook(dll, sym))) 153 { 154 if (dllerrorf) 155 (*dllerrorf)(NiL, disc, 2, "%s: %s: initialization function not found in library", names->path, sym); 156 else 157 errorf("dll", NiL, -1, "dll_lib: %s version %lu initialization function %s not found in library", names->name, version, sym); 158 return 0; 159 } 160 161 /* 162 * add to the loaded list 163 */ 164 165 if (lib = newof(0, Dll_lib_t, 1, (n = strlen(names->base)) + strlen(names->path) + 1)) 166 { 167 lib->libf = libf; 168 strcpy(lib->base, names->base); 169 strcpy(lib->path = lib->base + n + 1, names->path); 170 lib->next = loaded; 171 loaded = lib; 172 errorf("dll", NiL, -1, "dll_lib: %s version %lu loaded from %s", names->name, version, lib->path); 173 } 174 init: 175 return (*libf)(names->path, disc, names->type); 176 } 177 178 /* 179 * return method pointer for <id,name,version> 180 */ 181 182 void* 183 dllmeth(const char* id, const char* name, unsigned long version) 184 { 185 Dllnames_t names; 186 187 return dll_lib(dllnames(id, name, &names), version, 0, 0); 188 } 189