diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rwxr-xr-x | autogen.sh | 76 | ||||
-rw-r--r-- | configure.in | 114 | ||||
-rw-r--r-- | m4/ax_compare_version.m4 | 153 | ||||
-rw-r--r-- | m4/ax_path_bdb.m4 | 575 | ||||
-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 | ||||
-rw-r--r-- | ui/gtk.c | 6 | ||||
-rw-r--r-- | ui/librccui.c | 9 | ||||
-rw-r--r-- | ui/rccnames.c | 2 |
30 files changed, 1465 insertions, 140 deletions
diff --git a/Makefile.am b/Makefile.am index 618d546..90d0a74 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ SUBDIRS = src ui +EXTRA_DIST = librcd.spec -EXTRA_DIST = librcd.spec
\ No newline at end of file +ACLOCAL_AMFLAGS = -I m4 @@ -1,9 +1,71 @@ -#!/bin/bash +#!/bin/sh +PROG=`basename $0` + +KEYFILE=src/librcc.c + +# Some OS's have multiple versions (autoconf259, etc.) and don't have an +# autoconf binary + +AUTOCONF=`which autoconf` +if test x"${AUTOCONF}" != x -a -f ${AUTOCONF} +then + AUTOCONF=autoconf + AUTOMAKE=automake + ACLOCAL=aclocal + LIBTOOLIZE=libtoolize + AUTOHEADER=autoheader +else + FINDPATH=`echo ${PATH}|sed -e 's,:, ,g'` + AUTOCONF=`find ${FINDPATH} -name "autoconf*"|sort -r|head -1` + AUTOMAKE=`find ${FINDPATH} -name "automake*"|sort -r|head -1` + ACLOCAL=`find ${FINDPATH} -name "aclocal*"|sort -r|head -1` + LIBTOOLIZE=`find ${FINDPATH} -name "libtoolize*"|sort -r|head -1` + AUTOHEADER=`find /usr/bin /usr/local/bin -name "autoheader*"|sort -r|head -1` + echo "$0: autoconf: using ${AUTOCONF}" + echo "$0: automake: using ${AUTOMAKE}" + echo "$0: aclocal: using ${ACLOCAL}" + echo "$0: libtoolize: using ${LIBTOOLIZE}" + echo "$0: autoheader: using ${AUTOHEADER}" +fi + +GETTEXTIZE_FLAGS=--no-changelog +AUTOPOINT_FLAGS= +LIBTOOLIZE_FLAGS= + +# Some OS's require /usr/local/share/aclocal + +if test ! -d /usr/local/share/aclocal +then + ACLOCAL_FLAGS='-I m4' +else + ACLOCAL_FLAGS='-I m4 -I /usr/local/share/aclocal' +fi +AUTOHEADER_FLAGS=-Wall +AUTOMAKE_FLAGS='--add-missing -Wall' +AUTOCONF_FLAGS=-Wno-obsolete + +die() +{ + err=$? + echo "$PROG: exited by previous error(s), return code was $err" >&2 + exit 1 +} + +if [ ! -f $KEYFILE ] +then + echo "$PROG: key-file \`$KEYFILE' not found, exiting." >&2 + echo "$PROG: hint: you should run $PROG from top-level sourse directory." >&2 + exit 1 +fi + +# gettextize ${GETTEXTIZE_FLAGS} +# autopoint ${AUTOPOINT_FLAGS} +# xml-i18n-toolize || die +# intltoolize || die +${LIBTOOLIZE} ${LIBTOOLIZE_FLAGS} --force || die +${ACLOCAL} ${ACLOCAL_FLAGS} || die +${AUTOHEADER} ${AUTOHEADER_FLAGS} || die +${AUTOMAKE} ${AUTOMAKE_FLAGS} || die +${AUTOCONF} ${AUTOCONF_FLAGS} || die -rm -f configure -aclocal -autoheader -libtoolize --force -automake -autoconf
\ No newline at end of file diff --git a/configure.in b/configure.in index e2fe1c4..7d50ab6 100644 --- a/configure.in +++ b/configure.in @@ -29,6 +29,10 @@ AC_SUBST(LIBRCC_CVS_DATE) AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AC_ARG_ENABLE( force-dynamic-engines, + [ --enable-force-dynamic-engines force usage of dynamic engines],, + enable_force_dynamic_engines="no") + AC_PROG_CC AC_PROG_INSTALL AM_PROG_LIBTOOL @@ -41,7 +45,7 @@ dnl Checks for programs. dnl Checks for header files. AC_CHECK_HEADERS(iconv.h,, [AC_MSG_ERROR(Missing iconv header)]) -AC_CHECK_HEADERS(mntent.h pwd.h sys/types.h unistd.h) +AC_CHECK_HEADERS(mntent.h pwd.h sys/types.h sys/stat.h unistd.h) AC_TRY_COMPILE([#include <langinfo.h>], [char *codeset = nl_langinfo (CODESET);], @@ -61,37 +65,97 @@ AC_SUBST(XML_INCLUDES) AC_PATH_PROG(GTK_CONFIG, gtk-config, no) AM_CONDITIONAL(HAVE_GTK, [ test $GTK_CONFIG != no ]) -GTK_LIBS="\`gtk-config --libs\`" -GTK_INCLUDES="\`gtk-config --cflags\`" +if test $GTK_CONFIG = no; then + GTK_LIBS="" + GTK_INCLUDES="" + HAVE_GTK=no +else + GTK_LIBS="\`gtk-config --libs\`" + GTK_INCLUDES="\`gtk-config --cflags\`" + HAVE_GTK=yes +fi AC_SUBST(GTK_LIBS) AC_SUBST(GTK_INCLUDES) +AC_CHECK_HEADER(dlfcn.h, [AC_CHECK_LIB(dl, dlopen, [ + AC_DEFINE(HAVE_DLOPEN,1,[Defines if dlopen is available]) + DLOPEN_LIBS="-ldl" + DLOPEN_INCLUDES="" + HAVE_DLOPEN=yes +],[ + DLOPEN_LIBS="" + DLOPEN_INCLUDES="" + HAVE_DLOPEN=no +])]) + +if test $enable_force_dynamic_engines = yes; then + RCD_LIBS="" + RCD_INCLUDES="" + HAVE_RCD=no + ENCA_LIBS="" + ENCA_INCLUDES="" + HAVE_ENCA=no +else AC_CHECK_HEADER(librcd.h, [AC_CHECK_LIB(rcd, rcdGetRussianCharset, [ + AC_DEFINE(HAVE_RCD,1,[Defines if libRCD is available]) RCD_LIBS="-lrcd" RCD_INCLUDES="" -], AC_MSG_ERROR(LibRCD is required))], [AC_MSG_ERROR(LibRCD is required)]) -AC_SUBST(RCD_LIBS) -AC_SUBST(RCD_INCLUDES) - -AC_CHECK_HEADER(enca.h, [AC_CHECK_LIB(enca, enca_analyse, [ - AC_DEFINE(HAVE_ENCA,1,[Defines if enca is available]) - ENCA_LIBS="-lenca" - ENCA_INCLUDES="" + HAVE_RCD=yes +],[ + RCD_LIBS="" + RCD_INCLUDES="" + HAVE_RCD=no ])]) - -if test "x$ENCA_LIBS" = "x"; then - AC_CHECK_HEADER(dlfcn.h, [AC_CHECK_LIB(dl, dlopen, [ - AC_DEFINE(HAVE_DLOPEN,1,[Defines if dlopen is available]) - ENCA_LIBS="-ldl" +AC_CHECK_HEADER(enca.h, [AC_CHECK_LIB(enca, enca_analyse, [ + AC_DEFINE(HAVE_ENCA,1,[Defines if enca is available]) + ENCA_LIBS="-lenca" ENCA_INCLUDES="" - ],[ + HAVE_ENCA=yes +],[ ENCA_LIBS="" ENCA_INCLUDES="" - ])]) + HAVE_ENCA=no +])]) fi + +AC_SUBST(RCD_LIBS) +AC_SUBST(RCD_INCLUDES) AC_SUBST(ENCA_LIBS) AC_SUBST(ENCA_INCLUDES) +USE_DLOPEN=no +if test $HAVE_DLOPEN = yes; then + if test $HAVE_ENCA = no; then + HAVE_ENCA=dynamic + USE_DLOPEN=yes + fi + if test $HAVE_RCD = no; then + HAVE_RCD=dynamic + USE_DLOPEN=yes + fi + + if test $USE_DLOPEN = no; then + DLOPEN_LIBS="" + DLOPEN_INCLUDES="" + fi +fi +AC_SUBST(DLOPEN_LIBS) +AC_SUBST(DLOPEN_INCLUDES) + + +AX_PATH_BDB([4],[ + BDB_LIBS="$BDB_LDFLAGS $BDB_LIBS" + BDB_INCLUDES="$BDB_CPPFLAGS" + HAVE_BDB=yes +],[ + BDB_LIBS="" + BDB_INCLUDES="" + HAVE_BDB=no +]) +AC_SUBST(BDB_LIBS) +AC_SUBST(BDB_INCLUDES) + + dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -99,3 +163,17 @@ dnl Checks for library functions. AC_CHECK_FUNCS(strcasecmp strncasecmp strdup) AC_OUTPUT(src/Makefile ui/Makefile examples/Makefile Makefile librcc.spec) + +echo "" +echo "Configuration:" +echo " Dynamic Engine Loading Support: $HAVE_DLOPEN" +echo " Enca Charset Detection Support: $HAVE_ENCA" +echo " LibRCD Charset Detection Support: $HAVE_RCD" +echo "" +echo " Multilanguage support with DB4: $HAVE_BDB" +echo "" +echo "User Interfaces:" +echo " GTK User Interface: $HAVE_GTK" +echo "" +echo "" +echo "" diff --git a/m4/ax_compare_version.m4 b/m4/ax_compare_version.m4 new file mode 100644 index 0000000..7a54a73 --- /dev/null +++ b/m4/ax_compare_version.m4 @@ -0,0 +1,153 @@ +dnl @synopsis AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +dnl +dnl This macro compares two version strings. It is used heavily in the +dnl macro _AX_PATH_BDB for library checking. Due to the various number +dnl of minor-version numbers that can exist, and the fact that string +dnl comparisons are not compatible with numeric comparisons, this is +dnl not necessarily trivial to do in a autoconf script. This macro makes +dnl doing these comparisons easy. +dnl +dnl The six basic comparisons are available, as well as checking +dnl equality limited to a certain number of minor-version levels. +dnl +dnl The operator OP determines what type of comparison to do, and +dnl can be one of: +dnl eq - equal (test A == B) +dnl ne - not equal (test A != B) +dnl le - less than or equal (test A <= B) +dnl ge - greater than or equal (test A >= B) +dnl lt - less than (test A < B) +dnl gt - greater than (test A > B) +dnl +dnl Additionally, the eq and ne operator can have a number after it +dnl to limit the test to that number of minor versions. +dnl eq0 - equal up to the length of the shorter version +dnl ne0 - not equal up to the length of the shorter version +dnl eqN - equal up to N sub-version levels +dnl neN - not equal up to N sub-version levels +dnl +dnl When the condition is true, shell commands ACTION-IF-TRUE are run, +dnl otherwise shell commands ACTION-IF-FALSE are run. The environment +dnl variable 'ax_compare_version' is always set to either 'true' or 'false' +dnl as well. +dnl +dnl Examples: +dnl AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) +dnl AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) +dnl would both be true. +dnl +dnl AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) +dnl AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) +dnl would both be false. +dnl +dnl AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) +dnl would be true because it is only comparing two minor versions. +dnl AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) +dnl would be true because it is only comparing the lesser number of +dnl minor versions of the two values. +dnl +dnl Note: The characters that separate the version numbers do not +dnl matter. An empty string is the same as version 0. OP is evaluated +dnl by autoconf, not configure, so must be a string, not a variable. +dnl +dnl The author would like to acknowledge Guido Draheim whose advice about +dnl the m4_case and m4_ifvaln functions make this macro only include +dnl the portions necessary to perform the specific comparison specified +dnl by the OP argument in the final configure script. +dnl +dnl @version $Id: ax_compare_version.m4,v 1.1 2004/03/01 19:14:43 guidod Exp $ +dnl @author Tim Toolan <toolan@ele.uri.edu> +dnl + +dnl ######################################################################### +AC_DEFUN([AX_COMPARE_VERSION], [ + # Used to indicate true or false condition + ax_compare_version=false + + # Convert the two version strings to be compared into a format that + # allows a simple string comparison. The end result is that a version + # string of the form 1.12.5-r617 will be converted to the form + # 0001001200050617. In other words, each number is zero padded to four + # digits, and non digits are removed. + AS_VAR_PUSHDEF([A],[ax_compare_version_A]) + A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ + -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/[[^0-9]]//g'` + + AS_VAR_PUSHDEF([B],[ax_compare_version_B]) + B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ + -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ + -e 's/[[^0-9]]//g'` + + dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary + dnl # then the first line is used to determine if the condition is true. + dnl # The sed right after the echo is to remove any indented white space. + m4_case(m4_tolower($2), + [lt],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` + ], + [gt],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` + ], + [le],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` + ], + [ge],[ + ax_compare_version=`echo "x$A +x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` + ],[ + dnl Split the operator from the subversion count if present. + m4_bmatch(m4_substr($2,2), + [0],[ + # A count of zero means use the length of the shorter version. + # Determine the number of characters in A and B. + ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'` + ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'` + + # Set A to no more than B's length and B to no more than A's length. + A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` + B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` + ], + [[0-9]+],[ + # A count greater than zero means use only that many subversions + A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` + B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` + ], + [.+],[ + AC_WARNING( + [illegal OP numeric parameter: $2]) + ],[]) + + # Pad zeros at end of numbers to make same length. + ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" + B="$B`echo $A | sed 's/./0/g'`" + A="$ax_compare_version_tmp_A" + + # Check for equality or inequality as necessary. + m4_case(m4_tolower(m4_substr($2,0,2)), + [eq],[ + test "x$A" = "x$B" && ax_compare_version=true + ], + [ne],[ + test "x$A" != "x$B" && ax_compare_version=true + ],[ + AC_WARNING([illegal OP parameter: $2]) + ]) + ]) + + AS_VAR_POPDEF([A])dnl + AS_VAR_POPDEF([B])dnl + + dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. + if test "$ax_compare_version" = "true" ; then + m4_ifvaln([$4],[$4],[:])dnl + m4_ifvaln([$5],[else $5])dnl + fi +]) dnl AX_COMPARE_VERSION diff --git a/m4/ax_path_bdb.m4 b/m4/ax_path_bdb.m4 new file mode 100644 index 0000000..cb4eb12 --- /dev/null +++ b/m4/ax_path_bdb.m4 @@ -0,0 +1,575 @@ +dnl @synopsis AX_PATH_BDB([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl +dnl This macro finds the latest version of Berkeley DB on the system, +dnl and ensures that the header file and library versions match. If +dnl MINIMUM-VERSION is specified, it will ensure that the library +dnl found is at least that version. +dnl +dnl It determines the name of the library as well as the path to the +dnl header file and library. It will check both the default environment +dnl as well as the default Berkeley DB install location. When found, it +dnl sets BDB_LIBS, BDB_CPPFLAGS, and BDB_LDFLAGS to the necessary values +dnl to add to LIBS, CPPFLAGS, and LDFLAGS, as well as setting BDB_VERSION +dnl to the version found. HAVE_DB_H is defined also. +dnl +dnl The option --with-bdb-dir=DIR can be used to specify a specific +dnl Berkeley DB installation to use. +dnl +dnl An example of it's use is: +dnl AX_PATH_BDB([3],[ +dnl LIBS="$BDB_LIBS $LIBS" +dnl LDFLAGS="$BDB_LDFLAGS $LDFLAGS" +dnl CPPFLAGS="$CPPFLAGS $BDB_CPPFLAGS" +dnl ]) +dnl which will locate the latest version of Berkeley DB on the system, +dnl and ensure that it is version 3.0 or higher. +dnl +dnl Details: This macro does not use either AC_CHECK_HEADERS or +dnl AC_CHECK_LIB because, first, the functions inside the library are +dnl sometimes renamed to contain a version code that is only available +dnl from the db.h on the system, and second, because it is common to +dnl have multiple db.h and libdb files on a system it is important to +dnl make sure the ones being used correspond to the same version. +dnl Additionally, there are many different possible names for libdb +dnl when installed by an OS distribution, and these need to be checked +dnl if db.h does not correspond to libdb. +dnl +dnl When cross compiling, only header versions are verified since it +dnl would be difficult to check the library version. Additionally +dnl the default Berkeley DB installation locations /usr/local/BerkeleyDB* +dnl are not searched for higher versions of the library. +dnl +dnl The format for the list of library names to search came from the +dnl Cyrus IMAP distribution, although they are generated dynamically +dnl here, and only for the version found in db.h. +dnl +dnl The macro AX_COMPARE_VERSION is required to use this macro, and +dnl should be available from the Autoconf Macro Archive. +dnl +dnl The author would like to acknowledge the generous and valuable feedback +dnl from Guido Draheim, without which this macro would be far less robust, +dnl and have poor and inconsistent cross compilation support. +dnl +dnl Changes: +dnl 1/5/05 applied patch from Rafa Rzepecki to eliminate compiler +dnl warning about unused variable, argv +dnl +dnl @version $Id: ax_path_bdb.m4,v 1.3 2005/01/20 00:15:41 guidod Exp $ +dnl @author Tim Toolan <toolan@ele.uri.edu> +dnl + +dnl ######################################################################### +AC_DEFUN([AX_PATH_BDB], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_ok=no + + # Add --with-bdb-dir option to configure. + AC_ARG_WITH([bdb-dir], + [AC_HELP_STRING([--with-bdb-dir=DIR], + [Berkeley DB installation directory])]) + + # Check if --with-bdb-dir was specified. + if test "x$with_bdb_dir" = "x" ; then + # No option specified, so just search the system. + AX_PATH_BDB_NO_OPTIONS([$1], [HIGHEST], [ + ax_path_bdb_ok=yes + ]) + else + # Set --with-bdb-dir option. + ax_path_bdb_INC="$with_bdb_dir/include" + ax_path_bdb_LIB="$with_bdb_dir/lib" + + dnl # Save previous environment, and modify with new stuff. + ax_path_bdb_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-I$ax_path_bdb_INC $CPPFLAGS" + + ax_path_bdb_save_LDFLAGS=$LDFLAGS + LDFLAGS="-L$ax_path_bdb_LIB $LDFLAGS" + + # Check for specific header file db.h + AC_MSG_CHECKING([db.h presence in $ax_path_bdb_INC]) + if test -f "$ax_path_bdb_INC/db.h" ; then + AC_MSG_RESULT([yes]) + # Check for library + AX_PATH_BDB_NO_OPTIONS([$1], [ENVONLY], [ + ax_path_bdb_ok=yes + BDB_CPPFLAGS="-I$ax_path_bdb_INC" + BDB_LDFLAGS="-L$ax_path_bdb_LIB" + ]) + else + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([no usable Berkeley DB not found]) + fi + + dnl # Restore the environment. + CPPFLAGS="$ax_path_bdb_save_CPPFLAGS" + LDFLAGS="$ax_path_bdb_save_LDFLAGS" + + fi + + dnl # Execute ACTION-IF-FOUND / ACTION-IF-NOT-FOUND. + if test "$ax_path_bdb_ok" = "yes" ; then + m4_ifvaln([$2],[$2],[:])dnl + m4_ifvaln([$3],[else $3])dnl + fi + +]) dnl AX_PATH_BDB + +dnl ######################################################################### +dnl Check for berkeley DB of at least MINIMUM-VERSION on system. +dnl +dnl The OPTION argument determines how the checks occur, and can be one of: +dnl +dnl HIGHEST - Check both the environment and the default installation +dnl directories for Berkeley DB and choose the version that +dnl is highest. (default) +dnl ENVFIRST - Check the environment first, and if no satisfactory +dnl library is found there check the default installation +dnl directories for Berkeley DB which is /usr/local/BerkeleyDB* +dnl ENVONLY - Check the current environment only. +dnl +dnl Requires AX_PATH_BDB_PATH_GET_VERSION, AX_PATH_BDB_PATH_FIND_HIGHEST, +dnl AX_PATH_BDB_ENV_CONFIRM_LIB, AX_PATH_BDB_ENV_GET_VERSION, and +dnl AX_COMPARE_VERSION macros. +dnl +dnl Result: sets ax_path_bdb_no_options_ok to yes or no +dnl sets BDB_LIBS, BDB_CPPFLAGS, BDB_LDFLAGS, BDB_VERSION +dnl +dnl AX_PATH_BDB_NO_OPTIONS([MINIMUM-VERSION], [OPTION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +AC_DEFUN([AX_PATH_BDB_NO_OPTIONS], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_no_options_ok=no + + # Values to add to environment to use Berkeley DB. + BDB_VERSION='' + BDB_LIBS='' + BDB_CPPFLAGS='' + BDB_LDFLAGS='' + + # Check cross compilation here. + if test "x$cross_compiling" = "xyes" ; then + # If cross compiling, can't use AC_RUN_IFELSE so do these tests. + # The AC_PREPROC_IFELSE confirms that db.h is preprocessable, + # and extracts the version number from it. + AC_MSG_CHECKING([for db.h]) + + AS_VAR_PUSHDEF([HEADER_VERSION],[ax_path_bdb_no_options_HEADER_VERSION])dnl + HEADER_VERSION='' + AC_PREPROC_IFELSE([ + AC_LANG_SOURCE([[ +#include <db.h> +AX_PATH_BDB_STUFF DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH + ]]) + ],[ + # Extract version from preprocessor output. + HEADER_VERSION=`eval "$ac_cpp conftest.$ac_ext" 2> /dev/null \ + | grep AX_PATH_BDB_STUFF | sed 's/[[^0-9,]]//g;s/,/./g;1q'` + ],[]) + + if test "x$HEADER_VERSION" = "x" ; then + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([$HEADER_VERSION]) + + # Check that version is high enough. + AX_COMPARE_VERSION([$HEADER_VERSION],[ge],[$1],[ + # get major and minor version numbers + AS_VAR_PUSHDEF([MAJ],[ax_path_bdb_no_options_MAJOR])dnl + MAJ=`echo $HEADER_VERSION | sed 's,\..*,,'` + AS_VAR_PUSHDEF([MIN],[ax_path_bdb_no_options_MINOR])dnl + MIN=`echo $HEADER_VERSION | sed 's,^[[0-9]]*\.,,;s,\.[[0-9]]*$,,'` + + dnl # Save LIBS. + ax_path_bdb_no_options_save_LIBS="$LIBS" + + # Check that we can link with the library. + AC_SEARCH_LIBS([db_version], + [db db-$MAJ.$MIN db$MAJ.$MIN db$MAJ$MIN db-$MAJ db$MAJ],[ + # Sucessfully found library. + ax_path_bdb_no_options_ok=yes + BDB_VERSION=$HEADER_VERSION + + # Extract library from LIBS + ax_path_bdb_no_options_LEN=` \ + echo "x$ax_path_bdb_no_options_save_LIBS" \ + | awk '{print(length)}'` + BDB_LIBS=`echo "x$LIBS " \ + | sed "s/.\{$ax_path_bdb_no_options_LEN\}\$//;s/^x//;s/ //g"` + ],[]) + + dnl # Restore LIBS + LIBS="$ax_path_bdb_no_options_save_LIBS" + + AS_VAR_POPDEF([MAJ])dnl + AS_VAR_POPDEF([MIN])dnl + ]) + fi + + AS_VAR_POPDEF([HEADER_VERSION])dnl + else + # Not cross compiling. + # Check version of Berkeley DB in the current environment. + AX_PATH_BDB_ENV_GET_VERSION([ + AX_COMPARE_VERSION([$ax_path_bdb_env_get_version_VERSION],[ge],[$1],[ + # Found acceptable version in current environment. + ax_path_bdb_no_options_ok=yes + BDB_VERSION="$ax_path_bdb_env_get_version_VERSION" + BDB_LIBS="$ax_path_bdb_env_get_version_LIBS" + ]) + ]) + + # Determine if we need to search /usr/local/BerkeleyDB* + ax_path_bdb_no_options_DONE=no + if test "x$2" = "xENVONLY" ; then + ax_path_bdb_no_options_DONE=yes + elif test "x$2" = "xENVFIRST" ; then + ax_path_bdb_no_options_DONE=$ax_path_bdb_no_options_ok + fi + + if test "$ax_path_bdb_no_options_DONE" = "no" ; then + # Check for highest in /usr/local/BerkeleyDB* + AX_PATH_BDB_PATH_FIND_HIGHEST([ + if test "$ax_path_bdb_no_options_ok" = "yes" ; then + # If we already have an acceptable version use this if higher. + AX_COMPARE_VERSION( + [$ax_path_bdb_path_find_highest_VERSION],[gt],[$BDB_VERSION]) + else + # Since we didn't have an acceptable version check if this one is. + AX_COMPARE_VERSION( + [$ax_path_bdb_path_find_highest_VERSION],[ge],[$1]) + fi + ]) + + dnl # If result from _AX_COMPARE_VERSION is true we want this version. + if test "$ax_compare_version" = "true" ; then + ax_path_bdb_no_options_ok=yes + BDB_LIBS="-ldb" + if test "x$ax_path_bdb_path_find_highest_DIR" != x ; then + BDB_CPPFLAGS="-I$ax_path_bdb_path_find_highest_DIR/include" + BDB_LDFLAGS="-L$ax_path_bdb_path_find_highest_DIR/lib" + fi + BDB_VERSION="$ax_path_bdb_path_find_highest_VERSION" + fi + fi + fi + + dnl # Execute ACTION-IF-FOUND / ACTION-IF-NOT-FOUND. + if test "$ax_path_bdb_no_options_ok" = "yes" ; then + AC_MSG_NOTICE([using Berkeley DB version $BDB_VERSION]) + AC_DEFINE([HAVE_DB_H],[1], + [Define to 1 if you have the <db.h> header file.]) + m4_ifvaln([$3],[$3])dnl + else + AC_MSG_NOTICE([no Berkeley DB version $1 or higher found]) + m4_ifvaln([$4],[$4])dnl + fi +]) dnl AX_PATH_BDB_NO_OPTIONS + +dnl ######################################################################### +dnl Check the default installation directory for Berkeley DB which is +dnl of the form /usr/local/BerkeleyDB* for the highest version. +dnl +dnl Result: sets ax_path_bdb_path_find_highest_ok to yes or no, +dnl sets ax_path_bdb_path_find_highest_VERSION to version, +dnl sets ax_path_bdb_path_find_highest_DIR to directory. +dnl +dnl AX_PATH_BDB_PATH_FIND_HIGHEST([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +AC_DEFUN([AX_PATH_BDB_PATH_FIND_HIGHEST], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_path_find_highest_ok=no + + AS_VAR_PUSHDEF([VERSION],[ax_path_bdb_path_find_highest_VERSION])dnl + VERSION='' + + ax_path_bdb_path_find_highest_DIR='' + + # find highest verison in default install directory for Berkeley DB + AS_VAR_PUSHDEF([CURDIR],[ax_path_bdb_path_find_highest_CURDIR])dnl + AS_VAR_PUSHDEF([CUR_VERSION],[ax_path_bdb_path_get_version_VERSION])dnl + + for CURDIR in `ls -d /usr/local/BerkeleyDB* 2> /dev/null` + do + AX_PATH_BDB_PATH_GET_VERSION([$CURDIR],[ + AX_COMPARE_VERSION([$CUR_VERSION],[gt],[$VERSION],[ + ax_path_bdb_path_find_highest_ok=yes + ax_path_bdb_path_find_highest_DIR="$CURDIR" + VERSION="$CUR_VERSION" + ]) + ]) + done + + AS_VAR_POPDEF([VERSION])dnl + AS_VAR_POPDEF([CUR_VERSION])dnl + AS_VAR_POPDEF([CURDIR])dnl + + dnl # Execute ACTION-IF-FOUND / ACTION-IF-NOT-FOUND. + if test "$ax_path_bdb_path_find_highest_ok" = "yes" ; then + m4_ifvaln([$1],[$1],[:])dnl + m4_ifvaln([$2],[else $2])dnl + fi + +]) dnl AX_PATH_BDB_PATH_FIND_HIGHEST + +dnl ######################################################################### +dnl Checks for Berkeley DB in specified directory's lib and include +dnl subdirectories. +dnl +dnl Result: sets ax_path_bdb_path_get_version_ok to yes or no, +dnl sets ax_path_bdb_path_get_version_VERSION to version. +dnl +dnl AX_PATH_BDB_PATH_GET_VERSION(BDB-DIR, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +AC_DEFUN([AX_PATH_BDB_PATH_GET_VERSION], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_path_get_version_ok=no + + # Indicate status of checking for Berkeley DB header. + AC_MSG_CHECKING([in $1/include for db.h]) + ax_path_bdb_path_get_version_got_header=no + test -f "$1/include/db.h" && ax_path_bdb_path_get_version_got_header=yes + AC_MSG_RESULT([$ax_path_bdb_path_get_version_got_header]) + + # Indicate status of checking for Berkeley DB library. + AC_MSG_CHECKING([in $1/lib for library -ldb]) + + ax_path_bdb_path_get_version_VERSION='' + + if test -d "$1/include" && test -d "$1/lib" && + test "$ax_path_bdb_path_get_version_got_header" = "yes" ; then + dnl # save and modify environment + ax_path_bdb_path_get_version_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-I$1/include $CPPFLAGS" + + ax_path_bdb_path_get_version_save_LIBS="$LIBS" + LIBS="$LIBS -ldb" + + ax_path_bdb_path_get_version_save_LDFLAGS="$LDFLAGS" + LDFLAGS="-L$1/lib $LDFLAGS" + + # Compile and run a program that compares the version defined in + # the header file with a version defined in the library function + # db_version. + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ +#include <stdio.h> +#include <db.h> +int main(int argc,char **argv) +{ + int major,minor,patch; + (void) argv; + db_version(&major,&minor,&patch); + if (argc > 1) + printf("%d.%d.%d\n",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); + if (DB_VERSION_MAJOR == major && DB_VERSION_MINOR == minor && + DB_VERSION_PATCH == patch) + return 0; + else + return 1; +} + ]]) + ],[ + # Program compiled and ran, so get version by adding argument. + ax_path_bdb_path_get_version_VERSION=`./conftest$ac_exeext x` + ax_path_bdb_path_get_version_ok=yes + ],[],[]) + + dnl # restore environment + CPPFLAGS="$ax_path_bdb_path_get_version_save_CPPFLAGS" + LIBS="$ax_path_bdb_path_get_version_save_LIBS" + LDFLAGS="$ax_path_bdb_path_get_version_save_LDFLAGS" + fi + + dnl # Finally, execute ACTION-IF-FOUND / ACTION-IF-NOT-FOUND. + if test "$ax_path_bdb_path_get_version_ok" = "yes" ; then + AC_MSG_RESULT([$ax_path_bdb_path_get_version_VERSION]) + m4_ifvaln([$2],[$2])dnl + else + AC_MSG_RESULT([no]) + m4_ifvaln([$3],[$3])dnl + fi +]) dnl AX_PATH_BDB_PATH_GET_VERSION + +############################################################################# +dnl Checks if version of library and header match specified version. +dnl Only meant to be used by AX_PATH_BDB_ENV_GET_VERSION macro. +dnl +dnl Requires AX_COMPARE_VERSION macro. +dnl +dnl Result: sets ax_path_bdb_env_confirm_lib_ok to yes or no. +dnl +dnl AX_PATH_BDB_ENV_CONFIRM_LIB(VERSION, [LIBNAME]) +AC_DEFUN([AX_PATH_BDB_ENV_CONFIRM_LIB], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_env_confirm_lib_ok=no + + dnl # save and modify environment to link with library LIBNAME + ax_path_bdb_env_confirm_lib_save_LIBS="$LIBS" + LIBS="$LIBS $2" + + # Compile and run a program that compares the version defined in + # the header file with a version defined in the library function + # db_version. + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ +#include <stdio.h> +#include <db.h> +int main(int argc,char **argv) +{ + int major,minor,patch; + (void) argv; + db_version(&major,&minor,&patch); + if (argc > 1) + printf("%d.%d.%d\n",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); + if (DB_VERSION_MAJOR == major && DB_VERSION_MINOR == minor && + DB_VERSION_PATCH == patch) + return 0; + else + return 1; +} + ]]) + ],[ + # Program compiled and ran, so get version by giving an argument, + # which will tell the program to print the output. + ax_path_bdb_env_confirm_lib_VERSION=`./conftest$ac_exeext x` + + # If the versions all match up, indicate success. + AX_COMPARE_VERSION([$ax_path_bdb_env_confirm_lib_VERSION],[eq],[$1],[ + ax_path_bdb_env_confirm_lib_ok=yes + ]) + ],[],[]) + + dnl # restore environment + LIBS="$ax_path_bdb_env_confirm_lib_save_LIBS" + +]) dnl AX_PATH_BDB_ENV_CONFIRM_LIB + +############################################################################# +dnl Finds the version and library name for Berkeley DB in the +dnl current environment. Tries many different names for library. +dnl +dnl Requires AX_PATH_BDB_ENV_CONFIRM_LIB macro. +dnl +dnl Result: set ax_path_bdb_env_get_version_ok to yes or no, +dnl set ax_path_bdb_env_get_version_VERSION to the version found, +dnl and ax_path_bdb_env_get_version_LIBNAME to the library name. +dnl +dnl AX_PATH_BDB_ENV_GET_VERSION([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +AC_DEFUN([AX_PATH_BDB_ENV_GET_VERSION], [ + dnl # Used to indicate success or failure of this function. + ax_path_bdb_env_get_version_ok=no + + ax_path_bdb_env_get_version_VERSION='' + ax_path_bdb_env_get_version_LIBS='' + + AS_VAR_PUSHDEF([HEADER_VERSION],[ax_path_bdb_env_get_version_HEADER_VERSION])dnl + AS_VAR_PUSHDEF([TEST_LIBNAME],[ax_path_bdb_env_get_version_TEST_LIBNAME])dnl + + # Indicate status of checking for Berkeley DB library. + AC_MSG_CHECKING([for db.h]) + + # Compile and run a program that determines the Berkeley DB version + # in the header file db.h. + HEADER_VERSION='' + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ +#include <stdio.h> +#include <db.h> +int main(int argc,char **argv) +{ + (void) argv; + if (argc > 1) + printf("%d.%d.%d\n",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); + return 0; +} + ]]) + ],[ + # Program compiled and ran, so get version by adding an argument. + HEADER_VERSION=`./conftest$ac_exeext x` + AC_MSG_RESULT([$HEADER_VERSION]) + ],[AC_MSG_RESULT([no])],[AC_MSG_RESULT([no])]) + + # Have header version, so try to find corresponding library. + # Looks for library names in the order: + # nothing, db, db-X.Y, dbX.Y, dbXY, db-X, dbX + # and stops when it finds the first one that matches the version + # of the header file. + if test "x$HEADER_VERSION" != "x" ; then + AC_MSG_CHECKING([for library containing Berkeley DB $HEADER_VERSION]) + + AS_VAR_PUSHDEF([MAJOR],[ax_path_bdb_env_get_version_MAJOR])dnl + AS_VAR_PUSHDEF([MINOR],[ax_path_bdb_env_get_version_MINOR])dnl + + # get major and minor version numbers + MAJOR=`echo $HEADER_VERSION | sed 's,\..*,,'` + MINOR=`echo $HEADER_VERSION | sed 's,^[[0-9]]*\.,,;s,\.[[0-9]]*$,,'` + + # see if it is already specified in LIBS + TEST_LIBNAME='' + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "db" + TEST_LIBNAME='-ldb' + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "db-X.Y" + TEST_LIBNAME="-ldb-${MAJOR}.$MINOR" + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "dbX.Y" + TEST_LIBNAME="-ldb${MAJOR}.$MINOR" + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "dbXY" + TEST_LIBNAME="-ldb$MAJOR$MINOR" + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "db-X" + TEST_LIBNAME="-ldb-$MAJOR" + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + if test "$ax_path_bdb_env_confirm_lib_ok" = "no" ; then + # try format "dbX" + TEST_LIBNAME="-ldb$MAJOR" + AX_PATH_BDB_ENV_CONFIRM_LIB([$HEADER_VERSION], [$TEST_LIBNAME]) + fi + + dnl # Found a valid library. + if test "$ax_path_bdb_env_confirm_lib_ok" = "yes" ; then + if test "x$TEST_LIBNAME" = "x" ; then + AC_MSG_RESULT([none required]) + else + AC_MSG_RESULT([$TEST_LIBNAME]) + fi + ax_path_bdb_env_get_version_VERSION="$HEADER_VERSION" + ax_path_bdb_env_get_version_LIBS="$TEST_LIBNAME" + ax_path_bdb_env_get_version_ok=yes + else + AC_MSG_RESULT([no]) + fi + + AS_VAR_POPDEF([MAJOR])dnl + AS_VAR_POPDEF([MINOR])dnl + fi + + AS_VAR_POPDEF([HEADER_VERSION])dnl + AS_VAR_POPDEF([TEST_LIBNAME])dnl + + dnl # Execute ACTION-IF-FOUND / ACTION-IF-NOT-FOUND. + if test "$ax_path_bdb_env_confirm_lib_ok" = "yes" ; then + m4_ifvaln([$1],[$1],[:])dnl + m4_ifvaln([$2],[else $2])dnl + fi + +]) dnl BDB_ENV_GET_VERSION + +############################################################################# + 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]; @@ -126,7 +126,7 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) { config = rccGetConfig(rccctx, language_id); charset_id = rccConfigGetSelectedCharset(config, (rcc_class_id)ctx->id); - if (charset_id < 0) charset_id = 0; + if (charset_id == (rcc_charset_id)-1) charset_id = 0; gtk_option_menu_set_history(GTK_OPTION_MENU(menu), charset_id); break; case RCC_UI_MENU_ENGINE: @@ -148,12 +148,10 @@ int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) { gtk_option_menu_remove_menu(GTK_OPTION_MENU(menu)); gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), list); - config = rccGetConfig(rccctx, language_id); engine_id = rccConfigGetCurrentEngine(config); - if (engine_id < 0) engine_id = 0; + if (engine_id == (rcc_engine_id)-1) engine_id = 0; gtk_option_menu_set_history(GTK_OPTION_MENU(menu), engine_id); - break; case RCC_UI_MENU_OPTION: if (!ctx->widget) { diff --git a/ui/librccui.c b/ui/librccui.c index c868708..3b8bcdc 100644 --- a/ui/librccui.c +++ b/ui/librccui.c @@ -165,12 +165,9 @@ int rccUiRestoreLanguage(rcc_ui_context ctx) { rcc_class_ptr *classes; rcc_language_id language_id; - rcc_language_config config; - if (!ctx) return -1; language_id = (rcc_language_id)rccUiMenuGet(ctx->language); - config = rccGetConfig(ctx->rccctx, language_id); rccUiMenuConfigureWidget(ctx->engine); //rccUiMenuSet(ctx->engine, (rcc_ui_id)rccConfigGetSelectedEngine(config)); @@ -386,6 +383,7 @@ rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title) { rcc_ui_frame frame; rcc_ui_box engine; rcc_ui_box opt; + const char *optname; if (!ctx) return NULL; @@ -400,7 +398,10 @@ rcc_ui_frame rccUiGetEngineFrame(rcc_ui_context ctx, const char *title) { rccUiFrameAdd(framectx, engine); for (i=0; i<RCC_MAX_OPTIONS; i++) { - opt = rccUiGetOptionBox(ctx, (rcc_option)i, rccUiGetOptionName(ctx, i)); + optname = rccUiGetOptionName(ctx, i); + if (!optname) continue; + + opt = rccUiGetOptionBox(ctx, (rcc_option)i, optname); rccUiFrameAdd(framectx, opt); } diff --git a/ui/rccnames.c b/ui/rccnames.c index 2e11165..f5bf4d8 100644 --- a/ui/rccnames.c +++ b/ui/rccnames.c @@ -40,5 +40,5 @@ const char *rccUiGetOptionName(rcc_ui_context ctx, rcc_option option) { res = rccGetOptionFullName(option); if (res) return res; - return ""; + return NULL; } |