Skip to content
Snippets Groups Projects
Commit 16a636f2 authored by Konstantin Belyavskiy's avatar Konstantin Belyavskiy Committed by Konstantin Osipov
Browse files

Fix linking with iconv under FreeBSD

On FreeBSD we have either system iconv (part of libc) or the one
in /usr/local. The first one is not fully compatible with Linux/
OSX iconv and both adds specific prefixes to function names.
So to use them via Lua FFI mechanism, specific names are required.
Proposal fix:
Under FreeBSD link with /usr/local/lib/libiconv.so and add prefix.

Closes gh-3073.
parent 01015ee7
No related branches found
No related tags found
No related merge requests found
...@@ -234,6 +234,12 @@ if (TARGET_OS_FREEBSD AND NOT TARGET_OS_DEBIAN_FREEBSD) ...@@ -234,6 +234,12 @@ if (TARGET_OS_FREEBSD AND NOT TARGET_OS_DEBIAN_FREEBSD)
else() else()
set (common_libraries ${common_libraries} ${INTL}) set (common_libraries ${common_libraries} ${INTL})
endif() endif()
find_library (ICONV iconv)
if (NOT ICONV)
message(FATAL_ERROR "iconv library not found")
else()
set (common_libraries ${common_libraries} ${ICONV})
endif()
endif() endif()
set (common_libraries ${common_libraries} ${LIBUUID_LIBRARIES}) set (common_libraries ${common_libraries} ${LIBUUID_LIBRARIES})
......
...@@ -8,6 +8,13 @@ iconv_t iconv_open(const char *tocode, const char *fromcode); ...@@ -8,6 +8,13 @@ iconv_t iconv_open(const char *tocode, const char *fromcode);
void iconv_close(iconv_t cd); void iconv_close(iconv_t cd);
size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft); char **outbuf, size_t *outbytesleft);
/*
* add prefix 'lib' under FreeBSD
*/
iconv_t libiconv_open(const char *tocode, const char *fromcode);
void libiconv_close(iconv_t cd);
size_t libiconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
]] ]]
local iconv_t = ffi.typeof('struct iconv') local iconv_t = ffi.typeof('struct iconv')
...@@ -16,6 +23,22 @@ local cchar_ptr_arr_t = ffi.typeof('const char *[1]') ...@@ -16,6 +23,22 @@ local cchar_ptr_arr_t = ffi.typeof('const char *[1]')
local cchar_ptr_t = ffi.typeof('const char *') local cchar_ptr_t = ffi.typeof('const char *')
local size_t_arr_t = ffi.typeof('size_t [1]') local size_t_arr_t = ffi.typeof('size_t [1]')
local _iconv_open
local _iconv_close
local _iconv
-- To fix #3073, BSD iconv implementation is not fully
-- compatible with iconv, so use external iconv.so lib
if jit.os == 'BSD' then
_iconv_open = ffi.C.libiconv_open
_iconv_close = ffi.C.libiconv_close
_iconv = ffi.C.libiconv
else
_iconv_open = ffi.C.iconv_open
_iconv_close = ffi.C.iconv_close
_iconv = ffi.C.iconv
end
local E2BIG = errno['E2BIG'] local E2BIG = errno['E2BIG']
local EINVAL = errno['EINVAL'] local EINVAL = errno['EINVAL']
local EILSEQ = errno['EILSEQ'] local EILSEQ = errno['EILSEQ']
...@@ -41,10 +64,10 @@ local function iconv_convert(iconv, data) ...@@ -41,10 +64,10 @@ local function iconv_convert(iconv, data)
while data_left[0] > 0 do while data_left[0] > 0 do
buf_ptr[0] = buf:reserve(output_len) buf_ptr[0] = buf:reserve(output_len)
buf_left[0] = buf:unused() buf_left[0] = buf:unused()
local res = ffi.C.iconv(iconv, data_ptr, data_left, local res = _iconv(iconv, data_ptr, data_left,
buf_ptr, buf_left) buf_ptr, buf_left)
if res == ffi.cast('size_t', -1) and errno() ~= E2BIG then if res == ffi.cast('size_t', -1) and errno() ~= E2BIG then
ffi.C.iconv(iconv, nil, nil, nil, nil) _iconv(iconv, nil, nil, nil, nil)
if errno() == EINVAL then if errno() == EINVAL then
error('Invalid multibyte sequence') error('Invalid multibyte sequence')
end end
...@@ -57,7 +80,7 @@ local function iconv_convert(iconv, data) ...@@ -57,7 +80,7 @@ local function iconv_convert(iconv, data)
end end
-- iconv function sets cd's conversion state to the initial state -- iconv function sets cd's conversion state to the initial state
ffi.C.iconv(iconv, nil, nil, nil, nil) _iconv(iconv, nil, nil, nil, nil)
local result = ffi.string(buf.rpos, buf:size()) local result = ffi.string(buf.rpos, buf:size())
buf:reset() buf:reset()
return result return result
...@@ -65,7 +88,7 @@ end ...@@ -65,7 +88,7 @@ end
local iconv_mt = { local iconv_mt = {
__call = iconv_convert, __call = iconv_convert,
__gc = ffi.C.iconv_close, __gc = _iconv_close,
__tostring = function(iconv) return string.format("iconv: %p", iconv) end __tostring = function(iconv) return string.format("iconv: %p", iconv) end
} }
...@@ -75,7 +98,7 @@ local function iconv_new(to, from) ...@@ -75,7 +98,7 @@ local function iconv_new(to, from)
if type(to) ~= 'string' or type(from) ~= 'string' then if type(to) ~= 'string' or type(from) ~= 'string' then
error('Usage: iconv.new("CP1251", "KOI8-R")') error('Usage: iconv.new("CP1251", "KOI8-R")')
end end
local iconv = ffi.C.iconv_open(to, from) local iconv = _iconv_open(to, from)
if iconv == conv_rv_error then if iconv == conv_rv_error then
error('iconv: '..errno.strerror()) error('iconv: '..errno.strerror())
end end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment