diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/db4.c | 0 | ||||
-rw-r--r-- | src/db4.h | 5 | ||||
-rw-r--r-- | src/engine.c | 93 | ||||
-rw-r--r-- | src/engine.h | 28 | ||||
-rw-r--r-- | src/fake_rcd.h | 22 | ||||
-rw-r--r-- | src/fs.c | 3 | ||||
-rw-r--r-- | src/internal.h | 5 | ||||
-rw-r--r-- | src/librcc.c | 46 | ||||
-rw-r--r-- | src/librcc.h | 15 | ||||
-rw-r--r-- | src/lng.c | 29 | ||||
-rw-r--r-- | src/lng.h | 6 | ||||
-rw-r--r-- | src/lngconfig.c | 80 | ||||
-rw-r--r-- | src/lngconfig.h | 5 | ||||
-rw-r--r-- | src/opt.h | 19 | ||||
-rw-r--r-- | src/plugin.c | 1 | ||||
-rw-r--r-- | src/rccconfig.c | 20 | ||||
-rw-r--r-- | src/rccdb4.c | 124 | ||||
-rw-r--r-- | src/rccdb4.h | 23 | ||||
-rw-r--r-- | src/rccenca.c | 24 | ||||
-rw-r--r-- | src/rccxml.c | 97 | ||||
-rw-r--r-- | src/recode.c | 16 |
22 files changed, 562 insertions, 105 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index bef8240..022ef1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,9 @@ librcc_la_SOURCES = librcc.c \ rccconfig.c rccconfig.h \ rcclist.c rcclist.h \ plugin.c plugin.h \ + fake_enca.h fake_rcd.h \ rccenca.c rccenca.h \ + rccdb4.c rccdb4.h \ engine.c engine.h \ rccstring.c rccstring.h \ rccxml.c rccxml.h \ @@ -18,7 +20,7 @@ librcc_la_SOURCES = librcc.c \ internal.h include_HEADERS = librcc.h -INCLUDES = @XML_INCLUDES@ @RCD_INCLUDES@ @ENCA_INCLUDES@ -librcc_la_LIBADD = @XML_LIBS@ @RCD_LIBS@ @ENCA_LIBS@ +INCLUDES = @XML_INCLUDES@ @DLOPEN_INCLUDES@ @RCD_INCLUDES@ @ENCA_INCLUDES@ @BDB_INCLUDES@ +librcc_la_LIBADD = @XML_LIBS@ @DLOPEN_LIBS@ @RCD_LIBS@ @ENCA_LIBS@ @BDB_LIBS@ librcc_la_LDFLAGS = -version-info @LIBRCC_VERSION_INFO@ diff --git a/src/db4.c b/src/db4.c deleted file mode 100644 index e69de29..0000000 --- a/src/db4.c +++ /dev/null diff --git a/src/db4.h b/src/db4.h deleted file mode 100644 index e13dd5f..0000000 --- a/src/db4.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _RCC_DB4_H -#define _RCC_DB4_H - - -#endif /* _RCC_DB4_H */ diff --git a/src/engine.c b/src/engine.c index 5f7a3ff..5bb8b7a 100644 --- a/src/engine.c +++ b/src/engine.c @@ -2,8 +2,95 @@ #include <string.h> #include "internal.h" +#include "plugin.h" +#include "rccconfig.h" -int rccEngineInit(rcc_engine_context engine_ctx, rcc_context ctx) { +#include "engine.h" + +#ifdef RCC_RCD_SUPPORT +# ifdef RCC_RCD_DYNAMIC +# include "fake_rcd.h" +# else +# include <librcd.h> +# endif /* RCC_RCD_DYNAMIC */ +#endif /* RCC_RCD_SUPPORT */ + +static rcc_library_handle rcd_handle = NULL; + +rcc_charset_id rccAutoengineRussian(rcc_engine_context ctx, const char *buf, int len) { +#ifdef RCC_RCD_SUPPORT + rcc_charset_id id; +# ifdef RCC_RCD_DYNAMIC + if (!rcdGetRussianCharset) return (rcc_charset_id)-1; +# endif /* RCC_RCD_DYNAMIC */ + return (rcc_charset_id)rcdGetRussianCharset(buf,len); +#else /* RCC_RCD_SUPPORT */ + return (rcc_charset_id)-1; +#endif /* RCC_RCD_SUPPORT */ +} + + +static int rccRCDLibraryLoad() { +#ifdef RCC_RCD_DYNAMIC + if (rcd_handle) return 0; + + rcd_handle = rccLibraryOpen(RCC_RCD_LIB); + if (!rcd_handle) return -1; + + rcdGetRussianCharset = rccLibraryFind(rcd_handle,"rcdGetRussianCharset"); + if (!rcdGetRussianCharset) { + rccLibraryClose(rcd_handle); + rcd_handle = NULL; +# ifdef RCC_DEBUG + perror( "rccRCD. Incomplete function set in library" ); +# endif /* RCC_DEBUG */ + return -1; + } +#endif /* RCC_RCD_DYNAMIC */ + + return 0; +} + +static void rccRCDLibraryUnload() { +#ifdef RCC_RCD_DYNAMIC + if (rcd_handle) { + rccLibraryClose(rcd_handle); + rcd_handle = NULL; + } +#endif /* RCC_RCD_DYNAMIC */ +} + +int rccEngineInit() { +#ifdef RCC_RCD_DYNAMIC + int err; + unsigned int i,j,flag; + rcc_engine **engines; + int *charsets; + + err = rccRCDLibraryLoad(); + if (err) { + for (i=0;rcc_default_languages[i].sn;i++) { + engines = rcc_default_languages[i].engines; + for (flag=0,j=0;engines[j];j++) { + if (flag) engines[j-1] = engines[j]; + else if (engines[j] == &rcc_russian_engine) flag=1; + } + if (flag) engines[j-1] = NULL; + } + } +#endif /* RCC_RCD_DYNAMIC */ + + return rccEncaInit(); +} + +void rccEngineFree() { + rccEncaFree(); +#ifdef RCC_RCD_DYNAMIC + rccRCDLibraryUnload(); +#endif /* RCC_RCD_DYNAMIC */ +} + +int rccEngineInitContext(rcc_engine_context engine_ctx, rcc_context ctx) { if ((!ctx)||(!engine_ctx)) return -1; engine_ctx->ctx = ctx; @@ -12,7 +99,7 @@ int rccEngineInit(rcc_engine_context engine_ctx, rcc_context ctx) { return 0; } -void rccEngineFree(rcc_engine_context engine_ctx) { +void rccEngineFreeContext(rcc_engine_context engine_ctx) { if (!engine_ctx) return; if (engine_ctx->free_func) { @@ -31,7 +118,7 @@ int rccEngineConfigure(rcc_engine_context ctx) { if ((!ctx)||(!ctx->ctx)) return -1; - rccEngineFree(ctx); + rccEngineFreeContext(ctx); language_id = rccGetCurrentLanguage(ctx->ctx); if (language_id == (rcc_language_id)-1) return -1; diff --git a/src/engine.h b/src/engine.h index c0cb57d..0d16d9f 100644 --- a/src/engine.h +++ b/src/engine.h @@ -1,6 +1,25 @@ #ifndef _RCC_ENGINE_H #define _RCC_ENGINE_H +#include "../config.h" + +#ifdef HAVE_RCD +# define RCC_RCD_SUPPORT +# undef RCC_RCD_DYNAMIC +#elif HAVE_DLOPEN +# define RCC_RCD_SUPPORT +# define RCC_RCD_DYNAMIC +#else +# undef RCC_RCD_SUPPORT +# undef RCC_RCD_DYNAMIC +#endif + +#define RCC_RCD_LIB "librcd.so.0" + +#ifdef RCC_RCD_DYNAMIC +# define RCC_RCD_SUPPORT +#endif + struct rcc_engine_context_t { rcc_context ctx; rcc_language *language; @@ -12,9 +31,14 @@ struct rcc_engine_context_t { }; typedef struct rcc_engine_context_t rcc_engine_context_s; -int rccEngineInit(rcc_engine_context engine_ctx, rcc_context ctx); -void rccEngineFree(rcc_engine_context engine_ctx); +int rccEngineInit(); +void rccEngineFree(); + +int rccEngineInitContext(rcc_engine_context engine_ctx, rcc_context ctx); +void rccEngineFreeContext(rcc_engine_context engine_ctx); rcc_engine_internal rccEngineGetInternal(rcc_engine_context ctx); +rcc_charset_id rccAutoengineRussian(rcc_engine_context ctx, const char *buf, int len); + #endif /* _RCC_ENGINE_H */ diff --git a/src/fake_rcd.h b/src/fake_rcd.h new file mode 100644 index 0000000..8dcb9ae --- /dev/null +++ b/src/fake_rcd.h @@ -0,0 +1,22 @@ +#ifndef _LIBRCD_H +#define _LIBRCD_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum rcd_russian_charset_t { + RUSSIAN_CHARSET_WIN = 0, + RUSSIAN_CHARSET_KOI, + RUSSIAN_CHARSET_UTF8, + RUSSIAN_CHARSET_ALT +}; +typedef enum rcd_russian_charset_t rcd_russian_charset; + +rcd_russian_charset (*rcdGetRussianCharset)(const char *buf, int len) = NULL; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBRCD_H */ @@ -174,15 +174,12 @@ const char *rccFS2(rcc_context ctx, iconv_t icnv, const char *prefix, const char if (icnv == (iconv_t)-1) return NULL; if (icnv == (iconv_t)-2) { - puts("-1"); strncpy(ctx->tmpbuffer, name, RCC_MAX_STRING_CHARS); ctx->tmpbuffer[RCC_MAX_STRING_CHARS] = 0; } else { - puts("-2"); err = rccIConv(ctx, icnv, name, 0); if (err<=0) return NULL; } - puts("ok"); return rccCheckFile(prefix, ctx->tmpbuffer); } diff --git a/src/internal.h b/src/internal.h index ac9a74e..8a99ca0 100644 --- a/src/internal.h +++ b/src/internal.h @@ -7,6 +7,7 @@ #include "engine.h" #include "lngconfig.h" #include "rccstring.h" +#include "rccdb4.h" #define STRNLEN(str,n) (n?strnlen(str,n):strlen(str)) @@ -44,6 +45,8 @@ struct rcc_context_t { rcc_language_config current_config; rcc_language_id current_language; + db4_context db4ctx; + unsigned int configuration_lock; }; typedef struct rcc_context_t rcc_context_s; @@ -52,4 +55,6 @@ int rccConfigure(rcc_context ctx); char *rccCreateResult(rcc_context ctx, size_t len, size_t *rlen); extern rcc_context rcc_default_ctx; +extern char *rcc_home_dir; + #endif /* _RCC_INTERNAL_H */ diff --git a/src/librcc.c b/src/librcc.c index d29ba8b..2e2a49e 100644 --- a/src/librcc.c +++ b/src/librcc.c @@ -16,13 +16,11 @@ # include <pwd.h> #endif /* HAVE_PWD_H */ -#include <librcd.h> - #include "internal.h" #include "rccconfig.h" #include "rccenca.h" #include "rcclist.h" -#include "rccenca.h" +#include "engine.h" #include "rccxml.h" static int initialized = 0; @@ -51,8 +49,7 @@ int rccInit() { #endif /* HAVE_PWD_H */ if (!rcc_home_dir) rcc_home_dir = strdup("/"); - - err = rccEncaInit(); + err = rccEngineInit(); if (!err) err = rccXmlInit(); if (err) { @@ -72,7 +69,7 @@ void rccFree() { } rccXmlFree(); - rccEncaFree(); + rccEngineFree(); if (rcc_home_dir) { free(rcc_home_dir); @@ -126,6 +123,8 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu } ctx->configuration_lock = 0; + + ctx->db4ctx = NULL; ctx->aliases[0] = NULL; for (i=0;rcc_default_aliases[i].alias;i++) @@ -158,7 +157,7 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu for (i=0;i<max_languages;i++) configs[i].charset = NULL; - err = rccEngineInit(&ctx->engine_ctx, ctx); + err = rccEngineInitContext(&ctx->engine_ctx, ctx); if (err) { rccFree(ctx); return NULL; @@ -175,6 +174,8 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu } else { strcpy(ctx->locale_variable, RCC_LOCALE_VARIABLE); } + + for (i=0;i<RCC_MAX_OPTIONS;i++) rccOptionSetDefault(ctx, (rcc_option)i); if (flags&RCC_NO_DEFAULT_CONFIGURATION) { rccRegisterLanguage(ctx, rcc_default_languages); @@ -201,11 +202,6 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu } } - for (i=0;i<RCC_MAX_OPTIONS;i++) { - ctx->options[i] = rccGetOptionDefaultValue((rcc_option)i); - ctx->default_options[i] = 1; - } - ctx->configure = 1; return ctx; @@ -251,7 +247,8 @@ void rccFreeContext(rcc_context ctx) { unsigned int i; if (ctx) { - rccEngineFree(&ctx->engine_ctx); + if (ctx->db4ctx) rccDb4FreeContext(ctx->db4ctx); + rccEngineFreeContext(&ctx->engine_ctx); rccFreeIConv(ctx); if (ctx->iconv_from) free(ctx->iconv_from); if (ctx->iconv_to) free(ctx->iconv_to); @@ -380,14 +377,19 @@ int rccConfigure(rcc_context ctx) { unsigned int i; rcc_charset *charsets; const char *charset; + rcc_language_config cfg; if (!ctx) return -1; if (!ctx->configure) return 0; - rccGetCurrentCharsetName(ctx, (rcc_class_id)0); + cfg = rccGetCurrentConfig(ctx); + if (!cfg) return 1; + + rccConfigGetCurrentCharsetName(cfg, (rcc_class_id)0); rccFreeIConv(ctx); for (i=0;i<ctx->n_classes;i++) { - charset = rccGetCurrentCharsetName(ctx, (rcc_class_id)i); + charset = rccConfigGetCurrentCharsetName(cfg, (rcc_class_id)i); + if (!charset) continue; printf("Configure %i: %s\n", i, charset); if (strcmp(charset, "UTF-8")&&strcmp(charset, "UTF8")) { ctx->iconv_from[i] = iconv_open("UTF-8", charset); @@ -399,12 +401,14 @@ int rccConfigure(rcc_context ctx) { } charsets = rccGetCurrentAutoCharsetList(ctx); - for (i=0;charsets[i];i++) { - charset = charsets[i]; - if (strcmp(charset, "UTF-8")&&strcmp(charset, "UTF8")) - ctx->iconv_auto[i] = iconv_open("UTF-8", charset); - else - ctx->iconv_auto[i] = (iconv_t)-2; + if (charsets) { + for (i=0;charsets[i];i++) { + charset = charsets[i]; + if (strcmp(charset, "UTF-8")&&strcmp(charset, "UTF8")) + ctx->iconv_auto[i] = iconv_open("UTF-8", charset); + else + ctx->iconv_auto[i] = (iconv_t)-2; + } } err = rccEngineConfigure(&ctx->engine_ctx); diff --git a/src/librcc.h b/src/librcc.h index 79aab7e..e6fe7bc 100644 --- a/src/librcc.h +++ b/src/librcc.h @@ -48,6 +48,9 @@ rcc_context rccCreateContext(const char *locale_variable, unsigned int max_langu int rccInitDefaultContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags); void rccFreeContext(rcc_context ctx); +typedef unsigned int rcc_db4_flags; +int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags); + int rccLockConfiguration(rcc_context ctx, unsigned int lock_code); int rccUnlockConfiguration(rcc_context ctx, unsigned int lock_code); @@ -114,10 +117,17 @@ typedef enum rcc_class_type_t { RCC_CLASS_FS } rcc_class_type; +struct rcc_class_default_charset_t { + const char *lang; + const char *charset; +}; +typedef const struct rcc_class_default_charset_t rcc_class_default_charset; + struct rcc_class_t { const char *name; - const char *defvalue; /* locale variable name or parrent name */ const rcc_class_type class_type; + const char *defvalue; /* locale variable name or parrent name */ + rcc_class_default_charset *defcharset; const char *fullname; }; typedef const struct rcc_class_t rcc_class; @@ -134,6 +144,7 @@ typedef enum rcc_option_t { RCC_LEARNING_MODE = 0, RCC_AUTODETECT_FS_TITLES, RCC_AUTODETECT_FS_NAMES, + RCC_CONFIGURED_LANGUAGES_ONLY, RCC_MAX_OPTIONS } rcc_option; @@ -141,7 +152,7 @@ struct rcc_option_name_t { rcc_option option; const char *name; - const char *sn; + const char **subnames; }; typedef struct rcc_option_name_t rcc_option_name; @@ -29,9 +29,9 @@ rcc_language_id rccGetLanguageByName(rcc_context ctx, const char *name) { else return (rcc_language_id)-1; } if (!name) return (rcc_language_id)-1; - - for (i=0;ctx->languages[i];i++) - if (!strcmp(ctx->languages[i]->sn, name)) return i; + + for (i=0;ctx->languages[i];i++) + if (!strcasecmp(ctx->languages[i]->sn, name)) return (rcc_language_id)i; return (rcc_language_id)-1; } @@ -41,16 +41,18 @@ static rcc_language_id rccGetDefaultLanguage(rcc_context ctx) { unsigned int i; char stmp[RCC_MAX_LANGUAGE_CHARS+1]; - err = rccLocaleGetLanguage(stmp, ctx->locale_variable, RCC_MAX_LANGUAGE_CHARS); - if (err) { - if (ctx->n_languages>1) return (rcc_language_id)1; - return (rcc_language_id)-1; + if (!rccLocaleGetLanguage(stmp, ctx->locale_variable, RCC_MAX_LANGUAGE_CHARS)) { + for (i=0;ctx->languages[i];i++) { + if (!strcmp(ctx->languages[i]->sn, stmp)) { + if (rccGetOption(ctx, RCC_CONFIGURED_LANGUAGES_ONLY)) { + if (!rccCheckConfig(ctx, (rcc_language_id)i)) break; + } + return (rcc_language_id)i; + } + } } - for (i=0;ctx->languages[i];i++) - if (!strcmp(ctx->languages[i]->sn, stmp)) return (rcc_language_id)i; - - if (i>1) return (rcc_language_id)1; + if (ctx->n_languages>1) return (rcc_language_id)1; return (rcc_language_id)-1; } @@ -116,17 +118,20 @@ int rccSetLanguage(rcc_context ctx, rcc_language_id language_id) { if (rcc_default_ctx) ctx = rcc_default_ctx; else return -1; } + if ((language_id < 0)||(language_id >= ctx->n_languages)) return -1; if ((!ctx->languages[language_id]->engines[0])||(!ctx->languages[language_id]->charsets[0])) return -2; if (ctx->current_language != language_id) { config = rccGetConfig(ctx, language_id); - if (!config) return -1; + // NULL is Okey (Off), if (!config) return -1; ctx->configure = 1; ctx->current_language = language_id; ctx->current_config = config; } + + return 0; } int rccSetLanguageByName(rcc_context ctx, const char *name) { @@ -1,10 +1,14 @@ #ifndef _RCC_LNG_H #define _RCC_LNG_H +#include "internal.h" #include "lngconfig.h" rcc_language_ptr rccGetLanguagePointer(rcc_context ctx, rcc_language_id language_id); -#define rccGetEnginePointer(ctx, engine_id) rccConfigGetEnginePointer(ctx->current_config, engine_id) +#define rccGetCurrentEnginePointer(ctx) rccConfigGetCurrentEnginePointer(ctx->current_config) +#define rccCheckCurrentEnginePointer(ctx) rccConfigCheckCurrentEnginePointer(ctx->current_config) +#define rccGetEnginePointer(ctx,id) rccConfigGetEnginePointer(ctx->current_config, id) +#define rccCheckEnginePointer(ctx,id) rccConfigCheckEnginePointer(ctx->current_config, id) #endif /* _RCC_LNG_H */ diff --git a/src/lngconfig.c b/src/lngconfig.c index 9748629..39fca76 100644 --- a/src/lngconfig.c +++ b/src/lngconfig.c @@ -8,22 +8,56 @@ rcc_engine_ptr rccConfigGetEnginePointer(rcc_language_config config, rcc_engine_id engine_id) { unsigned int i; rcc_engine_ptr *engines; - - if ((!config)||(!config->language)||(engine_id<0)) return NULL; - engines = config->language->engines; + if ((!config)||(!config->language)||(engine_id<0)) return NULL; + if (engine_id == (rcc_engine_id)-1) return NULL; + engines = config->language->engines; for (i=0;engines[i];i++); if (engine_id>=i) return NULL; return engines[engine_id]; } +rcc_engine_ptr rccConfigCheckEnginePointer(rcc_language_config config, rcc_engine_id engine_id) { + rcc_engine_ptr engine; + + engine = rccConfigGetEnginePointer(config, engine_id); + if ((engine)||(engine->func)) return engine; + return NULL; +} + +rcc_engine_ptr rccConfigGetCurrentEnginePointer(rcc_language_config config) { + unsigned int i; + rcc_engine_id engine_id; + rcc_engine_ptr *engines; + + engine_id = rccConfigGetCurrentEngine(config); + if (engine_id == (rcc_engine_id)-1) return NULL; + + return rccConfigGetEnginePointer(config, engine_id); +} + +rcc_engine_ptr rccConfigCheckCurrentEnginePointer(rcc_language_config config) { + rcc_engine_ptr engine; + + engine = rccConfigGetCurrentEnginePointer(config); + if ((engine)||(engine->func)) return engine; + return NULL; +} + + const char *rccConfigGetEngineName(rcc_language_config config, rcc_engine_id engine_id) { + unsigned int i; rcc_engine_ptr engine; + + if ((!config)||(!config->language)||(engine_id<-1)) return NULL; + if (engine_id == (rcc_engine_id)-1) return rcc_engine_nonconfigured; + engine = rccConfigGetEnginePointer(config, engine_id); if (!engine) return NULL; + return engine->title; } @@ -43,13 +77,16 @@ const char *rccConfigGetCharsetName(rcc_language_config config, rcc_charset_id c const char *rccConfigGetAutoCharsetName(rcc_language_config config, rcc_charset_id charset_id) { unsigned int i; + rcc_engine_id engine_id; rcc_charset *charsets; rcc_engine_ptr *engines; if ((!config)||(!config->language)||(charset_id<0)) return NULL; + engine_id = rccConfigGetCurrentEngine(config); + if (engine_id == (rcc_engine_id)-1) return NULL; engines = config->language->engines; - charsets = engines[config->engine]->charsets; + charsets = engines[engine_id]->charsets; for (i=0;charsets[i];i++); if (charset_id>=i) return NULL; @@ -62,11 +99,11 @@ rcc_engine_id rccConfigGetEngineByName(rcc_language_config config, const char *n unsigned int i; rcc_engine **engines; - if ((!config)||(!config->language)||(!name)) return -1; + if ((!config)||(!config->language)||(!name)) return (rcc_engine_id)-1; engines = config->language->engines; for (i=0;engines[i];i++) - if (!strcasecmp(engines[i]->title,name)) return i; + if (!strcasecmp(engines[i]->title,name)) return (rcc_engine_id)i; return (rcc_engine_id)-1; } @@ -86,17 +123,21 @@ rcc_charset_id rccConfigGetCharsetByName(rcc_language_config config, const char rcc_charset_id rccConfigGetAutoCharsetByName(rcc_language_config config, const char *name) { unsigned int i; + rcc_engine_id engine_id; rcc_charset *charsets; rcc_engine_ptr *engines; if ((!config)||(!config->language)||(!name)) return (rcc_charset_id)-1; + + engine_id = rccConfigGetCurrentEngine(config); + if (engine_id == (rcc_engine_id)-1) return (rcc_charset_id)-1; engines = config->language->engines; - charsets = engines[config->engine]->charsets; + charsets = engines[engine_id]->charsets; for (i=0;charsets[i];i++) if (!strcasecmp(charsets[i],name)) return (rcc_charset_id)i; - + return (rcc_charset_id)-1; } @@ -132,7 +173,7 @@ rcc_language_config rccCheckConfig(rcc_context ctx, rcc_language_id language_id) int err; new_language_id = rccGetRealLanguage(ctx, language_id); - if ((language_id == (rcc_language_id)-1)||(new_language_id != language_id)) return NULL; + if ((new_language_id == (rcc_language_id)-1)||(new_language_id != language_id)) return NULL; if (!ctx->configs[language_id].charset) return NULL; if (!strcasecmp(ctx->languages[language_id]->sn, "off")) return NULL; @@ -144,6 +185,8 @@ rcc_language_config rccGetConfig(rcc_context ctx, rcc_language_id language_id) { language_id = rccGetRealLanguage(ctx, language_id); if (language_id == (rcc_language_id)-1) return NULL; + if (!strcasecmp(ctx->languages[language_id]->sn, "off")) return NULL; + if (!ctx->configs[language_id].charset) { if (rccConfigInit(ctx->configs+language_id, ctx)) return NULL; } @@ -190,6 +233,8 @@ rcc_engine_id rccConfigGetCurrentEngine(rcc_language_config config) { rcc_engine **enginelist; rcc_engine_id engine_id; + if (!config) return (rcc_engine_id)-1; + engine_id = rccConfigGetSelectedEngine(config); if (engine_id != (rcc_engine_id)-1) return engine_id; @@ -213,7 +258,7 @@ const char *rccConfigGetCurrentEngineName(rcc_language_config config) { } rcc_charset_id rccConfigGetSelectedCharset(rcc_language_config config, rcc_class_id class_id) { - if ((!config)||(!config->ctx)||(class_id<0)||(class_id>=config->ctx->n_classes)) return -1; + if ((!config)||(!config->ctx)||(class_id<0)||(class_id>=config->ctx->n_classes)) return (rcc_charset_id)-1; return config->charset[class_id]; } @@ -232,6 +277,9 @@ rcc_charset_id rccConfigGetCurrentCharset(rcc_language_config config, rcc_class_ unsigned int i; rcc_charset_id charset_id; + rcc_class_default_charset *defcharset; + const char *lang; + rcc_language *language; rcc_class_ptr *classes; rcc_charset *charsets; @@ -262,7 +310,17 @@ rcc_charset_id rccConfigGetCurrentCharset(rcc_language_config config, rcc_class_ charset_id = rccConfigGetLocaleCharset(config, defvalue); if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) return charset_id; - + + defcharset = cl->defcharset; + if (defcharset) { + lang = config->language->sn; + + for (i = 0; cl->defcharset[i].lang; i++) { + if (!strcasecmp(lang, defcharset[i].lang)) + return rccConfigGetCharsetByName(config, defcharset[i].charset); + } + } + charsets=language->charsets; if ((charsets[0])&&(charsets[1])) return (rcc_charset_id)1; return (rcc_charset_id)-1; diff --git a/src/lngconfig.h b/src/lngconfig.h index 4e9681c..64ca523 100644 --- a/src/lngconfig.h +++ b/src/lngconfig.h @@ -1,6 +1,7 @@ #ifndef _RCC_LNGCONFIG_H #define _RCC_LNGCONFIG_H + struct rcc_language_config_t { rcc_context ctx; rcc_language *language; @@ -10,7 +11,11 @@ struct rcc_language_config_t { }; typedef struct rcc_language_config_t rcc_language_config_s; + rcc_engine_ptr rccConfigGetEnginePointer(rcc_language_config config, rcc_engine_id engine_id); +rcc_engine_ptr rccConfigCheckEnginePointer(rcc_language_config config, rcc_engine_id engine_id); +rcc_engine_ptr rccConfigGetCurrentEnginePointer(rcc_language_config config); +rcc_engine_ptr rccConfigCheckCurrentEnginePointer(rcc_language_config config); int rccConfigInit(rcc_language_config config, rcc_context ctx); int rccConfigFree(rcc_language_config config); @@ -7,4 +7,23 @@ struct rcc_option_defval_t { }; typedef struct rcc_option_defval_t rcc_option_defval; +enum rcc_option_type_t { + RCC_OPTION_TYPE_BOOLEAN = 0, + RCC_OPTION_TYPE_RANGE, + RCC_OPTION_TYPE_FLAGS, + RCC_OPTION_TYPE_MENU +}; +typedef enum rcc_option_type_t rcc_option_type; + +struct rcc_option_description_t { + rcc_option option; + const char *sn; + rcc_option_type; + rcc_option_value min; + rcc_option_value max; + +}; +typedef struct rcc_option_description_t rcc_option_description; + + #endif /* _RCC_OPT_H */ diff --git a/src/plugin.c b/src/plugin.c index a50bff3..7935491 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -22,6 +22,7 @@ rcc_library_handle rccLibraryOpen(char *filename) void rccLibraryClose(rcc_library_handle handle) { #ifdef RCC_PLUGINS + puts("HHHHHHHHHHHHHHHHHHHH"); dlclose(handle); #endif /* RCC_PLUGINS */ } diff --git a/src/rccconfig.c b/src/rccconfig.c index e1ac34a..d40941f 100644 --- a/src/rccconfig.c +++ b/src/rccconfig.c @@ -1,14 +1,10 @@ #include <stdio.h> -#include <librcd.h> #include "internal.h" #include "rccconfig.h" +#include "engine.h" #include "opt.h" -static rcc_charset_id rcc_autoengine_russian(rcc_engine_context ctx, const char *buf, int len) { - return (rcc_charset_id)rcdGetRussianCharset(buf,len); -} - rcc_language_alias rcc_default_aliases[] = { { "cs_SK", "sk" }, { "ru_UA", "uk" }, @@ -23,7 +19,7 @@ rcc_engine rcc_default_engine = { }; rcc_engine rcc_russian_engine = { - "Russian", NULL, NULL, &rcc_autoengine_russian, {"CP1251","KOI8-R","UTF-8","IBM866", NULL} + "Russian", NULL, NULL, &rccAutoengineRussian, {"CP1251","KOI8-R","UTF-8","IBM866", NULL} }; rcc_language rcc_default_languages[RCC_MAX_LANGUAGES + 1] = { @@ -37,12 +33,16 @@ rcc_language rcc_default_languages[RCC_MAX_LANGUAGES + 1] = { }}, {"ru", {"Default","KOI8-R","CP1251","UTF-8","IBM866","MACCYRILLIC","ISO8859-5", NULL}, { &rcc_default_engine, +#ifdef RCC_RCD_SUPPORT &rcc_russian_engine, +#endif /* RCC_RCD_SUPPORT */ NULL }}, {"uk", {"Default","KOI8-U","CP1251","UTF-8","IBM855","MACCYRILLIC","ISO8859-5","CP1125", NULL}, { &rcc_default_engine, +#ifdef RCC_RCD_SUPPORT &rcc_russian_engine, +#endif /* RCC_RCD_SUPPORT */ NULL }}, {"be", {"Default", "UTF-8", "CP1251", "IBM866", "ISO-8859-5", "KOI8-UNI", "maccyr" "IBM855", NULL},{ @@ -116,6 +116,13 @@ rcc_language_name rcc_default_language_names[RCC_MAX_LANGUAGES+1] = { {NULL, NULL} }; +rcc_option_description rcc_default_option_descriptions[] = { + {RCC_LEARNING_MODE, "LEARNING_MODE", RCC_OPTION_TYPE_BOOLEAN, 0, 0}, + {RCC_AUTODETECT_FS_TITLES, "AUTODETECT_FS_TITLES", RCC_OPTION_TYPE_BOOLEAN, 0, 0}, + {RCC_AUTODETECT_FS_NAMES, "AUTODETECT_FS_NAMES", RCC_OPTION_TYPE_NAMES; + {RCC_AUTODETECT_FS_TITLES, "AUTODETECT_FS_TITLES", RCC_OPTION_TYPE_NAMES; + RCC_CONFIGURED_LANGUAGES_ONLY + rcc_option_name rcc_default_option_names[] = { { RCC_LEARNING_MODE, "Learning Mode", "LEARNING_MODE" }, { RCC_AUTODETECT_FS_TITLES, "Autodetect FS Encoding", "AUTODETECT_FS_TITLES" }, @@ -127,6 +134,7 @@ rcc_option_defval rcc_default_option_values[] = { { RCC_LEARNING_MODE, 0 }, { RCC_AUTODETECT_FS_TITLES, 1}, { RCC_AUTODETECT_FS_NAMES, 1}, + { RCC_CONFIGURED_LANGUAGES_ONLY, 1}, { RCC_MAX_OPTIONS, 0} }; diff --git a/src/rccdb4.c b/src/rccdb4.c new file mode 100644 index 0000000..795b721 --- /dev/null +++ b/src/rccdb4.c @@ -0,0 +1,124 @@ +#include <stdio.h> + +#include "internal.h" +#include "rccdb4.h" + +#define DATABASE "autolearn.db" +#define MIN_CHARS 3 + +int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) { + size_t size; + char *dbname; + + if (!ctx) { + if (rcc_default_ctx) ctx = rcc_default_ctx; + else return -1; + } + + if (!name) name = "default"; + + size = strlen(rcc_home_dir) + strlen(name) + 32; + dbname = (char*)malloc(size*sizeof(char)); + if (!dbname) return -1; + + sprintf(dbname,"%s/.rcc/",rcc_home_dir); + mkdir(dbname, 00644); + + sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name); + mkdir(dbname, 00644); + + ctx->db4ctx = rccDb4CreateContext(dbname, flags); + free(dbname); + + if (!ctx->db4ctx) return -1; + + return 0; +} + +db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) { + int err; + db4_context ctx; + DB_ENV *dbe; + DB *db; + + err = db_env_create(&dbe, 0); + if (err) return NULL; + + err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0); + if (err) { + dbe->close(dbe, 0); + return NULL; + } + + err = db_create(&db, dbe, 0); + if (err) { + dbe->close(dbe, 0); + return NULL; + } + + err = db->open(db, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0); + if (err) { + db->close(db, 0); + dbe->close(dbe, 0); + return NULL; + } + + ctx = (db4_context)malloc(sizeof(db4_context_s)); + if (!ctx) { + db->close(db, 0); + dbe->close(dbe, 0); + return NULL; + } + + ctx->db = db; + ctx->dbe = dbe; + ctx->flags = flags; + return ctx; +} + +void rccDb4FreeContext(db4_context ctx) { + if (ctx) { + ctx->db->close(ctx->db, 0); + ctx->dbe->close(ctx->dbe, 0); + free(ctx); + } +} + +int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string, size_t slen) { + int err; + DBT key, data; + + if ((!ctx)||(!orig)||(!string)) return -1; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = (char*)orig; + key.size = STRNLEN(orig, olen); + data.data = (char*)string; + data.size = STRNLEN(string, slen); + + if (key.size < MIN_CHARS) return -1; + + err = ctx->db->put(ctx->db, NULL, &key, &data, 0); + return err; +} + +rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) { + int err; + DBT key, data; + + if ((!ctx)||(!orig)) return NULL; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = (char*)orig; + key.size = STRNLEN(orig, olen); + + data.flags = DB_DBT_REALLOC; + + err = ctx->db->get(ctx->db, NULL, &key, &data, 0); + if (err) return NULL; + return data.data; +} diff --git a/src/rccdb4.h b/src/rccdb4.h new file mode 100644 index 0000000..0fb55b7 --- /dev/null +++ b/src/rccdb4.h @@ -0,0 +1,23 @@ +#ifndef _RCC_DB4_H +#define _RCC_DB4_H + +#include <db.h> +#include "rccstring.h" + +struct db4_context_t { + DB_ENV *dbe; + DB *db; + + rcc_db4_flags flags; +}; + +typedef struct db4_context_t db4_context_s; +typedef struct db4_context_t *db4_context; + +db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags); +void rccDb4FreeContext(db4_context ctx); + +int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string, size_t slen); +rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen); + +#endif /* _RCC_DB4_H */ diff --git a/src/rccenca.c b/src/rccenca.c index 1aabf7a..8a439bc 100644 --- a/src/rccenca.c +++ b/src/rccenca.c @@ -56,18 +56,17 @@ rcc_charset_id rccEnca(rcc_engine_context ctx, const char *buf, int len) { EncaEncoding ee; internal = rccEngineGetInternal(ctx); - if ((!internal)||(!buf)) return -1; - + if ((!internal)||(!buf)) return (rcc_charset_id)-1; len = STRNLEN(buf, len); ee = enca_analyse_const((EncaAnalyser)ctx->internal,buf,len); - if (ee.charset<0) return -1; + if (ee.charset<0) return (rcc_charset_id)-1; charset = enca_charset_name(ee.charset, ENCA_NAME_STYLE_ICONV); return rccGetAutoCharsetByName(ctx->ctx, charset); #else /* RCC_ENCA_SUPPORT */ - return -1; + return (rcc_charset_id)-1; #endif /* RCC_ENCA_SUPPORT */ } @@ -107,6 +106,7 @@ static int rccEncaLibraryLoad() { # ifdef RCC_DEBUG perror( "rccEnca. Incomplete function set in library" ); # endif /* RCC_DEBUG */ + return -1; } #endif /* RCC_ENCA_DYNAMIC */ @@ -116,7 +116,7 @@ static int rccEncaLibraryLoad() { static void rccEncaLibraryUnload() { #ifdef RCC_ENCA_DYNAMIC if (enca_handle) { - rccLibraryUnload(enca_handle); + rccLibraryClose(enca_handle); enca_handle = NULL; } #endif /* RCC_ENCA_DYNAMIC */ @@ -130,15 +130,16 @@ int rccEncaInit() { int *charsets; size_t n_charsets; + const char *charset; #ifdef RCC_ENCA_SUPPORT - if (enca_engines) return -1; + if (enca_engines) return 0; for (i=0;rcc_default_languages[i].sn;i++); enca_engines = (rcc_engine*)malloc(i*sizeof(rcc_engine)); if (!enca_engines) return -1; err = rccEncaLibraryLoad(); - if (err) return err; + if (err) return 0; for (i=0;rcc_default_languages[i].sn;i++) { engines = rcc_default_languages[i].engines; @@ -152,10 +153,15 @@ int rccEncaInit() { if (charsets) { memcpy(enca_engines+i, &rcc_enca_engine, sizeof(rcc_engine)); for (k=0;enca_engines[i].charsets[k];k++); + if (n_charsets+k>=RCC_MAX_CHARSETS) n_charsets = RCC_MAX_CHARSETS-k; - for (l=0;l<n_charsets;l++) - enca_engines[j].charsets[k++] = enca_charset_name(charsets[l], ENCA_NAME_STYLE_ICONV); + for (l=0;l<n_charsets;l++) { + // Enca bug, STYLE_ICONV return's a lot of NULL's + charset = enca_charset_name(charsets[l], ENCA_NAME_STYLE_ICONV); + if (!charset) charset = enca_charset_name(charsets[l], ENCA_NAME_STYLE_ENCA); + enca_engines[i].charsets[k++] = charset; + } enca_engines[j].charsets[k] = NULL; engines[j] = enca_engines + i; diff --git a/src/rccxml.c b/src/rccxml.c index a64e759..7227dbd 100644 --- a/src/rccxml.c +++ b/src/rccxml.c @@ -14,8 +14,6 @@ #include "internal.h" #include "rccconfig.h" -extern char *rcc_home_dir; - #define MAX_HOME_CHARS 96 #define XPATH_LANGUAGE "//Language[@name]" @@ -149,6 +147,8 @@ static xmlNodePtr rccNodeFind(xmlXPathContextPtr xpathctx, const char *request, unsigned int size = 64; va_list ap; char *req; + + if (!xpathctx) return NULL; for (req = strstr(request, "%s"); req; req = strstr(req + 1, "%s")) args++; @@ -358,7 +358,7 @@ clear: int rccLoad(rcc_context ctx, const char *name) { int err; - int fd; + int fd, sysfd; char *config; struct stat st; @@ -372,8 +372,8 @@ int rccLoad(rcc_context ctx, const char *name) { rcc_class_ptr *classes; rcc_class_ptr cl; - xmlXPathContextPtr xpathctx; - xmlDocPtr doc = NULL; + xmlXPathContextPtr xpathctx = NULL, sysxpathctx = NULL, curxpathctx; + xmlDocPtr doc = NULL, sysdoc = NULL; xmlNodePtr node, lnode; if (!ctx) { @@ -389,17 +389,52 @@ int rccLoad(rcc_context ctx, const char *name) { sprintf(config,"%s/.rcc/%s.xml",rcc_home_dir,name); fd = open(config, O_RDONLY); - if (fd == -1) goto clear; - flock(fd, LOCK_EX); + + sprintf(config, "/etc/rcc/%s.xml",name); + sysfd = open(config, O_RDONLY); - if ((!fstat(fd, &st))&&(st.st_size)) { - doc = xmlReadFd(fd, config, NULL, 0); - } else goto clear; + free(config); + + if (fd != -1) { + flock(fd, LOCK_EX); + if ((!fstat(fd, &st))&&(st.st_size)) { + doc = xmlReadFd(fd, name, NULL, 0); + } + flock(fd, LOCK_UN); + close(fd); - xpathctx = xmlXPathNewContext(doc); - if (!xpathctx) goto clear; + if (doc) { + xpathctx = xmlXPathNewContext(doc); + if (!xpathctx) { + xmlFreeDoc(doc); + doc = NULL; + } + } + } + + if (sysfd != -1) { + flock(sysfd, LOCK_EX); + if ((!fstat(sysfd, &st))&&(st.st_size)) { + sysdoc = xmlReadFd(sysfd, name, NULL, 0); + } + flock(sysfd, LOCK_UN); + close(sysfd); + + if (sysdoc) { + sysxpathctx = xmlXPathNewContext(sysdoc); + if (!sysxpathctx) { + xmlFreeDoc(sysdoc); + sysdoc = NULL; + } + } + } + + if ((!doc)&&(!sysdoc)) goto clear; + + node = rccNodeFind(xpathctx, XPATH_SELECTED_LANGUAGE); + if (!node) node = rccNodeFind(sysxpathctx, XPATH_SELECTED_LANGUAGE); if (node) { tmp = rccXmlGetText(node); if (tmp) err = rccSetLanguageByName(ctx, tmp); @@ -412,6 +447,7 @@ int rccLoad(rcc_context ctx, const char *name) { if (!oname) continue; node = rccNodeFind(xpathctx, XPATH_SELECTED_OPTION, oname); + if (!node) node = rccNodeFind(sysxpathctx, XPATH_SELECTED_OPTION, oname); if (node) { tmp = rccXmlGetText(node); if ((tmp)&&(strcasecmp(tmp,rcc_option_nonconfigured))) err = rccSetOption(ctx, (rcc_option)i, (rcc_option_value)atoi(tmp)); @@ -427,12 +463,17 @@ int rccLoad(rcc_context ctx, const char *name) { language = languages[i]; lnode = rccNodeFind(xpathctx, XPATH_SELECTED_LANG, language->sn); - if (!lnode) continue; + if (lnode) curxpathctx = xpathctx; + else { + lnode = rccNodeFind(sysxpathctx, XPATH_SELECTED_LANG, language->sn); + if (lnode) curxpathctx = sysxpathctx; + else continue; + } cfg = rccGetConfig(ctx, (rcc_language_id)i); if (!cfg) continue; - node = rccNodeFind(xpathctx, XPATH_SELECTED_ENGINE, language->sn); + node = rccNodeFind(curxpathctx, XPATH_SELECTED_ENGINE, language->sn); if (node) { tmp = rccXmlGetText(node); if (tmp) err = rccConfigSetEngineByName(cfg, tmp); @@ -443,7 +484,7 @@ int rccLoad(rcc_context ctx, const char *name) { for (j=0;classes[j];j++) { cl = classes[j]; - node = rccNodeFind(xpathctx, XPATH_SELECTED_CLASS, language->sn, cl->name); + node = rccNodeFind(curxpathctx, XPATH_SELECTED_CLASS, language->sn, cl->name); if (node) { tmp = rccXmlGetText(node); if (tmp) err = rccConfigSetCharsetByName(cfg, (rcc_class_id)j, tmp); @@ -454,18 +495,24 @@ int rccLoad(rcc_context ctx, const char *name) { } clear: - if (config) { - if (fd != -1) { - if (doc) { - if (xpathctx) { - xmlXPathFreeContext(xpathctx); - } - xmlFreeDoc(doc); - } - close(fd); + + if (sysdoc) { + if (sysxpathctx) { + xmlXPathFreeContext(sysxpathctx); } - free(config); + xmlFreeDoc(sysdoc); + } + if (doc) { + if (xpathctx) { + xmlXPathFreeContext(xpathctx); + } + xmlFreeDoc(doc); } + if ((!ctx->current_language)&&(rccGetOption(ctx, RCC_CONFIGURED_LANGUAGES_ONLY))) { + ctx->current_config = rccGetCurrentConfig(ctx); + ctx->configure = 1; + } + return 0; } diff --git a/src/recode.c b/src/recode.c index 4c1c5bd..f071f33 100644 --- a/src/recode.c +++ b/src/recode.c @@ -8,6 +8,7 @@ #include "lng.h" #include "rccstring.h" #include "rccconfig.h" +#include "rccdb4.h" @@ -20,8 +21,8 @@ static rcc_charset_id rccIConvAuto(rcc_context ctx, rcc_class_id class_id, const class_type = rccGetClassType(ctx, class_id); if ((class_type == RCC_CLASS_STANDARD)||((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_AUTODETECT_FS_TITLES)))) { - engine = rccGetEnginePointer(ctx, rccGetCurrentEngine(ctx)); - if ((!engine)||(!engine->func)||(!strcasecmp(engine->title, "off"))||(!strcasecmp(engine->title, "dissable"))) return -1; + engine = rccGetCurrentEnginePointer(ctx); + if ((!engine)||(!engine->func)) return (rcc_charset_id)-1; return engine->func(&ctx->engine_ctx, buf, len); } @@ -42,6 +43,13 @@ rcc_string rccFrom(rcc_context ctx, rcc_class_id class_id, const char *buf, size } if ((class_id<0)||(class_id>=ctx->n_classes)||(!buf)) return NULL; + + string = rccDb4GetKey(ctx->db4ctx, buf, len); + if (string) { + puts("Got a string"); + return string; + } + err = rccConfigure(ctx); if (err) return NULL; @@ -50,7 +58,7 @@ rcc_string rccFrom(rcc_context ctx, rcc_class_id class_id, const char *buf, size if (ret) return NULL; language_id = rccGetCurrentLanguage(ctx); - // DS: Learning. check database (language_id) + // DS: Learning. check database (language_id, check if language_id initialized) charset_id = rccIConvAuto(ctx, class_id, buf, len); if (charset_id != (rcc_charset_id)-1) icnv = ctx->iconv_auto[charset_id]; @@ -96,8 +104,10 @@ char *rccTo(rcc_context ctx, rcc_class_id class_id, const rcc_string buf, size_t language_id = rccStringGetLanguage(buf); utfstring = rccStringGetString(buf); + /* COnfigure is only required in case of current language */ err = rccConfigure(ctx); if (err) return NULL; + /* Do something even in case of error (Language can be changed) */ icnv = ctx->iconv_to[class_id]; |