From 7d0214ee34c0bb393a0b26149efcc3537968e91e Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 7 Jun 2003 21:56:47 +0000 Subject: [PATCH] Change module loader interface a bit (use enum instead of string to specify module type), and make "yasm -[adfpr] help" work dynamically by scanning preloaded symbols and filesystem directories. svn path=/trunk/yasm/; revision=972 --- Mkfiles/vc/yasm-module.c | 91 ++++++---- frontends/yasm/yasm-module.c | 317 ++++++++++++++++++++++------------- frontends/yasm/yasm-module.h | 48 +++--- frontends/yasm/yasm.c | 2 +- 4 files changed, 286 insertions(+), 172 deletions(-) diff --git a/Mkfiles/vc/yasm-module.c b/Mkfiles/vc/yasm-module.c index 260274fa..b9a50c72 100644 --- a/Mkfiles/vc/yasm-module.c +++ b/Mkfiles/vc/yasm-module.c @@ -24,14 +24,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#define YASM_LIB_INTERNAL -#include +#include /*@unused@*/ RCSID("$IdPath$"); +#include + #include "yasm-module.h" typedef struct module { + module_type type; /* module type */ const char *keyword; /* module keyword */ const char *symbol; /* module symbol */ void *data; /* associated data */ @@ -51,28 +53,29 @@ extern yasm_preproc yasm_raw_LTX_preproc; extern yasm_preproc yasm_yapp_LTX_preproc; static module modules[] = { - {"x86", "arch", &yasm_x86_LTX_arch}, - {"x86", "mode_bits", &yasm_x86_LTX_mode_bits}, - {"null", "dbgfmt", &yasm_null_LTX_dbgfmt}, - {"bin", "objfmt", &yasm_bin_LTX_objfmt}, - {"coff", "objfmt", &yasm_coff_LTX_objfmt}, - {"win32", "objfmt", &yasm_win32_LTX_objfmt}, - {"dbg", "objfmt", &yasm_dbg_LTX_objfmt}, - {"basic", "optimizer", &yasm_basic_LTX_optimizer}, - {"nasm", "parser", &yasm_nasm_LTX_parser}, - {"nasm", "preproc", &yasm_nasm_LTX_preproc}, - {"raw", "preproc", &yasm_raw_LTX_preproc}, + {MODULE_ARCH, "x86", "arch", &yasm_x86_LTX_arch}, + {MODULE_ARCH, "x86", "mode_bits", &yasm_x86_LTX_mode_bits}, + {MODULE_DBGFMT, "null", "dbgfmt", &yasm_null_LTX_dbgfmt}, + {MODULE_OBJFMT, "bin", "objfmt", &yasm_bin_LTX_objfmt}, + {MODULE_OBJFMT, "coff", "objfmt", &yasm_coff_LTX_objfmt}, + {MODULE_OBJFMT, "dbg", "objfmt", &yasm_dbg_LTX_objfmt}, + {MODULE_OBJFMT, "win32", "objfmt", &yasm_win32_LTX_objfmt}, + {MODULE_OPTIMIZER, "basic", "optimizer", &yasm_basic_LTX_optimizer}, + {MODULE_PARSER, "nasm", "parser", &yasm_nasm_LTX_parser}, + {MODULE_PREPROC, "nasm", "preproc", &yasm_nasm_LTX_preproc}, + {MODULE_PREPROC, "raw", "preproc", &yasm_raw_LTX_preproc}, }; static /*@dependent@*/ /*@null@*/ module * -load_module(const char *keyword) +load_module(module_type type, const char *keyword) { int i; /* Look for the module. */ for (i=0; iname, of->keyword); - } - } -} - -void -list_parsers(void (*printfunc) (const char *name, const char *keyword)) +list_modules(module_type type, + void (*printfunc) (const char *name, const char *keyword)) { int i; + yasm_arch *arch; + yasm_dbgfmt *dbgfmt; + yasm_objfmt *objfmt; + yasm_optimizer *optimizer; + yasm_parser *parser; + yasm_preproc *preproc; /* Go through available list, and try to load each one */ for (i=0; iname, p->keyword); + if (modules[i].type == type) { + switch (type) { + case MODULE_ARCH: + arch = modules[i].data; + printfunc(arch->name, arch->keyword); + break; + case MODULE_DBGFMT: + dbgfmt = modules[i].data; + printfunc(dbgfmt->name, dbgfmt->keyword); + break; + case MODULE_OBJFMT: + objfmt = modules[i].data; + printfunc(objfmt->name, objfmt->keyword); + break; + case MODULE_OPTIMIZER: + optimizer = modules[i].data; + printfunc(optimizer->name, optimizer->keyword); + break; + case MODULE_PARSER: + parser = modules[i].data; + printfunc(parser->name, parser->keyword); + break; + case MODULE_PREPROC: + preproc = modules[i].data; + printfunc(preproc->name, preproc->keyword); + break; + } } } } diff --git a/frontends/yasm/yasm-module.c b/frontends/yasm/yasm-module.c index 89ba01f1..8441ab88 100644 --- a/frontends/yasm/yasm-module.c +++ b/frontends/yasm/yasm-module.c @@ -35,70 +35,29 @@ #include "yasm-module.h" +extern const lt_dlsymlist lt_preloaded_symbols[]; + typedef struct module { SLIST_ENTRY(module) link; - /*@only@*/ char *type; /* module type */ - /*@only@*/ char *keyword; /* module keyword */ + module_type type; /* module type */ + /*@only@*/ char *type_str; + char *keyword; /* module keyword */ lt_dlhandle handle; /* dlopen handle */ } module; -SLIST_HEAD(modulehead, module) modules = SLIST_HEAD_INITIALIZER(modules); - -/* NULL-terminated list of all possibly available architecture keywords. - * Could improve this a little by generating automatically at build-time. - */ -/*@-nullassign@*/ -const char *archs[] = { - "x86", - NULL -}; -/*@=nullassign@*/ - -/* NULL-terminated list of all possibly available object format keywords. - * Could improve this a little by generating automatically at build-time. - */ -/*@-nullassign@*/ -const char *dbgfmts[] = { - "null", - NULL -}; -/*@=nullassign@*/ - -/* NULL-terminated list of all possibly available object format keywords. - * Could improve this a little by generating automatically at build-time. - */ -/*@-nullassign@*/ -const char *objfmts[] = { - "dbg", - "bin", - "coff", - NULL -}; -/*@=nullassign@*/ - -/* NULL-terminated list of all possibly available parser keywords. - * Could improve this a little by generating automatically at build-time. - */ -/*@-nullassign@*/ -const char *parsers[] = { - "nasm", - NULL -}; -/*@=nullassign@*/ +static SLIST_HEAD(modulehead, module) modules = SLIST_HEAD_INITIALIZER(modules); -/* NULL-terminated list of all possibly available preproc keywords. - * Could improve this a little by generating automatically at build-time. - */ -/*@-nullassign@*/ -const char *preprocs[] = { - "nasm", - "raw", - NULL +static const char *module_type_str[] = { + "arch", + "dbgfmt", + "objfmt", + "optimizer", + "parser", + "preproc" }; -/*@=nullassign@*/ static /*@dependent@*/ /*@null@*/ module * -load_module(const char *type, const char *keyword) +load_module(module_type type, const char *keyword) { module *m; char *name; @@ -107,15 +66,14 @@ load_module(const char *type, const char *keyword) /* See if the module has already been loaded. */ SLIST_FOREACH(m, &modules, link) { - if (yasm__strcasecmp(m->type, type) == 0 && - yasm__strcasecmp(m->keyword, keyword) == 0) + if (m->type == type && yasm__strcasecmp(m->keyword, keyword) == 0) return m; } /* Look for dynamic module. First build full module name from keyword. */ - typelen = strlen(type); + typelen = strlen(module_type_str[type]); name = yasm_xmalloc(typelen+strlen(keyword)+2); - strcpy(name, type); + strcpy(name, module_type_str[type]); strcat(name, "_"); strcat(name, keyword); handle = lt_dlopenext(name); @@ -126,7 +84,8 @@ load_module(const char *type, const char *keyword) } m = yasm_xmalloc(sizeof(module)); - m->type = name; + m->type = type; + m->type_str = name; name[typelen] = '\0'; m->keyword = &name[typelen+1]; m->handle = handle; @@ -142,14 +101,14 @@ unload_modules(void) while (!SLIST_EMPTY(&modules)) { m = SLIST_FIRST(&modules); SLIST_REMOVE_HEAD(&modules, link); - yasm_xfree(m->type); + yasm_xfree(m->type_str); lt_dlclose(m->handle); yasm_xfree(m); } } void * -get_module_data(const char *type, const char *keyword, const char *symbol) +get_module_data(module_type type, const char *keyword, const char *symbol) { char *name; /*@dependent@*/ module *m; @@ -174,72 +133,196 @@ get_module_data(const char *type, const char *keyword, const char *symbol) return data; } -void -list_objfmts(void (*printfunc) (const char *name, const char *keyword)) -{ - int i; - yasm_objfmt *of; - - /* Go through available list, and try to load each one */ - for (i = 0; objfmts[i]; i++) { - of = load_objfmt(objfmts[i]); - if (of) - printfunc(of->name, of->keyword); - } -} +typedef struct list_module_info { + SLIST_ENTRY(list_module_info) link; + char keyword[20]; + char name[60]; +} list_module_info; -void -list_parsers(void (*printfunc) (const char *name, const char *keyword)) +typedef struct list_module_data { + module_type type; + list_module_info *matches; + size_t matches_num, matches_alloc; +} list_module_data; + +static int +list_module_load(const char *filename, lt_ptr data) { - int i; - yasm_parser *p; - - /* Go through available list, and try to load each one */ - for (i = 0; parsers[i]; i++) { - p = load_parser(parsers[i]); - if (p) - printfunc(p->name, p->keyword); + list_module_data *lmdata = data; + const char *basename; + const char *module_keyword = NULL, *module_name = NULL; + int dota = 0; + char *name; + char *dot; + + yasm_arch *arch; + yasm_dbgfmt *dbgfmt; + yasm_objfmt *objfmt; + yasm_optimizer *optimizer; + yasm_parser *parser; + yasm_preproc *preproc; + + lt_dlhandle handle; + + /* All modules have '_' in them; early check */ + if (!strchr(filename, '_')) + return 0; + + /* Strip off path components, if any */ + basename = strrchr(filename, '/'); + if (!basename) + basename = strrchr(filename, '\\'); + if (!basename) + basename = filename; + else + basename++; + + /* Check to see if module is of the type we're looking for. + * Even though this check is also implicitly performed below, there's a + * massive speedup in avoiding the dlopen() call. + */ + if (strncmp(basename, module_type_str[lmdata->type], + strlen(module_type_str[lmdata->type])) != 0) + return 0; + + if (!strcmp(&filename[strlen(filename)-2], ".a")) + dota = 1; + + /* Load it */ + if (dota) + handle = lt_dlopen(filename); + else + handle = lt_dlopenext(filename); + if (!handle) + return 0; + + /* Build base symbol name */ + name = yasm_xmalloc(strlen(basename)+5+ + strlen(module_type_str[lmdata->type])+1); + strcpy(name, basename); + if (dota) { + dot = strrchr(name, '.'); + if (dot) + *dot = '\0'; + } + strcat(name, "_LTX_"); + strcat(name, module_type_str[lmdata->type]); + + /* Prefix with yasm in the right place and get name/keyword */ + switch (lmdata->type) { + case MODULE_ARCH: + strncpy(name, "yasm", 4); + arch = lt_dlsym(handle, name); + if (arch) { + module_keyword = arch->keyword; + module_name = arch->name; + } + break; + case MODULE_DBGFMT: + strncpy(name+2, "yasm", 4); + dbgfmt = lt_dlsym(handle, name+2); + if (dbgfmt) { + module_keyword = dbgfmt->keyword; + module_name = dbgfmt->name; + } + break; + case MODULE_OBJFMT: + strncpy(name+2, "yasm", 4); + objfmt = lt_dlsym(handle, name+2); + if (objfmt) { + module_keyword = objfmt->keyword; + module_name = objfmt->name; + } + break; + case MODULE_OPTIMIZER: + strncpy(name+5, "yasm", 4); + optimizer = lt_dlsym(handle, name+5); + if (optimizer) { + module_keyword = optimizer->keyword; + module_name = optimizer->name; + } + break; + case MODULE_PARSER: + strncpy(name+2, "yasm", 4); + parser = lt_dlsym(handle, name+2); + if (parser) { + module_keyword = parser->keyword; + module_name = parser->name; + } + break; + case MODULE_PREPROC: + strncpy(name+3, "yasm", 4); + preproc = lt_dlsym(handle, name+3); + if (preproc) { + module_keyword = preproc->keyword; + module_name = preproc->name; + } + break; } -} -void -list_preprocs(void (*printfunc) (const char *name, const char *keyword)) -{ - int i; - yasm_preproc *p; - - /* Go through available list, and try to load each one */ - for (i = 0; preprocs[i]; i++) { - p = load_preproc(preprocs[i]); - if (p) - printfunc(p->name, p->keyword); + if (module_keyword && module_name) { + list_module_info *lminfo; + /* Find empty location in array */ + if (lmdata->matches_num >= lmdata->matches_alloc) { + lmdata->matches_alloc *= 2; + lmdata->matches = + yasm_xrealloc(lmdata->matches, + sizeof(list_module_info)*lmdata->matches_alloc); + } + lminfo = &lmdata->matches[lmdata->matches_num++]; + /* Build lminfo structure */ + strncpy(lminfo->keyword, module_keyword, sizeof(lminfo->keyword) - 1); + lminfo->keyword[sizeof(lminfo->keyword) - 1] = '\0'; + strncpy(lminfo->name, module_name, sizeof(lminfo->name) - 1); + lminfo->name[sizeof(lminfo->name) - 1] = '\0'; } + + /* Clean up */ + yasm_xfree(name); + lt_dlclose(handle); + return 0; } -void -list_dbgfmts(void (*printfunc) (const char *name, const char *keyword)) +static int +list_module_compare(const void *n1, const void *n2) { - int i; - yasm_dbgfmt *p; - - /* Go through available list, and try to load each one */ - for (i = 0; dbgfmts[i]; i++) { - p = load_dbgfmt(dbgfmts[i]); - if (p) - printfunc(p->name, p->keyword); - } + const list_module_info *i1 = n1, *i2 = n2; + return strcmp(i1->keyword, i2->keyword); } void -list_archs(void (*printfunc) (const char *name, const char *keyword)) +list_modules(module_type type, + void (*printfunc) (const char *name, const char *keyword)) { - int i; - yasm_arch *p; - - /* Go through available list, and try to load each one */ - for (i = 0; archs[i]; i++) { - p = load_arch(archs[i]); - if (p) - printfunc(p->name, p->keyword); + size_t i; + const lt_dlsymlist *preloaded; + list_module_data lmdata; + char *prev_keyword = NULL; + + lmdata.type = type; + lmdata.matches_num = 0; + lmdata.matches_alloc = 10; + lmdata.matches = + yasm_xmalloc(sizeof(list_module_info)*lmdata.matches_alloc); + + /* Search preloaded symbols */ + preloaded = lt_preloaded_symbols; + while (preloaded->name) { + list_module_load(preloaded->name, &lmdata); + preloaded++; + } + /* Search external module path */ + lt_dlforeachfile(NULL, list_module_load, &lmdata); + lt_dlforeachfile(".", list_module_load, &lmdata); + + /* Sort, print, and cleanup */ + yasm__mergesort(lmdata.matches, lmdata.matches_num, + sizeof(list_module_info), list_module_compare); + for (i=0; ikeyword, "x86") == 0) { unsigned char *x86_mode_bits; - x86_mode_bits = (unsigned char *)get_module_data("arch", "x86", + x86_mode_bits = (unsigned char *)get_module_data(MODULE_ARCH, "x86", "mode_bits"); if (x86_mode_bits) *x86_mode_bits = cur_objfmt->default_x86_mode_bits; -- 2.40.0