/*
 * YASM module loader
 *
 *  Copyright (C) 2004-2007  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <util.h>
/*@unused@*/ RCSID("$Id$");

#include <libyasm.h>


typedef struct module {
    const char *keyword;            /* module keyword */
    void *data;                     /* associated data */
} module;

EXTERN_LIST

static module arch_modules[] = {
MODULES_arch_
};

static module dbgfmt_modules[] = {
MODULES_dbgfmt_
};

static module objfmt_modules[] = {
MODULES_objfmt_
};

static module listfmt_modules[] = {
MODULES_listfmt_
};

static module parser_modules[] = {
MODULES_parser_
};

static module preproc_modules[] = {
MODULES_preproc_
};

static struct {
    module *m;
    size_t n;
} module_types[] = {
    {arch_modules, sizeof(arch_modules)/sizeof(module)},
    {dbgfmt_modules, sizeof(dbgfmt_modules)/sizeof(module)},
    {objfmt_modules, sizeof(objfmt_modules)/sizeof(module)},
    {listfmt_modules, sizeof(listfmt_modules)/sizeof(module)},
    {parser_modules, sizeof(parser_modules)/sizeof(module)},
    {preproc_modules, sizeof(preproc_modules)/sizeof(module)},
};

typedef struct loaded_module {
    yasm_module_type type;          /* module type */
    const char *keyword;            /* module keyword */
    void *data;                     /* associated data */
} loaded_module;

static loaded_module *loaded_modules = NULL;
static size_t num_loaded_modules = 0;

void *
yasm_load_module(yasm_module_type type, const char *keyword)
{
    size_t i;
    module *modules;
    size_t n;

    /* Look for the module/symbol, first in loaded modules */
    if (loaded_modules) {
        for (i=0; i<num_loaded_modules; i++) {
            if (loaded_modules[i].type == type &&
                yasm__strcasecmp(loaded_modules[i].keyword, keyword) == 0)
                return loaded_modules[i].data;
        }
    }

    modules = module_types[type].m;
    n = module_types[type].n;
    for (i=0; i<n; i++) {
        if (yasm__strcasecmp(modules[i].keyword, keyword) == 0)
            return modules[i].data;
    }

    return NULL;
}

void
yasm_register_module(yasm_module_type type, const char *keyword, void *data)
{
    loaded_modules =
        yasm_xrealloc(loaded_modules,
                      (num_loaded_modules+1)*sizeof(loaded_module));
    loaded_modules[num_loaded_modules].type = type;
    loaded_modules[num_loaded_modules].keyword = keyword;
    loaded_modules[num_loaded_modules].data = data;
    num_loaded_modules++;
}

static void
yasm_list_one_module(yasm_module_type type, void *data,
                     void (*printfunc) (const char *name, const char *keyword))
{
    yasm_arch_module *arch;
    yasm_dbgfmt_module *dbgfmt;
    yasm_objfmt_module *objfmt;
    yasm_listfmt_module *listfmt;
    yasm_parser_module *parser;
    yasm_preproc_module *preproc;

    switch (type) {
        case YASM_MODULE_ARCH:
            arch = data;
            printfunc(arch->name, arch->keyword);
            break;
        case YASM_MODULE_DBGFMT:
            dbgfmt = data;
            printfunc(dbgfmt->name, dbgfmt->keyword);
            break;
        case YASM_MODULE_OBJFMT:
            objfmt = data;
            printfunc(objfmt->name, objfmt->keyword);
            break;
        case YASM_MODULE_LISTFMT:
            listfmt = data;
            printfunc(listfmt->name, listfmt->keyword);
            break;
        case YASM_MODULE_PARSER:
            parser = data;
            printfunc(parser->name, parser->keyword);
            break;
        case YASM_MODULE_PREPROC:
            preproc = data;
            printfunc(preproc->name, preproc->keyword);
            break;
    }
}

void
yasm_list_modules(yasm_module_type type,
                  void (*printfunc) (const char *name, const char *keyword))
{
    size_t i;
    module *modules;
    size_t n;;

    /* Go through available list, and try to load each one */
    if (loaded_modules) {
        for (i=0; i<num_loaded_modules; i++)
            yasm_list_one_module(type, loaded_modules[i].data, printfunc);
    }

    modules = module_types[type].m;
    n = module_types[type].n;
    for (i=0; i<n; i++)
        yasm_list_one_module(type, modules[i].data, printfunc);
}
