rktio: add iconv
This commit is contained in:
parent
db7c242983
commit
6a543f4783
67
racket/src/configure
vendored
67
racket/src/configure
vendored
|
@ -5103,32 +5103,8 @@ fi
|
|||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $using_gnu_cpp" >&5
|
||||
$as_echo "$using_gnu_cpp" >&6; }
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo (CODESET)" >&5
|
||||
$as_echo_n "checking for nl_langinfo (CODESET)... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <langinfo.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
char *codeset = nl_langinfo (CODESET);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
|
||||
$as_echo "#define HAVE_CODESET 1" >>confdefs.h
|
||||
|
||||
have_codeset=yes
|
||||
else
|
||||
have_codeset=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_codeset" >&5
|
||||
$as_echo "$have_codeset" >&6; }
|
||||
|
||||
# Although rktio takes care of iconv, we need to know whether
|
||||
# to link to it
|
||||
iconv_lib_flag=""
|
||||
if test "${skip_iconv_check}" = "no" ; then
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
|
@ -5463,40 +5439,8 @@ $as_echo_n "checking $msg... " >&6; }
|
|||
iconv_usage_result="$enable_iconv$iconv_lib_flag"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $iconv_usage_result" >&5
|
||||
$as_echo "$iconv_usage_result" >&6; }
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
MZOPTIONS="$MZOPTIONS -DMZ_NO_ICONV"
|
||||
fi
|
||||
fi
|
||||
|
||||
msg="for mbsrtowcs"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $msg" >&5
|
||||
$as_echo_n "checking $msg... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <wchar.h>
|
||||
#include <strings.h>
|
||||
int main() {
|
||||
mbstate_t state;
|
||||
char *src = "X";
|
||||
bzero(&state, sizeof(mbstate_t));
|
||||
mbsrtowcs(0, &src, 0, &state);
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
mbsrtowcs=yes
|
||||
else
|
||||
mbsrtowcs=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test "$mbsrtowcs" = "no" ; then
|
||||
MZOPTIONS="$MZOPTIONS -DNO_MBTOWC_FUNCTIONS"
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mbsrtowcs" >&5
|
||||
$as_echo "$mbsrtowcs" >&6; }
|
||||
|
||||
if test "${check_for_mprotect}" = "yes" ; then
|
||||
msg="for mmap and mprotect"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $msg" >&5
|
||||
|
@ -6892,6 +6836,13 @@ else
|
|||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --disable-pthread"
|
||||
fi
|
||||
|
||||
# Make sure the --enable-iconv result is propagated:
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --enable-iconv"
|
||||
else
|
||||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --disable-iconv"
|
||||
fi
|
||||
|
||||
FOREIGNTARGET=
|
||||
FOREIGN_IF_USED="FOREIGN_NOT_USED"
|
||||
if test -d "${srcdir}/foreign" && test "${enable_foreign}" = "yes" ; then
|
||||
|
|
|
@ -1068,14 +1068,8 @@ if test "$using_gnu_cpp" = "yes" ; then
|
|||
fi
|
||||
AC_MSG_RESULT($using_gnu_cpp)
|
||||
|
||||
AC_MSG_CHECKING([for nl_langinfo (CODESET)])
|
||||
AC_TRY_LINK([#include <langinfo.h>],
|
||||
[char *codeset = nl_langinfo (CODESET);],
|
||||
AC_DEFINE(HAVE_CODESET,1,[Have nl_langinfo (CODESET)])
|
||||
have_codeset=yes,
|
||||
have_codeset=no)
|
||||
AC_MSG_RESULT($have_codeset)
|
||||
|
||||
# Although rktio takes care of iconv, we need to know whether
|
||||
# to link to it
|
||||
iconv_lib_flag=""
|
||||
if test "${skip_iconv_check}" = "no" ; then
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
|
@ -1113,28 +1107,8 @@ if test "${skip_iconv_check}" = "no" ; then
|
|||
AC_MSG_CHECKING($msg)
|
||||
iconv_usage_result="$enable_iconv$iconv_lib_flag"
|
||||
AC_MSG_RESULT($iconv_usage_result)
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
MZOPTIONS="$MZOPTIONS -DMZ_NO_ICONV"
|
||||
fi
|
||||
fi
|
||||
|
||||
[ msg="for mbsrtowcs" ]
|
||||
AC_MSG_CHECKING($msg)
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#include <wchar.h>
|
||||
#include <strings.h>
|
||||
int main() {
|
||||
mbstate_t state;
|
||||
char *src = "X";
|
||||
bzero(&state, sizeof(mbstate_t));
|
||||
mbsrtowcs(0, &src, 0, &state);
|
||||
return 0;
|
||||
}])], mbsrtowcs=yes, mbsrtowcs=no)
|
||||
if test "$mbsrtowcs" = "no" ; then
|
||||
MZOPTIONS="$MZOPTIONS -DNO_MBTOWC_FUNCTIONS"
|
||||
fi
|
||||
AC_MSG_RESULT($mbsrtowcs)
|
||||
|
||||
if test "${check_for_mprotect}" = "yes" ; then
|
||||
[ msg="for mmap and mprotect" ]
|
||||
AC_MSG_CHECKING($msg)
|
||||
|
@ -1825,6 +1799,13 @@ else
|
|||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --disable-pthread"
|
||||
fi
|
||||
|
||||
# Make sure the --enable-iconv result is propagated:
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --enable-iconv"
|
||||
else
|
||||
SUB_CONFIGURE_EXTRAS="$SUB_CONFIGURE_EXTRAS --disable-iconv"
|
||||
fi
|
||||
|
||||
FOREIGNTARGET=
|
||||
FOREIGN_IF_USED="FOREIGN_NOT_USED"
|
||||
if test -d "${srcdir}/foreign" && test "${enable_foreign}" = "yes" ; then
|
||||
|
|
|
@ -44,9 +44,6 @@ typedef unsigned long uintptr_t;
|
|||
/* Direction of stack growth: 1 = up, -1 = down, 0 = unknown. */
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Whether nl_langinfo works. */
|
||||
#undef HAVE_CODESET
|
||||
|
||||
/* Whether __attribute__ ((noinline)) works. */
|
||||
#undef MZ_USE_NOINLINE
|
||||
|
||||
|
|
|
@ -5392,29 +5392,23 @@ void scheme_set_addon_dir(Scheme_Object *p)
|
|||
|
||||
#ifdef DOS_FILE_SYSTEM
|
||||
|
||||
static wchar_t *dlldir;
|
||||
|
||||
wchar_t *scheme_get_dll_path(wchar_t *s)
|
||||
{
|
||||
if (dlldir) {
|
||||
int len1, len2;
|
||||
wchar_t *p;
|
||||
len1 = wc_strlen(dlldir);
|
||||
len2 = wc_strlen(s);
|
||||
p = (wchar_t *)scheme_malloc_atomic((len1 + len2 + 2) * sizeof(wchar_t));
|
||||
memcpy(p, dlldir, len1 * sizeof(wchar_t));
|
||||
if (p[len1 - 1] != '\\') {
|
||||
p[len1++] = '\\';
|
||||
}
|
||||
memcpy(p + len1, s, (len2 + 1) * sizeof(wchar_t));
|
||||
return p;
|
||||
} else
|
||||
return s;
|
||||
}
|
||||
|
||||
void scheme_set_dll_path(wchar_t *p)
|
||||
{
|
||||
dlldir = p;
|
||||
rktio_set_dll_path(p);
|
||||
}
|
||||
|
||||
wchar_t *scheme_get_dll_path(wchar_t *p)
|
||||
{
|
||||
wchar_t *r, *r2;
|
||||
intptr_t len;
|
||||
r = rktio_get_dll_path(p);
|
||||
if (!r)
|
||||
return p;
|
||||
len = wcslen(r) + 1;
|
||||
r2 = scheme_malloc_atomic(sizeof(wchar_t) * len);
|
||||
memcpy(r2, r, sizeof(wchar_t) * len);
|
||||
free(r);
|
||||
return r2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,7 @@ OBJS = rktio_fs.@LTO@ \
|
|||
rktio_shellex.@LTO@ \
|
||||
rktio_time.@LTO@ \
|
||||
rktio_syslog.@LTO@ \
|
||||
rktio_convert.@LTO@ \
|
||||
rktio_error.@LTO@ \
|
||||
rktio_hash.@LTO@ \
|
||||
rktio_wide.@LTO@ \
|
||||
|
@ -85,6 +86,9 @@ rktio_time.@LTO@: $(srcdir)/rktio_time.c $(RKTIO_HEADERS)
|
|||
rktio_syslog.@LTO@: $(srcdir)/rktio_syslog.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_syslog.@LTO@ -c $(srcdir)/rktio_syslog.c
|
||||
|
||||
rktio_convert.@LTO@: $(srcdir)/rktio_convert.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_convert.@LTO@ -c $(srcdir)/rktio_convert.c
|
||||
|
||||
rktio_error.@LTO@: $(srcdir)/rktio_error.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.@LTO@ -c $(srcdir)/rktio_error.c
|
||||
|
||||
|
|
54
racket/src/rktio/configure
vendored
54
racket/src/rktio/configure
vendored
|
@ -694,6 +694,8 @@ ac_subst_files=''
|
|||
ac_user_opts='
|
||||
enable_option_checking
|
||||
enable_shared
|
||||
enable_pthread
|
||||
enable_iconv
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
host_alias
|
||||
|
@ -1317,6 +1319,8 @@ Optional Features:
|
|||
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
|
||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--enable-shared create shared libraries (ok, but not recommended)
|
||||
--enable-pthread link with pthreads (usually auto-enabled if needed)
|
||||
--enable-iconv use iconv (usually auto-enabled)
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
|
@ -2243,6 +2247,20 @@ if test "${enable_shared+set}" = set; then :
|
|||
enableval=$enable_shared;
|
||||
fi
|
||||
|
||||
# Check whether --enable-pthread was given.
|
||||
if test "${enable_pthread+set}" = set; then :
|
||||
enableval=$enable_pthread;
|
||||
fi
|
||||
|
||||
# Check whether --enable-iconv was given.
|
||||
if test "${enable_iconv+set}" = set; then :
|
||||
enableval=$enable_iconv;
|
||||
fi
|
||||
|
||||
|
||||
if test "${enable_iconv}" = "" ; then
|
||||
enable_iconv=yes
|
||||
fi
|
||||
|
||||
###### Autoconfigure #######
|
||||
|
||||
|
@ -3921,9 +3939,39 @@ $as_echo_n "checking $msg... " >&6; }
|
|||
iconv_usage_result="$enable_iconv$iconv_lib_flag"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $iconv_usage_result" >&5
|
||||
$as_echo "$iconv_usage_result" >&6; }
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
CFLAGS="$CFLAGS -DRKTIO_NO_ICONV"
|
||||
fi
|
||||
fi
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
|
||||
$as_echo "#define RKTIO_NO_ICON 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo (CODESET)" >&5
|
||||
$as_echo_n "checking for nl_langinfo (CODESET)... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <langinfo.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
char *codeset = nl_langinfo (CODESET);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
|
||||
$as_echo "#define RKTIO_HAVE_CODESET 1" >>confdefs.h
|
||||
|
||||
have_codeset=yes
|
||||
else
|
||||
have_codeset=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_codeset" >&5
|
||||
$as_echo "$have_codeset" >&6; }
|
||||
fi
|
||||
|
||||
msg="for mbsrtowcs"
|
||||
|
|
|
@ -11,6 +11,12 @@ AC_CONFIG_AUX_DIR(../lt)
|
|||
AC_CANONICAL_SYSTEM
|
||||
|
||||
AC_ARG_ENABLE(shared, [ --enable-shared create shared libraries (ok, but not recommended)])
|
||||
AC_ARG_ENABLE(pthread, [ --enable-pthread link with pthreads (usually auto-enabled if needed)])
|
||||
AC_ARG_ENABLE(iconv, [ --enable-iconv use iconv (usually auto-enabled)])
|
||||
|
||||
if test "${enable_iconv}" = "" ; then
|
||||
enable_iconv=yes
|
||||
fi
|
||||
|
||||
###### Autoconfigure #######
|
||||
|
||||
|
@ -156,9 +162,19 @@ if test "${skip_iconv_check}" = "no" ; then
|
|||
AC_MSG_CHECKING($msg)
|
||||
iconv_usage_result="$enable_iconv$iconv_lib_flag"
|
||||
AC_MSG_RESULT($iconv_usage_result)
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
CFLAGS="$CFLAGS -DRKTIO_NO_ICONV"
|
||||
fi
|
||||
fi
|
||||
if test "${enable_iconv}" = "no" ; then
|
||||
AC_DEFINE(RKTIO_NO_ICON,1,[Do not use iconv])
|
||||
fi
|
||||
|
||||
if test "${enable_iconv}" = "yes" ; then
|
||||
AC_MSG_CHECKING([for nl_langinfo (CODESET)])
|
||||
AC_TRY_LINK([#include <langinfo.h>],
|
||||
[char *codeset = nl_langinfo (CODESET);],
|
||||
AC_DEFINE(RKTIO_HAVE_CODESET,1,[Have nl_langinfo (CODESET)])
|
||||
have_codeset=yes,
|
||||
have_codeset=no)
|
||||
AC_MSG_RESULT($have_codeset)
|
||||
fi
|
||||
|
||||
[ msg="for mbsrtowcs" ]
|
||||
|
|
|
@ -72,6 +72,9 @@ Thread and signal conventions:
|
|||
# define RKTIO_EXTERN extern
|
||||
#endif
|
||||
|
||||
/*************************************************/
|
||||
/* Initialization and general datatypes */
|
||||
|
||||
typedef struct rktio_t rktio_t;
|
||||
/* A rktio_t value represents an instance of the Racket I/O system.
|
||||
Almost every `rktio_...` function takes it as the first argument. */
|
||||
|
@ -101,6 +104,24 @@ typedef int rktio_tri_t;
|
|||
typedef int rktio_bool_t;
|
||||
/* 0 or 1. */
|
||||
|
||||
typedef unsigned short rktio_char16_t;
|
||||
/* A UTF-16 code unit. A `rktio_char16_t *` is meant to be the same as
|
||||
`wchar_t *` on Windows. */
|
||||
|
||||
/*************************************************/
|
||||
/* DLL paths */
|
||||
|
||||
RKTIO_EXTERN void rktio_set_dll_path(rktio_char16_t *p);
|
||||
/* Sets a path to search for loading DLLs, such as `iconv` on Windows.
|
||||
This function departs from all the usual conventions: the given
|
||||
path is in wide-character format, it's not copied, and it's not
|
||||
specific to a `rktio_t` instance. */
|
||||
|
||||
RKTIO_EXTERN rktio_char16_t *rktio_get_dll_path(rktio_char16_t *p);
|
||||
/* Combines a path prevously registered with `rktio_set_dll_path` with
|
||||
the given filename. The result is allocated (as should be
|
||||
deallocated) as usual. */
|
||||
|
||||
/*************************************************/
|
||||
/* Reading and writing files */
|
||||
|
||||
|
@ -878,11 +899,10 @@ rktio_ok_t rktio_shell_execute(rktio_t *rktio,
|
|||
/*************************************************/
|
||||
/* Path conversion */
|
||||
|
||||
void *rktio_path_to_wide_path(rktio_t *rktio, const char *p);
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const void *wp);
|
||||
rktio_char16_t *rktio_path_to_wide_path(rktio_t *rktio, const char *p);
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const rktio_char16_t *wp);
|
||||
/* Convert to/from the OS's native path representation. These
|
||||
functions are useful only on Windows, where each `void *`
|
||||
is actually a `wchar_t*`. The `rktio_path_to_wide_path`
|
||||
functions are useful only on Windows. The `rktio_path_to_wide_path`
|
||||
function can fail and report `RKTIO_ERROR_INVALID_PATH`. */
|
||||
|
||||
/*************************************************/
|
||||
|
@ -904,6 +924,91 @@ enum {
|
|||
RKTIO_LOG_DEBUG
|
||||
};
|
||||
|
||||
/*************************************************/
|
||||
/* Encoding conversion */
|
||||
|
||||
int rktio_convert_properties(rktio_t *rktio);
|
||||
/* Returns a combination of the following flags. */
|
||||
|
||||
#define RKTIO_CONVERTER_SUPPORTED (1 << 0)
|
||||
#define RKTIO_CONVERT_STRCOLL_UTF16 (1 << 1)
|
||||
#define RKTIO_CONVERT_RECASE_UTF16 (1 << 2)
|
||||
|
||||
typedef struct rktio_converter_t rktio_converter_t;
|
||||
|
||||
rktio_converter_t *rktio_converter_open(rktio_t *rktio, const char *to_enc, const char *from_enc);
|
||||
/* Creates an encoding converter. */
|
||||
|
||||
void rktio_converter_close(rktio_t *rktio, rktio_converter_t *cvt);
|
||||
/* Destroys an encoding converter. */
|
||||
|
||||
intptr_t rktio_convert(rktio_t *rktio,
|
||||
rktio_converter_t *cvt,
|
||||
char **in, intptr_t *in_left,
|
||||
char **out, intptr_t *out_left);
|
||||
/* Converts some bytes, following the icon protocol: each consumed by
|
||||
increments `*in` and decrements `*in_left`, and each produced by
|
||||
increments `*out` and decrements `*out_left`. In case of an error,
|
||||
the result is `RKTIO_CONVERT_ERROR` and the last error is set to
|
||||
one of `RKTIO_ERROR_CONVERT_NOT_ENOUGH_SPACE`,
|
||||
`RKTIO_ERROR_CONVERT_BAD_SEQUENCE`, or `RKTIO_ERROR_CONVERT_OTHER`
|
||||
--- but an error indicates something within `in` or `out`,
|
||||
and some bytes may have been successfully converted even if an
|
||||
error is reported. */
|
||||
|
||||
#define RKTIO_CONVERT_ERROR (-1)
|
||||
|
||||
char *rktio_locale_recase(rktio_t *rktio,
|
||||
rktio_bool_t to_up,
|
||||
char *in);
|
||||
/* Upcases (of `to_up`) or downcases (if `!to_up`) the content of `in`
|
||||
using the current locale's encoding and case conversion. */
|
||||
|
||||
rktio_char16_t *rktio_recase_utf16(rktio_t *rktio,
|
||||
rktio_bool_t to_up, rktio_char16_t *s1,
|
||||
intptr_t len, intptr_t *olen);
|
||||
/* Converts the case of a string encoded in UTF-16 for the system's
|
||||
default locale if the OS provided direct support for it. The
|
||||
`RKTIO_CONVERT_RECASE_UTF16 property from
|
||||
`rktio_convert_properties` reports whether this functon will work.
|
||||
Takes and optionally returns a length (`olen` can be NULL), but the
|
||||
UTF-16 sequence is expected to have no nuls. */
|
||||
|
||||
int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2);
|
||||
/* Returns -1 if `s1` is less than `s2` by the current locale's
|
||||
comparison, positive is `s1` is greater, and 0 if the strings
|
||||
are equal. */
|
||||
|
||||
int rktio_strcoll_utf16(rktio_t *rktio,
|
||||
rktio_char16_t *s1, intptr_t l1,
|
||||
rktio_char16_t *s2, intptr_t l2,
|
||||
rktio_bool_t cvt_case);
|
||||
/* Compares two strings encoded in UTF-16 for the system's default
|
||||
locale if the OS provided direct support for it. The
|
||||
`RKTIO_CONVERT_STRCOLL_UTF16 property from
|
||||
`rktio_convert_properties` reports whether this functon will work.
|
||||
Takes lengths, but the UTF-16 sequences are expected to have
|
||||
no include nuls. */
|
||||
|
||||
char *rktio_locale_encoding(rktio_t *rktio);
|
||||
/* Returns the name of the current locale's encoding. */
|
||||
|
||||
void rktio_set_locale(rktio_t *rktio, char *name);
|
||||
/* Sets the current locale, which affects string comparisons and
|
||||
conversions. It can also affect the C library's character-property
|
||||
predicates and number printing/parsing. The empty string
|
||||
corresponds to the OS's native locale. */
|
||||
|
||||
char *rktio_push_c_numeric_locale(rktio_t *rktio);
|
||||
void rktio_pop_c_numeric_locale(rktio_t *rktio, char *prev);
|
||||
/* Use this pair of funtions to temporarily switch the locale to the C
|
||||
locale for number parsing and printing. The result of the first
|
||||
function is deallocated when passed to second function. */
|
||||
|
||||
char *rktio_system_language_country(rktio_t *rktio);
|
||||
/* Returns the current system's language in country in a 5-character
|
||||
format such as "en_US". */
|
||||
|
||||
/*************************************************/
|
||||
/* Errors */
|
||||
|
||||
|
@ -948,6 +1053,10 @@ enum {
|
|||
RKTIO_ERROR_TIME_OUT_OF_RANGE,
|
||||
RKTIO_ERROR_NO_SUCH_ENVVAR,
|
||||
RKTIO_ERROR_SHELL_EXECUTE_FAILED,
|
||||
RKTIO_ERROR_CONVERT_NOT_ENOUGH_SPACE,
|
||||
RKTIO_ERROR_CONVERT_BAD_SEQUENCE,
|
||||
RKTIO_ERROR_CONVERT_PREMATURE_END,
|
||||
RKTIO_ERROR_CONVERT_OTHER,
|
||||
};
|
||||
|
||||
RKTIO_EXTERN void rktio_set_last_error(rktio_t *rktio, int kind, int errid);
|
||||
|
|
|
@ -46,8 +46,14 @@ typedef unsigned long long rktio_uint64_t;
|
|||
/* Whether getaddrinfo() is available: */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Whether nl_langinfo works. */
|
||||
#undef RKTIO_HAVE_CODESET
|
||||
|
||||
/* In case you want to avoid dynamic sizing of `fd_set` arrays: */
|
||||
#undef RKTIO_STATIC_FDSET_SIZE
|
||||
|
||||
/* In case you want to use fcntl for file locks */
|
||||
#undef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
|
||||
|
||||
/* In case iconv is not available: */
|
||||
#undef RKTIO_NO_ICONV
|
||||
|
|
670
racket/src/rktio/rktio_convert.c
Normal file
670
racket/src/rktio/rktio_convert.c
Normal file
|
@ -0,0 +1,670 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef OS_X
|
||||
# define MACOS_UNICODE_SUPPORT
|
||||
#endif
|
||||
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#if !defined(RKTIO_SYSTEM_WINDOWS) && !defined(RKTIO_NO_ICONV)
|
||||
# include <iconv.h>
|
||||
# include <langinfo.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
#ifdef MACOS_UNICODE_SUPPORT
|
||||
# include <CoreFoundation/CFString.h>
|
||||
# include <CoreFoundation/CFLocale.h>
|
||||
#endif
|
||||
|
||||
/*============================================================*/
|
||||
/* Using iconv via a DLL */
|
||||
/*============================================================*/
|
||||
|
||||
#ifdef RKTIO_NO_ICONV
|
||||
|
||||
# define HAVE_CODESET 0
|
||||
# define ICONV_errno 0
|
||||
# define RKTIO_CHK_PROC(x) 0
|
||||
# define iconv_ready 1
|
||||
|
||||
typedef intptr_t iconv_t;
|
||||
static size_t iconv(iconv_t cd, char **in, size_t *in_left, char **out, size_t *out_left) { return (size_t)-1; }
|
||||
static iconv_t iconv_open(const char *to, const char *from) { return -1; }
|
||||
static void iconv_close(iconv_t cd) { }
|
||||
static void init_iconv() { }
|
||||
|
||||
#elif defined(RKTIO_SYSTEM_WINDOWS)
|
||||
|
||||
static wchar_t *dlldir;
|
||||
|
||||
typedef intptr_t iconv_t;
|
||||
typedef int *(*errno_proc_t)();
|
||||
typedef size_t (*iconv_proc_t)(iconv_t cd,
|
||||
char **inbuf, size_t *inbytesleft,
|
||||
char **outbuf, size_t *outbytesleft);
|
||||
typedef iconv_t (*iconv_open_proc_t)(const char *tocode, const char *fromcode);
|
||||
typedef void (*iconv_close_proc_t)(iconv_t cd);
|
||||
typedef char *(*locale_charset_proc_t)();
|
||||
static errno_proc_t iconv_errno;
|
||||
static iconv_proc_t iconv;
|
||||
static iconv_open_proc_t iconv_open;
|
||||
static iconv_close_proc_t iconv_close;
|
||||
static locale_charset_proc_t locale_charset; /* Not used, currently */
|
||||
|
||||
static int get_iconv_errno(void)
|
||||
{
|
||||
int *a;
|
||||
a = iconv_errno();
|
||||
return *a;
|
||||
}
|
||||
|
||||
# define HAVE_CODESET 1
|
||||
# define CODESET 0
|
||||
# define ICONV_errno get_iconv_errno()
|
||||
# define RKTIO_CHK_PROC(x) x
|
||||
static int iconv_ready = 0;
|
||||
|
||||
static void init_iconv()
|
||||
{
|
||||
HMODULE m;
|
||||
wchar_t *p;
|
||||
|
||||
p = rktio_get_dll_path(L"iconv.dll");
|
||||
if (p) {
|
||||
m = LoadLibraryW(p);
|
||||
free(p);
|
||||
} else
|
||||
m = NULL;
|
||||
|
||||
if (!m) {
|
||||
p = rktio_get_dll_path(L"libiconv.dll");
|
||||
if (p) {
|
||||
m = LoadLibraryW(p);
|
||||
free(p);
|
||||
} else
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
if (!m) {
|
||||
p = rktio_get_dll_path(L"libiconv-2.dll");
|
||||
if (p) {
|
||||
m = LoadLibraryW(p);
|
||||
free(p);
|
||||
} else
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
if (!m)
|
||||
m = LoadLibraryW(L"iconv.dll");
|
||||
if (!m)
|
||||
m = LoadLibraryW(L"libiconv.dll");
|
||||
if (!m)
|
||||
m = LoadLibraryW(L"libiconv-2.dll");
|
||||
|
||||
if (m) {
|
||||
iconv = (iconv_proc_t)GetProcAddress(m, "libiconv");
|
||||
iconv_open = (iconv_open_proc_t)GetProcAddress(m, "libiconv_open");
|
||||
iconv_close = (iconv_close_proc_t)GetProcAddress(m, "libiconv_close");
|
||||
locale_charset = (locale_charset_proc_t)GetProcAddress(m, "locale_charset");
|
||||
/* Make sure we have all of them or none: */
|
||||
if (!iconv || !iconv_open || !iconv_close) {
|
||||
iconv = NULL;
|
||||
iconv_open = NULL;
|
||||
iconv_close = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (iconv) {
|
||||
iconv_errno = (errno_proc_t)GetProcAddress(m, "_errno");
|
||||
if (!iconv_errno) {
|
||||
/* The iconv.dll distributed with Racket links to msvcrt.dll.
|
||||
It's a slighly dangerous assumption that whatever iconv we
|
||||
found also uses msvcrt.dll. */
|
||||
m = LoadLibraryW(L"msvcrt.dll");
|
||||
if (m) {
|
||||
iconv_errno = (errno_proc_t)GetProcAddress(m, "_errno");
|
||||
if (!iconv_errno) {
|
||||
iconv = NULL;
|
||||
iconv_open = NULL;
|
||||
iconv_close = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iconv_ready = 1;
|
||||
}
|
||||
|
||||
rktio_char16_t *rktio_get_dll_path(rktio_char16_t *s)
|
||||
{
|
||||
if (dlldir) {
|
||||
int len1, len2;
|
||||
wchar_t *p;
|
||||
len1 = wcslen(dlldir);
|
||||
len2 = wcslen(s);
|
||||
p = malloc((len1 + len2 + 2) * sizeof(wchar_t));
|
||||
memcpy(p, dlldir, len1 * sizeof(wchar_t));
|
||||
if (p[len1 - 1] != '\\') {
|
||||
p[len1++] = '\\';
|
||||
}
|
||||
memcpy(p + len1, s, (len2 + 1) * sizeof(wchar_t));
|
||||
return p;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rktio_set_dll_path(rktio_char16_t *p)
|
||||
{
|
||||
dlldir = p;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# ifdef RKTIO_HAVE_CODESET
|
||||
# define HAVE_CODESET 1
|
||||
# else
|
||||
# define HAVE_CODESET 0
|
||||
# endif
|
||||
|
||||
# include <errno.h>
|
||||
# define ICONV_errno errno
|
||||
# define iconv_ready 1
|
||||
# define RKTIO_CHK_PROC(x) 1
|
||||
static void init_iconv() { }
|
||||
|
||||
void rktio_set_dll_path(rktio_char16_t *p) { }
|
||||
rktio_char16_t *rktio_get_dll_path(rktio_char16_t *s) { return NULL; }
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================*/
|
||||
/* Properties */
|
||||
/*============================================================*/
|
||||
|
||||
int rktio_convert_properties(rktio_t *rktio)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (!iconv_ready) init_iconv();
|
||||
|
||||
if (RKTIO_CHK_PROC(iconv_errno))
|
||||
flags = RKTIO_CONVERTER_SUPPORTED;
|
||||
|
||||
#if defined(MACOS_UNICODE_SUPPORT) || defined(RKTIO_SYSTEM_WINDOWS)
|
||||
flags |= (RKTIO_CONVERT_STRCOLL_UTF16 | RKTIO_CONVERT_RECASE_UTF16);
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
/* Current locale */
|
||||
/*============================================================*/
|
||||
|
||||
void rktio_set_locale(rktio_t *rktio, char *name)
|
||||
{
|
||||
/* We only need CTYPE and COLLATE; two calls seem to be much
|
||||
faster than one call with ALL */
|
||||
if (name) {
|
||||
if (!setlocale(LC_CTYPE, name))
|
||||
setlocale(LC_CTYPE, "C");
|
||||
if (!setlocale(LC_COLLATE, name))
|
||||
setlocale(LC_COLLATE, "C");
|
||||
} else {
|
||||
setlocale(LC_CTYPE, "C");
|
||||
setlocale(LC_COLLATE, "C");
|
||||
}
|
||||
}
|
||||
|
||||
char *rktio_push_c_numeric_locale(rktio_t *rktio)
|
||||
{
|
||||
char *prev;
|
||||
prev = setlocale(LC_NUMERIC, NULL);
|
||||
if (!prev || !strcmp(prev, "C"))
|
||||
return NULL;
|
||||
else
|
||||
return setlocale(LC_NUMERIC, "C");
|
||||
}
|
||||
|
||||
void rktio_pop_c_numeric_locale(rktio_t *rktio, char *prev)
|
||||
{
|
||||
if (prev)
|
||||
setlocale(LC_NUMERIC, prev);
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
/* Current locale's encoding */
|
||||
/*============================================================*/
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
|
||||
static char *nl_langinfo_dup()
|
||||
{
|
||||
int i;
|
||||
char *current_locale_name;
|
||||
|
||||
current_locale_name = setlocale(LC_NUMERIC, NULL);
|
||||
if (!current_locale_name)
|
||||
current_locale_name = "";
|
||||
|
||||
if ((current_locale_name[0] == 'C')
|
||||
&& !current_locale_name[1])
|
||||
return MSC_IZE(strdup)("US-ASCII");
|
||||
|
||||
for (i = 0; current_locale_name[i]; i++) {
|
||||
if (current_locale_name[i] == '.') {
|
||||
if (current_locale_name[i + 1]) {
|
||||
int len, j;
|
||||
char *enc;
|
||||
i++;
|
||||
len = scheme_char_strlen(current_locale_name) - i;
|
||||
enc = malloc(2 + len + 1);
|
||||
|
||||
/* Check whether the encoding is numeric, in which case
|
||||
we add "CP" in front to make it an encoding name */
|
||||
for (j = i; current_locale_name[j]; j++) {
|
||||
if (current_locale_name[j] > 127)
|
||||
break;
|
||||
if (!isdigit(current_locale_name[j]))
|
||||
break;
|
||||
}
|
||||
if (!current_locale_name[j]) {
|
||||
j = 2;
|
||||
memcpy(enc, "CP", j);
|
||||
} else {
|
||||
j = 0;
|
||||
}
|
||||
|
||||
while (current_locale_name[i]) {
|
||||
if (current_locale_name[i] > 127) {
|
||||
free(enc);
|
||||
return MSC_IZE(strdup)("UTF-8");
|
||||
}
|
||||
enc[j++] = current_locale_name[i++];
|
||||
}
|
||||
enc[j] = 0;
|
||||
return enc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MSC_IZE(strdup)("UTF-8");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static char *nl_langinfo_dup()
|
||||
{
|
||||
char *s;
|
||||
# if HAVE_CODESET
|
||||
s = nl_langinfo(CODESET);
|
||||
# else
|
||||
/* nl_langinfo doesn't work, so just make up something */
|
||||
s = "UTF-8";
|
||||
# endif
|
||||
|
||||
return MSC_IZE(strdup)(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *rktio_locale_encoding(rktio_t *rktio)
|
||||
{
|
||||
return nl_langinfo_dup();
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
|
||||
char *rktio_system_language_country(rktio_t *rktio)
|
||||
{
|
||||
#ifdef MACOS_UNICODE_SUPPORT
|
||||
/* Mac OS */
|
||||
CFLocaleRef l;
|
||||
CFStringRef s;
|
||||
int len;
|
||||
char *r;
|
||||
|
||||
l = CFLocaleCopyCurrent();
|
||||
s = CFLocaleGetIdentifier(l);
|
||||
|
||||
len = CFStringGetLength(s);
|
||||
r = malloc(len * 6 + 1);
|
||||
CFStringGetCString(s, r, len * 6 + 1, kCFStringEncodingUTF8);
|
||||
|
||||
CFRelease(l);
|
||||
|
||||
r[5] = 0;
|
||||
|
||||
return r;
|
||||
#elif defined(RKTIO_SYSTEM_WINDOWS)
|
||||
/* Windows */
|
||||
LCID l;
|
||||
int llen, clen;
|
||||
char *lang, *country, *s;
|
||||
l = GetUserDefaultLCID();
|
||||
|
||||
llen = GetLocaleInfo(l, LOCALE_SENGLANGUAGE, NULL, 0);
|
||||
lang = malloc(llen);
|
||||
GetLocaleInfo(l, LOCALE_SENGLANGUAGE, lang, llen);
|
||||
if (llen)
|
||||
llen -= 1; /* drop nul terminator */
|
||||
|
||||
clen = GetLocaleInfo(l, LOCALE_SENGCOUNTRY, NULL, 0);
|
||||
country = malloc(clen);
|
||||
GetLocaleInfo(l, LOCALE_SENGCOUNTRY, country, clen);
|
||||
if (clen)
|
||||
clen -= 1; /* drop nul terminator */
|
||||
|
||||
s = malloc(clen + llen + 2);
|
||||
memcpy(s, lang, llen);
|
||||
memcpy(s + 1 + llen, country, clen);
|
||||
s[llen] = '_';
|
||||
s[clen + llen + 1] = 0;
|
||||
|
||||
free(lang);
|
||||
free(country);
|
||||
|
||||
return s;
|
||||
#else
|
||||
/* Unix */
|
||||
char *s;
|
||||
|
||||
s = getenv("LC_ALL");
|
||||
if (!s)
|
||||
s = getenv("LC_CTYPE");
|
||||
if (!s)
|
||||
s = getenv("LANG");
|
||||
|
||||
if (s) {
|
||||
/* Check that the environment variable has the form
|
||||
xx_XX[.ENC] */
|
||||
if ((s[0] >= 'a') && (s[0] <= 'z')
|
||||
&& (s[1] >= 'a') && (s[1] <= 'z')
|
||||
&& (s[2] == '_')
|
||||
&& (s[3] >= 'A') && (s[3] <= 'Z')
|
||||
&& (s[4] >= 'A') && (s[4] <= 'Z')
|
||||
&& (!s[5] || s[5] == '.')) {
|
||||
/* Good */
|
||||
} else
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
if (!s)
|
||||
s = "en_US";
|
||||
|
||||
return MSC_IZE(strdup)(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
/* Converters */
|
||||
/*============================================================*/
|
||||
|
||||
struct rktio_converter_t {
|
||||
iconv_t cd;
|
||||
};
|
||||
|
||||
rktio_converter_t *rktio_converter_open(rktio_t *rktio, const char *to_enc, const char *from_enc)
|
||||
{
|
||||
iconv_t cd;
|
||||
rktio_converter_t *cvt;
|
||||
|
||||
if (!iconv_ready) init_iconv();
|
||||
|
||||
cd = iconv_open(to_enc, from_enc);
|
||||
if (cd == (iconv_t)-1) {
|
||||
errno = ICONV_errno;
|
||||
get_posix_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cvt = malloc(sizeof(rktio_converter_t));
|
||||
cvt->cd = cd;
|
||||
return cvt;
|
||||
}
|
||||
|
||||
void rktio_converter_close(rktio_t *rktio, rktio_converter_t *cvt)
|
||||
{
|
||||
iconv_close(cvt->cd);
|
||||
free(cvt);
|
||||
}
|
||||
|
||||
intptr_t rktio_convert(rktio_t *rktio,
|
||||
rktio_converter_t *cvt,
|
||||
char **in, intptr_t *in_left,
|
||||
char **out, intptr_t *out_left)
|
||||
{
|
||||
size_t il = *in_left, ol = *out_left, r;
|
||||
int icerr;
|
||||
|
||||
r = iconv(cvt->cd, in, &il, out, &ol);
|
||||
|
||||
*in_left = il;
|
||||
*out_left = ol;
|
||||
|
||||
if (r == (size_t)-1) {
|
||||
icerr = ICONV_errno;
|
||||
|
||||
if (icerr == E2BIG)
|
||||
set_racket_error(RKTIO_ERROR_CONVERT_NOT_ENOUGH_SPACE);
|
||||
else if (icerr == EILSEQ)
|
||||
set_racket_error(RKTIO_ERROR_CONVERT_BAD_SEQUENCE);
|
||||
else if (icerr == EINVAL)
|
||||
set_racket_error(RKTIO_ERROR_CONVERT_PREMATURE_END);
|
||||
else
|
||||
set_racket_error(RKTIO_ERROR_CONVERT_OTHER);
|
||||
return RKTIO_CONVERT_ERROR;
|
||||
}
|
||||
|
||||
return (intptr_t)r;
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
/* Case conversion */
|
||||
/*============================================================*/
|
||||
|
||||
char *rktio_locale_recase(rktio_t *rktio,
|
||||
rktio_bool_t to_up,
|
||||
char *in)
|
||||
{
|
||||
char *out;
|
||||
|
||||
#ifdef NO_MBTOWC_FUNCTIONS
|
||||
/* No wide-char functions...
|
||||
The C library's toupper and tolower is supposed to be
|
||||
locale-sensitive. It can't be right for characters that are
|
||||
encoded in multiple bytes, but probably it will do the right
|
||||
thing in common cases. */
|
||||
intptr_t iilen = strlen(in);
|
||||
int i;
|
||||
|
||||
/* First, copy "in" to "out" */
|
||||
out = malloc(iilen + 1);
|
||||
memcpy(out, in, iilen);
|
||||
out[iilen] = 0;
|
||||
|
||||
/* Re-case chars in "out" */
|
||||
for (i = 0; i < iilen; i++) {
|
||||
char t;
|
||||
t = (to_up) ? toupper(out[i]) : tolower(out[i]);
|
||||
out[i] = t;
|
||||
}
|
||||
|
||||
return out;
|
||||
#else
|
||||
/* To change the case, convert the string to multibyte, re-case the
|
||||
multibyte, then convert back. */
|
||||
# define RKTIO_WC_BUF_SIZE 32
|
||||
mbstate_t state;
|
||||
size_t wl, ml;
|
||||
wchar_t *wc, *ws, wcbuf[RKTIO_WC_BUF_SIZE], cwc;
|
||||
const char *s;
|
||||
unsigned int j;
|
||||
/* The "n" versions are apparently not too standard: */
|
||||
# define mz_mbsnrtowcs(t, f, fl, tl, s) mbsrtowcs(t, f, tl, s)
|
||||
# define mz_wcsnrtombs(t, f, fl, tl, s) wcsrtombs(t, f, tl, s)
|
||||
|
||||
/* ----- to wide char ---- */
|
||||
|
||||
/* Get length */
|
||||
memset(&state, 0, sizeof(mbstate_t));
|
||||
s = in;
|
||||
wl = mz_mbsnrtowcs(NULL, &s, iilen, 0, &state);
|
||||
s = NULL;
|
||||
|
||||
/* Allocate space */
|
||||
if (wl < RKTIO_WC_BUF_SIZE) {
|
||||
wc = wcbuf;
|
||||
} else {
|
||||
wc = malloc(sizeof(wchar_t) * (wl + 1));
|
||||
}
|
||||
|
||||
/* Convert */
|
||||
memset(&state, 0, sizeof(mbstate_t));
|
||||
s = in;
|
||||
(void)mz_mbsnrtowcs(wc, &s, iilen, wl + 1, &state);
|
||||
s = NULL;
|
||||
|
||||
wc[wl] = 0; /* just in case */
|
||||
|
||||
/* ---- re-case ---- */
|
||||
|
||||
if (to_up) {
|
||||
for (j = 0; j < wl; j++) {
|
||||
cwc = towupper(wc[j]);
|
||||
wc[j] = cwc;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < wl; j++) {
|
||||
cwc = towlower(wc[j]);
|
||||
wc[j] = cwc;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- back to multibyte ---- */
|
||||
|
||||
/* Measure */
|
||||
memset(&state, 0, sizeof(mbstate_t));
|
||||
ws = wc;
|
||||
ml = mz_wcsnrtombs(NULL, (const wchar_t **)&ws, wl, 0, &state);
|
||||
ws = NULL;
|
||||
|
||||
/* Allocate space */
|
||||
out = malloc(ml + 1);
|
||||
|
||||
/* Convert */
|
||||
memset(&state, 0, sizeof(mbstate_t));
|
||||
ws = wc;
|
||||
(void)mz_wcsnrtombs(out, (const wchar_t **)&ws, wl, ml + 1, &state);
|
||||
ws = NULL;
|
||||
|
||||
out[ml] = 0;
|
||||
|
||||
if (wc != wcbuf) free(wc);
|
||||
|
||||
return out;
|
||||
#endif
|
||||
}
|
||||
|
||||
rktio_char16_t *rktio_recase_utf16(rktio_t *rktio, rktio_bool_t to_up, rktio_char16_t *s1, intptr_t l1, intptr_t *olen)
|
||||
{
|
||||
#ifdef MACOS_UNICODE_SUPPORT
|
||||
CFMutableStringRef mstr;
|
||||
CFStringRef str;
|
||||
CFRange rng;
|
||||
rktio_char16_t *result;
|
||||
intptr_t len;
|
||||
|
||||
str = CFStringCreateWithBytes(NULL, (unsigned char *)s1, (l1 * sizeof(rktio_char16_t)), kCFStringEncodingUnicode, FALSE);
|
||||
mstr = CFStringCreateMutableCopy(NULL, 0, str);
|
||||
CFRelease(str);
|
||||
|
||||
if (to_up)
|
||||
CFStringUppercase(mstr, NULL);
|
||||
else
|
||||
CFStringLowercase(mstr, NULL);
|
||||
|
||||
len = CFStringGetLength(mstr);
|
||||
|
||||
result = malloc((len + 1) * sizeof(rktio_char16_t));
|
||||
|
||||
rng = CFRangeMake(0, len);
|
||||
CFStringGetCharacters(mstr, rng, (UniChar *)result);
|
||||
CFRelease(mstr);
|
||||
|
||||
result[len] = 0;
|
||||
|
||||
if (olen)
|
||||
*olen = len;
|
||||
|
||||
return result;
|
||||
#elif defined(RKTIO_SYSTEM_WINDOWS)
|
||||
rktio_char16_t *result;
|
||||
|
||||
result = malloc((l1 + 1) * sizeof(rktio_char16_t));
|
||||
memcpy(result, s1, l1 * sizeof(rktio_char16_t));
|
||||
result[l1] = 0;
|
||||
|
||||
if (to_up)
|
||||
CharUpperBuffW((wchar_t *)result, l1);
|
||||
else
|
||||
CharLowerBuffW((wchar_t *)result, l1);
|
||||
|
||||
if (olen)
|
||||
*olen = l1;
|
||||
|
||||
return result;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*============================================================*/
|
||||
/* Native string comparison */
|
||||
/*============================================================*/
|
||||
|
||||
int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2)
|
||||
{
|
||||
return strcoll(s1, s2);
|
||||
}
|
||||
|
||||
int rktio_strcoll_utf16(rktio_t *rktio,
|
||||
rktio_char16_t *s1, intptr_t l1,
|
||||
rktio_char16_t *s2, intptr_t l2,
|
||||
rktio_bool_t cvt_case)
|
||||
{
|
||||
#ifdef MACOS_UNICODE_SUPPORT
|
||||
CFStringRef str1, str2;
|
||||
CFComparisonResult r;
|
||||
|
||||
str1 = CFStringCreateWithBytes(NULL, (unsigned char *)s1, (l1 * sizeof(rktio_char16_t)),
|
||||
kCFStringEncodingUnicode, FALSE);
|
||||
str2 = CFStringCreateWithBytes(NULL, (unsigned char *)s2, (l2 * sizeof(rktio_char16_t)),
|
||||
kCFStringEncodingUnicode, FALSE);
|
||||
|
||||
r = CFStringCompare(str1, str2, (kCFCompareLocalized
|
||||
| (cvt_case ? kCFCompareCaseInsensitive : 0)));
|
||||
|
||||
CFRelease(str1);
|
||||
CFRelease(str2);
|
||||
|
||||
return (int)r;
|
||||
#elif defined(RKTIO_SYSTEM_WINDOWS)
|
||||
int r;
|
||||
r = CompareStringW(LOCALE_USER_DEFAULT,
|
||||
((cvt_case ? NORM_IGNORECASE : 0)
|
||||
| NORM_IGNOREKANATYPE
|
||||
| NORM_IGNOREWIDTH),
|
||||
(wchar_t *)s1, l1, (wchar_t *)s2, l2);
|
||||
|
||||
return r - 2;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
|||
p = ea[i];
|
||||
for (j = 0; p[j] && p[j] != '='; j++) {
|
||||
}
|
||||
envvars->names[i] = MSC_IZE(strndup)(p, j);
|
||||
envvars->names[i] = rktio_strndup(p, j);
|
||||
envvars->vals[i] = MSC_IZE(strdup)(p+j+1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -38,6 +35,10 @@ err_str_t err_strs[] = {
|
|||
{ RKTIO_ERROR_TIME_OUT_OF_RANGE, "time value out-of-range for date conversion" },
|
||||
{ RKTIO_ERROR_NO_SUCH_ENVVAR, "no value as an environment variable" },
|
||||
{ RKTIO_ERROR_SHELL_EXECUTE_FAILED, "ShellExecute failed" },
|
||||
{ RKTIO_ERROR_CONVERT_NOT_ENOUGH_SPACE, "encoding conversion needs more output space" },
|
||||
{ RKTIO_ERROR_CONVERT_BAD_SEQUENCE, "ill-formed input encountered in encoding conversion" },
|
||||
{ RKTIO_ERROR_CONVERT_PREMATURE_END, "input encoding ended prematurely" },
|
||||
{ RKTIO_ERROR_CONVERT_OTHER, "encoding conversion encountered an error" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1533,7 +1533,7 @@ char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl)
|
|||
continue;
|
||||
# endif
|
||||
|
||||
return strndup(e->d_name, nlen);
|
||||
return rktio_strndup(e->d_name, nlen);
|
||||
}
|
||||
|
||||
rktio_directory_list_stop(rktio, dl);
|
||||
|
|
|
@ -51,7 +51,7 @@ void rktio_destroy(rktio_t *rktio)
|
|||
}
|
||||
|
||||
/* Useful on Windows to make sure everyone is using the same malloc()
|
||||
and fre(): */
|
||||
and free(): */
|
||||
void rktio_free(void *p)
|
||||
{
|
||||
free(p);
|
||||
|
|
|
@ -91,13 +91,13 @@ struct rktio_t {
|
|||
wchar_t *wide_buffer;
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
HANDLE hEventLog;
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
|
||||
struct rktio_hash_t *locked_fd_process_map;
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
HANDLE hEventLog;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*========================================================================*/
|
||||
|
@ -323,3 +323,5 @@ void rktio_syslog_clean(rktio_t* rktio);
|
|||
#else
|
||||
# define BIG_OFF_T_IZE(n) n
|
||||
#endif
|
||||
|
||||
char *rktio_strndup(char *s, intptr_t len);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* For converting byte strings to and from "wide" strings on Windows. */
|
||||
|
@ -7,14 +8,16 @@
|
|||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
void rktio_init_wide(rktio_t *rktio) { }
|
||||
|
||||
void *rktio_path_to_wide_path(rktio_t *rktio, const char *p)
|
||||
rktio_char16_t *rktio_path_to_wide_path(rktio_t *rktio, const char *p)
|
||||
{
|
||||
return strdup(p);
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const void *wp)
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const rktio_char16_t *wp)
|
||||
{
|
||||
return strdup((char *)wp);
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -320,14 +323,26 @@ char *rktio_convert_from_wchar(const wchar_t *ws, int free_given)
|
|||
return s;
|
||||
}
|
||||
|
||||
void *rktio_path_to_wide_path(rktio_t *rktio, const char *p)
|
||||
rktio_char16_t *rktio_path_to_wide_path(rktio_t *rktio, const char *p)
|
||||
{
|
||||
return WIDE_PATH_copy(p);
|
||||
}
|
||||
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const void *wp)
|
||||
char *rktio_wide_path_to_path(rktio_t *rktio, const rktio_char16_t *wp)
|
||||
{
|
||||
return NARROW_PATH_copy(wp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================*/
|
||||
|
||||
/* The same as strndup(), but sometimes strndup() is missing */
|
||||
char *rktio_strndup(char *s, intptr_t len)
|
||||
{
|
||||
char *s2;
|
||||
s2 = malloc(len + 1);
|
||||
memcpy(s2, s, len);
|
||||
s2[len] = 0;
|
||||
return s2;
|
||||
}
|
||||
|
|
|
@ -166,6 +166,10 @@
|
|||
RelativePath="..\..\rktio\rktio_syslog.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\rktio\rktio_convert.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\rktio\rktio_error.c"
|
||||
>
|
||||
|
|
|
@ -130,6 +130,7 @@
|
|||
<ClCompile Include="..\..\rktio\rktio_shellex.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_time.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_syslog.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_convert.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_error.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_hash.c" />
|
||||
<ClCompile Include="..\..\rktio\rktio_wide.c" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user