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
This commit is contained in:
Peter Johnson 2003-06-07 21:56:47 +00:00
parent cc3f9486f3
commit 7d0214ee34
4 changed files with 289 additions and 175 deletions

View file

@ -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 <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))
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, "objfmt") == 0) {
yasm_objfmt *of = modules[i].data;
printfunc(of->name, of->keyword);
}
}
}
void
list_parsers(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, "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;
}
}
}
}

View file

@ -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);
static 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
static const char *module_type_str[] = {
"arch",
"dbgfmt",
"objfmt",
"optimizer",
"parser",
"preproc"
};
/*@=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@*/
/* 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
};
/*@=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;
typedef struct list_module_info {
SLIST_ENTRY(list_module_info) link;
char keyword[20];
char name[60];
} list_module_info;
/* 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_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)
{
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;
}
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;
}
static int
list_module_compare(const void *n1, const void *n2)
{
const list_module_info *i1 = n1, *i2 = n2;
return strcmp(i1->keyword, i2->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_parser *p;
size_t i;
const lt_dlsymlist *preloaded;
list_module_data lmdata;
char *prev_keyword = NULL;
/* 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);
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);
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);
}
}
void
list_dbgfmts(void (*printfunc) (const char *name, const char *keyword))
{
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);
}
}
void
list_archs(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);
/* 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);
}

View file

@ -27,29 +27,39 @@
#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);
(module_type 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")
#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 object formats. Calls printfunc with the name and
* keyword of each available format.
*/
void list_objfmts(void (*printfunc) (const char *name, const char *keyword));
void list_modules(module_type type,
void (*printfunc) (const char *name, const char *keyword));
/* 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_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

View 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;