]> granicus.if.org Git - yasm/commitdiff
Change module loader interface a bit (use enum instead of string to specify
authorPeter Johnson <peter@tortall.net>
Sat, 7 Jun 2003 21:56:47 +0000 (21:56 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 7 Jun 2003 21:56:47 +0000 (21:56 -0000)
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
frontends/yasm/yasm-module.c
frontends/yasm/yasm-module.h
frontends/yasm/yasm.c

index 260274fad5ee039523f1bd014e2ceb1623c96906..b9a50c7267a79030006043b0de194e9666102fd7 100644 (file)
  * 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 <libyasm.h>
+#include <util.h>
 /*@unused@*/ RCSID("$IdPath$");
 
+#include <libyasm.h>
+
 #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; i<sizeof(modules)/sizeof(modules[0]); i++) {
-       if (yasm__strcasecmp(modules[i].keyword, keyword) == 0)
+       if (modules[i].type == type &&
+           yasm__strcasecmp(modules[i].keyword, keyword) == 0)
            return &modules[i];
     }
 
@@ -85,13 +88,14 @@ unload_modules(void)
 }
 
 void *
-get_module_data(const char *keyword, const char *symbol)
+get_module_data(module_type type, const char *keyword, const char *symbol)
 {
     int i;
 
     /* Look for the module/symbol. */
     for (i=0; i<sizeof(modules)/sizeof(modules[0]); i++) {
-       if (yasm__strcasecmp(modules[i].keyword, keyword) == 0 &&
+       if (modules[i].type == type &&
+           yasm__strcasecmp(modules[i].keyword, keyword) == 0 &&
            strcmp(modules[i].symbol, symbol) == 0)
            return modules[i].data;
     }
@@ -100,29 +104,46 @@ get_module_data(const char *keyword, const char *symbol)
 }
 
 void
-list_objfmts(void (*printfunc) (const char *name, const char *keyword))
-{
-    int i;
-
-    /* Go through available list, and try to load each one */
-    for (i=0; i<sizeof(modules)/sizeof(modules[0]); i++) {
-       if (strcmp(modules[i].symbol, "objfmt") == 0) {
-           yasm_objfmt *of = modules[i].data;
-           printfunc(of->name, 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; i<sizeof(modules)/sizeof(modules[0]); i++) {
-       if (strcmp(modules[i].symbol, "parser") == 0) {
-           yasm_parser *p = modules[i].data;
-           printfunc(p->name, 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;
+           }
        }
     }
 }
index 89ba01f1437a973850596dae5b15d739a4f8d922..8441ab884d993a09a3683afc8d1c4cd888d04677 100644 (file)
 #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; i<lmdata.matches_num; i++) {
+       /* Don't print duplicates */
+       if (!prev_keyword || strcmp(prev_keyword, lmdata.matches[i].keyword))
+           printfunc(lmdata.matches[i].name, lmdata.matches[i].keyword);
+       prev_keyword = lmdata.matches[i].keyword;
     }
+    yasm_xfree(lmdata.matches);
 }
index af764cfe030e79ccfe4e4d403a9c3dd7318b5793..304afa04e3465c6cfedda563e9d0426dd7d040a6 100644 (file)
 #ifndef YASM_MODULE_H
 #define YASM_MODULE_H
 
+typedef enum module_type {
+    MODULE_ARCH = 0,
+    MODULE_DBGFMT,
+    MODULE_OBJFMT,
+    MODULE_OPTIMIZER,
+    MODULE_PARSER,
+    MODULE_PREPROC
+} module_type;
+
 void unload_modules(void);
 /*@dependent@*/ /*@null@*/ void *get_module_data
-    (const char *type, const char *keyword, const char *symbol);
-
-#define load_arch(keyword)     get_module_data("arch", keyword, "arch")
-#define load_dbgfmt(keyword)   get_module_data("dbgfmt", keyword, "dbgfmt")
-#define load_objfmt(keyword)   get_module_data("objfmt", keyword, "objfmt")
-#define load_optimizer(keyword)        get_module_data("optimizer", keyword, "optimizer")
-#define load_parser(keyword)   get_module_data("parser", keyword, "parser")
-#define load_preproc(keyword)  get_module_data("preproc", keyword, "preproc")
+    (module_type type, const char *keyword, const char *symbol);
 
-/* Lists all available object formats.  Calls printfunc with the name and
- * keyword of each available format.
- */
-void list_objfmts(void (*printfunc) (const char *name, const char *keyword));
+#define load_arch(keyword)     get_module_data(MODULE_ARCH, keyword, "arch")
+#define load_dbgfmt(keyword)   \
+    get_module_data(MODULE_DBGFMT, keyword, "dbgfmt")
+#define load_objfmt(keyword)   \
+    get_module_data(MODULE_OBJFMT, keyword, "objfmt")
+#define load_optimizer(keyword)        \
+    get_module_data(MODULE_OPTIMIZER, keyword, "optimizer")
+#define load_parser(keyword)   \
+    get_module_data(MODULE_PARSER, keyword, "parser")
+#define load_preproc(keyword)  \
+    get_module_data(MODULE_PREPROC, keyword, "preproc")
 
-/* Lists all available parsers.  Calls printfunc with the name and keyword
- * of each available parser.
- */
-void list_parsers(void (*printfunc) (const char *name, const char *keyword));
+void list_modules(module_type type,
+                 void (*printfunc) (const char *name, const char *keyword));
 
-void list_preprocs(void (*printfunc) (const char *name, const char *keyword));
-void list_dbgfmts(void (*printfunc) (const char *name, const char *keyword));
-void list_archs(void (*printfunc) (const char *name, const char *keyword));
+#define list_archs(func)       list_modules(MODULE_ARCH, func)
+#define list_dbgfmts(func)     list_modules(MODULE_DBGFMT, func)
+#define list_objfmts(func)     list_modules(MODULE_OBJFMT, func)
+#define list_optimizers(func)  list_modules(MODULE_OPTIMIZER, func)
+#define list_parsers(func)     list_modules(MODULE_PARSER, func)
+#define list_preprocs(func)    list_modules(MODULE_PREPROC, func)
 
 #endif
index 11bf923510fcecaa337074efaeba4576b6499380..63e329a6d293731f1507fe779f511f4bfef8c2c5 100644 (file)
@@ -457,7 +457,7 @@ main(int argc, char *argv[])
     /* Get initial x86 BITS setting from object format */
     if (strcmp(cur_arch->keyword, "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;