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*
dllnames(const char * id,const char * name,Dllnames_t * names)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*
dll_lib(Dllnames_t * names,unsigned long version,Dllerror_f dllerrorf,void * disc)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*
dllmeth(const char * id,const char * name,unsigned long version)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