summaryrefslogtreecommitdiff
path: root/src/lib/libdll/dll_lib.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libdll/dll_lib.c
downloadksh-3950ffe2a485479f6561c27364d3d7df5a21d124.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libdll/dll_lib.c')
-rw-r--r--src/lib/libdll/dll_lib.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/lib/libdll/dll_lib.c b/src/lib/libdll/dll_lib.c
new file mode 100644
index 0000000..29e4cd8
--- /dev/null
+++ b/src/lib/libdll/dll_lib.c
@@ -0,0 +1,183 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include "dlllib.h"
+
+typedef void* (*Dll_lib_f)(const char*, void*, const char*);
+
+typedef struct Dll_lib_s
+{
+ struct Dll_lib_s* next;
+ Dll_lib_f libf;
+ char* path;
+ char base[1];
+} Dll_lib_t;
+
+/*
+ * split <name,base,type,opts> from name into names
+ */
+
+Dllnames_t*
+dllnames(const char* id, const char* name, Dllnames_t* names)
+{
+ char* s;
+ char* t;
+ char* b;
+ char* e;
+ size_t n;
+
+ n = strlen(id);
+ if (strneq(name, id, n) && (streq(name + n, "_s") || streq(name + n, "_t")))
+ return 0;
+ if (!names)
+ {
+ s = fmtbuf(sizeof(Dllnames_t*) + sizeof(names) - 1);
+ if (n = (s - (char*)0) % sizeof(names))
+ s += sizeof(names) - n;
+ names = (Dllnames_t*)s;
+ }
+
+ /*
+ * determine the base name
+ */
+
+ if ((s = strrchr(name, '/')) || (s = strrchr(name, '\\')))
+ s++;
+ else
+ s = (char*)name;
+ if (strneq(s, "lib", 3))
+ s += 3;
+ b = names->base = names->data;
+ e = b + sizeof(names->data) - 1;
+ t = s;
+ while (b < e && *t && *t != '.' && *t != '-' && *t != ':')
+ *b++ = *t++;
+ *b++ = 0;
+
+ /*
+ * determine the optional type
+ */
+
+ if (t = strrchr(s, ':'))
+ {
+ names->name = b;
+ while (b < e && s < t)
+ *b++ = *s++;
+ *b++ = 0;
+ names->type = b;
+ while (b < e && *++t)
+ *b++ = *t;
+ *b++ = 0;
+ }
+ else
+ {
+ names->name = (char*)name;
+ names->type = 0;
+ }
+ *(names->path = b) = 0;
+ names->opts = 0;
+ names->id = (char*)id;
+ return names;
+}
+
+/*
+ * return method pointer for <id,version> in names
+ */
+
+void*
+dll_lib(Dllnames_t* names, unsigned long version, Dllerror_f errorf, void* disc)
+{
+ void* dll;
+ Dll_lib_t* lib;
+ Dll_lib_f libf;
+ int n;
+ char sym[64];
+
+ static Dll_lib_t* loaded;
+
+ if (!names)
+ return 0;
+
+ /*
+ * check if plugin already loaded
+ */
+
+ for (lib = loaded; lib; lib = lib->next)
+ if (streq(names->base, lib->base))
+ {
+ libf = lib->libf;
+ goto init;
+ }
+
+ /*
+ * load
+ */
+
+ 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))))
+ {
+ if (errorf)
+ (*errorf)(NiL, disc, 2, "%s: library not found", names->name);
+ return 0;
+ }
+
+ /*
+ * init
+ */
+
+ sfsprintf(sym, sizeof(sym), "%s_lib", names->id);
+ if (!(libf = (Dll_lib_f)dlllook(dll, sym)))
+ {
+ if (errorf)
+ (*errorf)(NiL, disc, 2, "%s: %s: initialization function not found in library", names->path, sym);
+ return 0;
+ }
+
+ /*
+ * add to the loaded list
+ */
+
+ if (lib = newof(0, Dll_lib_t, 1, (n = strlen(names->base)) + strlen(names->path) + 1))
+ {
+ lib->libf = libf;
+ strcpy(lib->base, names->base);
+ strcpy(lib->path = lib->base + n + 1, names->path);
+ lib->next = loaded;
+ loaded = lib;
+ }
+ init:
+ return (*libf)(names->path, disc, names->type);
+}
+
+/*
+ * return method pointer for <id,name,version>
+ */
+
+void*
+dllmeth(const char* id, const char* name, unsigned long version)
+{
+ Dllnames_t names;
+
+ return dll_lib(dllnames(id, name, &names), version, 0, 0);
+}