/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1997-2012 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 * * * ***********************************************************************/ #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 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 in names */ void* dll_lib(Dllnames_t* names, unsigned long version, Dllerror_f dllerrorf, void* disc) { void* dll; Dll_lib_t* lib; Dll_lib_f libf; ssize_t 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 (dllerrorf) (*dllerrorf)(NiL, disc, 2, "%s: library not found", names->name); else errorf("dll", NiL, -1, "dll_lib: %s version %lu library not found", names->name, version); return 0; } /* * init */ sfsprintf(sym, sizeof(sym), "%s_lib", names->id); if (!(libf = (Dll_lib_f)dlllook(dll, sym))) { if (dllerrorf) (*dllerrorf)(NiL, disc, 2, "%s: %s: initialization function not found in library", names->path, sym); else errorf("dll", NiL, -1, "dll_lib: %s version %lu initialization function %s not found in library", names->name, version, 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; errorf("dll", NiL, -1, "dll_lib: %s version %lu loaded from %s", names->name, version, lib->path); } init: return (*libf)(names->path, disc, names->type); } /* * return method pointer for */ void* dllmeth(const char* id, const char* name, unsigned long version) { Dllnames_t names; return dll_lib(dllnames(id, name, &names), version, 0, 0); }