#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gimp-print/gimp-print.h>
#include "gimp-print-internal.h"
#include <gimp-print/gimp-print-intl-internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <errno.h>
#include <unistd.h>
typedef struct stpi_internal_module_class
{
stp_module_class_t class;
const char *description;
} stpi_internal_module_class_t;
static void module_list_freefunc(void *item);
static int stp_module_register(stp_module_t *module);
#ifdef USE_DLOPEN
static void *stp_dlsym(void *handle, const char *symbol, const char *modulename);
#endif
static const stpi_internal_module_class_t module_classes[] =
{
{STP_MODULE_CLASS_MISC, N_("Miscellaneous (unclassified)")},
{STP_MODULE_CLASS_FAMILY, N_("Family driver")},
{STP_MODULE_CLASS_COLOR, N_("Color conversion module")},
{STP_MODULE_CLASS_DITHER, N_("Dither algorithm")},
{STP_MODULE_CLASS_INVALID, NULL}
};
#if !defined(USE_LTDL) && !defined(USE_DLOPEN)
extern stp_module_t print_canon_LTX_stp_module_data;
extern stp_module_t print_escp2_LTX_stp_module_data;
extern stp_module_t print_lexmark_LTX_stp_module_data;
extern stp_module_t print_pcl_LTX_stp_module_data;
extern stp_module_t print_ps_LTX_stp_module_data;
extern stp_module_t print_olympus_LTX_stp_module_data;
extern stp_module_t print_raw_LTX_stp_module_data;
extern stp_module_t color_traditional_LTX_stp_module_data;
static stp_module_t *static_modules[] =
{
&print_ps_LTX_stp_module_data,
&print_canon_LTX_stp_module_data,
&print_escp2_LTX_stp_module_data,
&print_pcl_LTX_stp_module_data,
&print_lexmark_LTX_stp_module_data,
&print_olympus_LTX_stp_module_data,
&print_raw_LTX_stp_module_data,
&color_traditional_LTX_stp_module_data,
NULL
};
#endif
static stp_list_t *module_list = NULL;
static void
module_list_freefunc(void *item )
{
stp_module_t *module = (stp_module_t *) item;
if (module && module->fini)
module->fini();
#if defined(USE_LTDL) || defined(USE_DLOPEN)
DLCLOSE(module->handle);
#endif
}
int stp_module_load(void)
{
#ifdef USE_LTDL
static int ltdl_is_initialised = 0;
#endif
static int module_list_is_initialised = 0;
#if defined(USE_LTDL) || defined(USE_DLOPEN)
stp_list_t *dir_list;
stp_list_t *file_list;
stp_list_item_t *file;
#endif
#ifdef USE_LTDL
if (!ltdl_is_initialised)
{
if (lt_dlinit())
{
stp_erprintf("Error initialising libltdl: %s\n", DLERROR());
return 1;
}
ltdl_is_initialised = 1;
}
lt_dladdsearchdir(PKGMODULEDIR);
#endif
if (!module_list_is_initialised)
{
if (!(module_list = stp_list_create()))
return 1;
stp_list_set_freefunc(module_list, module_list_freefunc);
module_list_is_initialised = 1;
}
#if defined (USE_LTDL) || defined (USE_DLOPEN)
if (!(dir_list = stp_list_create()))
return 1;
stp_list_set_freefunc(dir_list, stp_list_node_free_data);
if (getenv("STP_MODULE_PATH"))
{
stp_path_split(dir_list, getenv("STP_MODULE_PATH"));
}
else
{
#ifdef USE_LTDL
stp_path_split(dir_list, getenv("LTDL_LIBRARY_PATH"));
stp_path_split(dir_list, lt_dlgetsearchpath());
#else
stp_path_split(dir_list, PKGMODULEDIR);
#endif
}
#ifdef USE_LTDL
file_list = stp_path_search(dir_list, ".la");
#else
file_list = stp_path_search(dir_list, ".so");
#endif
stp_list_destroy(dir_list);
file = stp_list_get_start(file_list);
while (file)
{
stp_module_open((const char *) stp_list_item_get_data(file));
file = stp_list_item_next(file);
}
stp_list_destroy(file_list);
#else
{
int i=0;
while (static_modules[i])
{
stp_module_register(static_modules[i]);
i++;
}
}
#endif
return 0;
}
int
stp_module_exit(void)
{
if (module_list)
stp_list_destroy(module_list);
#ifdef USE_LTDL
return lt_dlexit();
#else
return 0;
#endif
}
stp_list_t *
stp_module_get_class(stp_module_class_t class )
{
stp_list_t *list;
stp_list_item_t *ln;
list = stp_list_create();
if (!list)
return NULL;
ln = stp_list_get_start(module_list);
while (ln)
{
if (((stp_module_t *) stp_list_item_get_data(ln))->class == class)
stp_list_item_create(list, NULL, stp_list_item_get_data(ln));
ln = stp_list_item_next(ln);
}
return list;
}
int
stp_module_open(const char *modulename )
{
#if defined(USE_LTDL) || defined(USE_DLOPEN)
#ifdef USE_LTDL
lt_dlhandle module;
#else
void *module;
#endif
stp_module_version_t *version;
stp_module_t *data;
stp_list_item_t *reg_module;
int error = 0;
stp_deprintf(STP_DBG_MODULE, "stp-module: open: %s\n", modulename);
while(1)
{
module = DLOPEN(modulename);
if (!module)
break;
version = (stp_module_version_t *) DLSYM(module, "stp_module_version");
if (!version)
break;
if (version->major != 1 && version->minor < 0)
break;
data = (void *) DLSYM(module, "stp_module_data");
if (!data)
break;
data->handle = module;
reg_module = stp_list_get_start(module_list);
while (reg_module)
{
if (!strcmp(data->name, ((stp_module_t *)
stp_list_item_get_data(reg_module))->name) &&
data->class == ((stp_module_t *)
stp_list_item_get_data(reg_module))->class)
{
stp_deprintf(STP_DBG_MODULE,
"stp-module: reject duplicate: %s\n",
data->name);
error = 1;
break;
}
reg_module = stp_list_item_next(reg_module);
}
if (error)
break;
if (stp_module_register(data))
break;
return 0;
}
if (module)
DLCLOSE(module);
#endif
return 1;
}
static int stp_module_register(stp_module_t *module )
{
if (stp_list_item_create(module_list, NULL, module))
return 1;
stp_deprintf(STP_DBG_MODULE, "stp-module: register: %s\n", module->name);
return 0;
}
int stp_module_init(void)
{
stp_list_item_t *module_item;
stp_module_t *module;
module_item = stp_list_get_start(module_list);
while (module_item)
{
module = (stp_module_t *) stp_list_item_get_data(module_item);
if (module)
{
stp_deprintf(STP_DBG_MODULE, "stp-module-init: %s\n", module->name);
if (module->init && module->init())
{
stp_deprintf(STP_DBG_MODULE,
"stp-module-init: %s: Module init failed\n",
module->name);
}
}
module_item = stp_list_item_next(module_item);
}
return 0;
}
int
stp_module_close(stp_list_item_t *module )
{
return stp_list_item_destroy(module_list, module);
}
#ifdef USE_DLOPEN
static void *stp_dlsym(void *handle,
const char *symbol,
const char *modulename)
{
int len;
static char *full_symbol = NULL;
char *module;
char *tmp = stp_strdup(modulename);
module = basename(tmp);
if (full_symbol)
{
stp_free (full_symbol);
full_symbol = NULL;
}
full_symbol = (char *) stp_malloc(sizeof(char) * (strlen(module) - 2));
len = strlen(symbol) + strlen(module) + 3;
full_symbol = (char *) stp_malloc(sizeof(char) * len);
len = 0;
strncpy (full_symbol, module, strlen(module) - 3);
len = strlen(module) - 3;
strcpy (full_symbol+len, "_LTX_");
len += 5;
strcpy (full_symbol+len, symbol);
len += strlen(symbol);
full_symbol[len] = '\0';
#if defined(__OpenBSD__)
{
char *prefix_symbol = stp_malloc(sizeof(char) * (strlen(full_symbol) + 2));
prefix_symbol[0] = '_';
strcpy(prefix_symbol+1, full_symbol);
stp_free(full_symbol);
full_symbol = prefix_symbol;
}
#endif
for (len = 0; full_symbol[len] != '\0'; len++)
if (full_symbol[len] == '-')
full_symbol[len] = '_';
stp_deprintf(STP_DBG_MODULE, "SYMBOL: %s\n", full_symbol);
return dlsym(handle, full_symbol);
}
#endif