Merge #10708 'remove DYNAMIC_ICONV'

closes #3457
This commit is contained in:
Justin M. Keyes 2019-08-09 11:19:37 +02:00
commit 8a56bd944a
10 changed files with 84 additions and 290 deletions

View File

@ -20,13 +20,6 @@ endif()
check_symbol_exists(_NSGetEnviron crt_externs.h HAVE__NSGETENVIRON)
# Headers
if(ICONV_INCLUDE_DIR)
list(APPEND CMAKE_REQUIRED_INCLUDES "${ICONV_INCLUDE_DIR}")
endif()
check_include_files(iconv.h HAVE_ICONV_H)
if(ICONV_INCLUDE_DIR)
list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${ICONV_INCLUDE_DIR}")
endif()
check_include_files(langinfo.h HAVE_LANGINFO_H)
check_include_files(locale.h HAVE_LOCALE_H)
check_include_files(pwd.h HAVE_PWD_H)

View File

@ -22,7 +22,6 @@
#cmakedefine HAVE_GETPWNAM
#cmakedefine HAVE_GETPWUID
#cmakedefine HAVE_ICONV
#cmakedefine HAVE_ICONV_H
#cmakedefine HAVE_LANGINFO_H
#cmakedefine HAVE_LOCALE_H
#cmakedefine HAVE_NL_LANGINFO_CODESET

View File

@ -11259,7 +11259,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"fork",
#endif
"gettext",
#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
#if defined(HAVE_ICONV)
"iconv",
#endif
"insert_expand",
@ -11372,10 +11372,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = stdout_isatty;
} else if (STRICMP(name, "multi_byte_encoding") == 0) {
n = has_mbyte != 0;
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
} else if (STRICMP(name, "iconv") == 0) {
n = iconv_enabled(false);
#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
#ifdef UNIX

View File

@ -163,22 +163,22 @@ typedef struct AutoPatCmd {
* Structure to pass arguments from buf_write() to buf_write_bytes().
*/
struct bw_info {
int bw_fd; /* file descriptor */
char_u *bw_buf; /* buffer with data to be written */
int bw_len; /* length of data */
int bw_fd; // file descriptor
char_u *bw_buf; // buffer with data to be written
int bw_len; // length of data
#ifdef HAS_BW_FLAGS
int bw_flags; /* FIO_ flags */
int bw_flags; // FIO_ flags
#endif
char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
int bw_restlen; /* nr of bytes in bw_rest[] */
int bw_first; /* first write call */
char_u *bw_conv_buf; /* buffer for writing converted chars */
int bw_conv_buflen; /* size of bw_conv_buf */
int bw_conv_error; /* set for conversion error */
linenr_T bw_conv_error_lnum; /* first line with error or zero */
linenr_T bw_start_lnum; /* line number at start of buffer */
# ifdef USE_ICONV
iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
int bw_restlen; // nr of bytes in bw_rest[]
int bw_first; // first write call
char_u *bw_conv_buf; // buffer for writing converted chars
int bw_conv_buflen; // size of bw_conv_buf
int bw_conv_error; // set for conversion error
linenr_T bw_conv_error_lnum; // first line with error or zero
linenr_T bw_start_lnum; // line number at start of buffer
# ifdef HAVE_ICONV
iconv_t bw_iconv_fd; // descriptor for iconv() or -1
# endif
};
@ -327,10 +327,10 @@ readfile(
char_u *fenc_next = NULL; // next item in 'fencs' or NULL
bool advance_fenc = false;
long real_size = 0;
# ifdef USE_ICONV
iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
int did_iconv = FALSE; /* TRUE when iconv() failed and trying
'charconvert' next */
# ifdef HAVE_ICONV
iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
int did_iconv = false; // TRUE when iconv() failed and trying
// 'charconvert' next
# endif
int converted = FALSE; /* TRUE if conversion done */
int notconverted = FALSE; /* TRUE if conversion wanted but it
@ -841,7 +841,7 @@ retry:
fileformat = EOL_UNKNOWN; /* detect from file */
}
# ifdef USE_ICONV
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
/* aborted conversion with iconv(), close the descriptor */
iconv_close(iconv_fd);
@ -908,15 +908,14 @@ retry:
# ifdef USE_ICONV
/*
* Try using iconv() if we can't convert internally.
*/
# ifdef HAVE_ICONV
// Try using iconv() if we can't convert internally.
if (fio_flags == 0
&& !did_iconv
)
) {
iconv_fd = (iconv_t)my_iconv_open(
enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
}
# endif
/*
@ -925,12 +924,12 @@ retry:
*/
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
&& !read_fifo
# ifdef USE_ICONV
# ifdef HAVE_ICONV
&& iconv_fd == (iconv_t)-1
# endif
) {
# ifdef USE_ICONV
did_iconv = FALSE;
# ifdef HAVE_ICONV
did_iconv = false;
# endif
/* Skip conversion when it's already done (retry for wrong
* "fileformat"). */
@ -950,7 +949,7 @@ retry:
}
} else {
if (fio_flags == 0
# ifdef USE_ICONV
# ifdef HAVE_ICONV
&& iconv_fd == (iconv_t)-1
# endif
) {
@ -1023,20 +1022,23 @@ retry:
* ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
* multiple of 4 */
real_size = (int)size;
# ifdef USE_ICONV
if (iconv_fd != (iconv_t)-1)
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
size = size / ICONV_MULT;
else
} else {
# endif
if (fio_flags & FIO_LATIN1)
if (fio_flags & FIO_LATIN1) {
size = size / 2;
else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
} else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
size = (size * 2 / 3) & ~1;
else if (fio_flags & FIO_UCS4)
} else if (fio_flags & FIO_UCS4) {
size = (size * 2 / 3) & ~3;
else if (fio_flags == FIO_UCSBOM)
size = size / ICONV_MULT; /* worst case */
} else if (fio_flags == FIO_UCSBOM) {
size = size / ICONV_MULT; // worst case
}
# ifdef HAVE_ICONV
}
# endif
if (conv_restlen > 0) {
// Insert unconverted bytes from previous line.
memmove(ptr, conv_rest, conv_restlen); // -V614
@ -1112,7 +1114,7 @@ retry:
/* When we did a conversion report an error. */
if (fio_flags != 0
# ifdef USE_ICONV
# ifdef HAVE_ICONV
|| iconv_fd != (iconv_t)-1
# endif
) {
@ -1135,7 +1137,7 @@ retry:
* leave the UTF8 checking code to do it, as it
* works slightly differently. */
if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
# ifdef USE_ICONV
# ifdef HAVE_ICONV
|| iconv_fd != (iconv_t)-1
# endif
)) {
@ -1144,8 +1146,8 @@ retry:
--conv_restlen;
}
}
fio_flags = 0; /* don't convert this */
# ifdef USE_ICONV
fio_flags = 0; // don't convert this
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
@ -1216,7 +1218,7 @@ retry:
if (size <= 0)
break;
# ifdef USE_ICONV
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
/*
* Attempt conversion of the read bytes to 'encoding' using
@ -1474,10 +1476,11 @@ retry:
* file is more likely than a conversion error. */
if (can_retry && !incomplete_tail)
break;
# ifdef USE_ICONV
/* When we did a conversion report an error. */
if (iconv_fd != (iconv_t)-1 && conv_error == 0)
# ifdef HAVE_ICONV
// When we did a conversion report an error.
if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
conv_error = readfile_linenr(linecnt, ptr, p);
}
# endif
/* Remember the first linenr with an illegal byte */
if (conv_error == 0 && illegal_byte == 0)
@ -1497,15 +1500,18 @@ retry:
if (p < ptr + size && !incomplete_tail) {
/* Detected a UTF-8 error. */
rewind_retry:
/* Retry reading with another conversion. */
# ifdef USE_ICONV
if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
/* iconv() failed, try 'charconvert' */
did_iconv = TRUE;
else
// Retry reading with another conversion.
# ifdef HAVE_ICONV
if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
// iconv() failed, try 'charconvert'
did_iconv = true;
} else {
# endif
// use next item from 'fileencodings'
advance_fenc = true;
# ifdef HAVE_ICONV
}
# endif
file_rewind = true;
goto retry;
}
@ -1710,7 +1716,7 @@ failed:
}
if (fenc_alloced)
xfree(fenc);
# ifdef USE_ICONV
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
# ifndef __clang_analyzer__
@ -2294,7 +2300,7 @@ buf_write(
write_info.bw_conv_error = FALSE;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
# ifdef USE_ICONV
# ifdef HAVE_ICONV
write_info.bw_iconv_fd = (iconv_t)-1;
# endif
@ -3015,7 +3021,7 @@ nobackup:
if (converted && wb_flags == 0) {
# ifdef USE_ICONV
# ifdef HAVE_ICONV
// Use iconv() conversion when conversion is needed and it's not done
// internally.
write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
@ -3045,7 +3051,7 @@ nobackup:
}
}
if (converted && wb_flags == 0
# ifdef USE_ICONV
# ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
# endif
&& wfname == fname
@ -3573,7 +3579,7 @@ nofail:
xfree(buffer);
xfree(fenc_tofree);
xfree(write_info.bw_conv_buf);
# ifdef USE_ICONV
# ifdef HAVE_ICONV
if (write_info.bw_iconv_fd != (iconv_t)-1) {
iconv_close(write_info.bw_iconv_fd);
write_info.bw_iconv_fd = (iconv_t)-1;
@ -3948,7 +3954,7 @@ static int buf_write_bytes(struct bw_info *ip)
}
}
# ifdef USE_ICONV
# ifdef HAVE_ICONV
if (ip->bw_iconv_fd != (iconv_t)-1) {
const char *from;
size_t fromlen;

View File

@ -655,16 +655,6 @@ EXTERN int inhibit_delete_count INIT(= 0);
/// Encoding used when 'fencs' is set to "default"
EXTERN char_u *fenc_default INIT(= NULL);
# if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
/* Pointers to functions and variables to be loaded at runtime */
EXTERN size_t (*iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
EXTERN iconv_t (*iconv_open)(const char *tocode, const char *fromcode);
EXTERN int (*iconv_close)(iconv_t cd);
EXTERN int (*iconvctl)(iconv_t cd, int request, void *argument);
EXTERN int* (*iconv_errno)(void);
# endif
/// "State" is the main state of Vim.
/// There are other variables that modify the state:
/// Visual_mode: When State is NORMAL or INSERT.

View File

@ -1,52 +1,20 @@
#ifndef NVIM_ICONV_H
#define NVIM_ICONV_H
// iconv can be linked at compile-time as well as loaded at runtime. In the
// latter case, some function pointers need to be initialized after loading
// the library (see `iconv_enabled()` in mbyte.c). These function pointers
// are stored in globals.h. Since globals.h includes iconv.h to get the
// definition of USE_ICONV, we can't include it from iconv.h. One way to
// solve this conundrum would be perhaps to let cmake decide the value of
// USE_ICONV, or to put the USE_ICONV definition in config.h.in directly. As
// it stands, globals.h needs to be included alongside iconv.h.
#include "auto/config.h"
// Use iconv() when it's available, either by linking to the library at
// compile time or by loading it at runtime.
#if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV)
# define USE_ICONV
#endif
// If we don't have the actual iconv header files present but USE_ICONV was
// defined, we provide a type shim (pull in errno.h and define iconv_t).
// This enables us to still load and use iconv dynamically at runtime.
#ifdef USE_ICONV
#ifdef HAVE_ICONV
# include <errno.h>
# ifdef HAVE_ICONV_H
# include <iconv.h>
# else
typedef void *iconv_t;
# endif
#endif
# include <iconv.h>
// define some missing constants if necessary
# ifdef USE_ICONV
# ifndef EILSEQ
# define EILSEQ 123
# endif
# ifdef DYNAMIC_ICONV
// on win32 iconv.dll is dynamically loaded
# define ICONV_ERRNO (*iconv_errno())
# define ICONV_E2BIG 7
# define ICONV_EINVAL 22
# define ICONV_EILSEQ 42
# else
# define ICONV_ERRNO errno
# define ICONV_E2BIG E2BIG
# define ICONV_EINVAL EINVAL
# define ICONV_EILSEQ EILSEQ
# endif
# endif
# define ICONV_ERRNO errno
# define ICONV_E2BIG E2BIG
# define ICONV_EINVAL EINVAL
# define ICONV_EILSEQ EILSEQ
#endif
#endif // NVIM_ICONV_H

View File

@ -664,9 +664,6 @@ void getout(int exitval)
ui_call_set_title(cstr_as_string((char *)p_titleold));
}
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
iconv_end();
#endif
cs_end();
if (garbage_collect_at_exit) {
garbage_collect(false);

View File

@ -2062,7 +2062,7 @@ enc_locale_copy_enc:
return enc_canonize((char_u *)buf);
}
# if defined(USE_ICONV)
# if defined(HAVE_ICONV)
/*
@ -2083,13 +2083,6 @@ void * my_iconv_open(char_u *to, char_u *from)
if (iconv_working == kBroken)
return (void *)-1; /* detected a broken iconv() previously */
#ifdef DYNAMIC_ICONV
// Check if the iconv.dll can be found.
if (!iconv_enabled(true)) {
return (void *)-1;
}
#endif
fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
if (fd != (iconv_t)-1 && iconv_working == kUnknown) {
@ -2196,152 +2189,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str,
return result;
}
# if defined(DYNAMIC_ICONV)
// Dynamically load the "iconv.dll" on Win32.
#ifndef DYNAMIC_ICONV // just generating prototypes
# define HINSTANCE int
#endif
static HINSTANCE hIconvDLL = 0;
static HINSTANCE hMsvcrtDLL = 0;
# ifndef DYNAMIC_ICONV_DLL
# define DYNAMIC_ICONV_DLL "iconv.dll"
# define DYNAMIC_ICONV_DLL_ALT "libiconv-2.dll"
# endif
# ifndef DYNAMIC_MSVCRT_DLL
# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
# endif
/*
* Get the address of 'funcname' which is imported by 'hInst' DLL.
*/
static void * get_iconv_import_func(HINSTANCE hInst,
const char *funcname)
{
PBYTE pImage = (PBYTE)hInst;
PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst;
PIMAGE_NT_HEADERS pPE;
PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
PIMAGE_THUNK_DATA pIAT; /* Import Address Table */
PIMAGE_THUNK_DATA pINT; /* Import Name Table */
PIMAGE_IMPORT_BY_NAME pImpName;
if (pDOS->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew);
if (pPE->Signature != IMAGE_NT_SIGNATURE)
return NULL;
pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage
+ pPE->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT]
.VirtualAddress);
for (; pImpDesc->FirstThunk; ++pImpDesc) {
if (!pImpDesc->OriginalFirstThunk)
continue;
pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk);
pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk);
for (; pIAT->u1.Function; ++pIAT, ++pINT) {
if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal))
continue;
pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage
+ (UINT_PTR)(pINT->u1.AddressOfData));
if (strcmp(pImpName->Name, funcname) == 0)
return (void *)pIAT->u1.Function;
}
}
return NULL;
}
// Load library "name".
HINSTANCE vimLoadLib(char *name)
{
HINSTANCE dll = NULL;
// NOTE: Do not use mch_dirname() and mch_chdir() here, they may call
// vimLoadLib() recursively, which causes a stack overflow.
wchar_t old_dirw[MAXPATHL];
// Path to exe dir.
char *buf = xstrdup((char *)get_vim_var_str(VV_PROGPATH));
// ptrdiff_t len = ;
// assert(len > 0);
buf[path_tail_with_sep(buf) - buf] = '\0';
if (GetCurrentDirectoryW(MAXPATHL, old_dirw) != 0) {
// Change directory to where the executable is, both to make
// sure we find a .dll there and to avoid looking for a .dll
// in the current directory.
SetCurrentDirectory((LPCSTR)buf);
// TODO(justinmk): use uv_dlopen instead. see os_libcall
dll = LoadLibrary(name);
SetCurrentDirectoryW(old_dirw);
}
return dll;
}
/*
* Try opening the iconv.dll and return TRUE if iconv() can be used.
*/
bool iconv_enabled(bool verbose)
{
if (hIconvDLL != 0 && hMsvcrtDLL != 0)
return true;
hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL);
if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */
hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT);
if (hIconvDLL != 0)
hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL);
if (hIconvDLL == 0 || hMsvcrtDLL == 0) {
/* Only give the message when 'verbose' is set, otherwise it might be
* done whenever a conversion is attempted. */
if (verbose && p_verbose > 0) {
verbose_enter();
EMSG2(_(e_loadlib),
hIconvDLL == 0 ? DYNAMIC_ICONV_DLL : DYNAMIC_MSVCRT_DLL);
verbose_leave();
}
iconv_end();
return false;
}
iconv = (void *)GetProcAddress(hIconvDLL, "libiconv");
iconv_open = (void *)GetProcAddress(hIconvDLL, "libiconv_open");
iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close");
iconvctl = (void *)GetProcAddress(hIconvDLL, "libiconvctl");
iconv_errno = get_iconv_import_func(hIconvDLL, "_errno");
if (iconv_errno == NULL)
iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno");
if (iconv == NULL || iconv_open == NULL || iconv_close == NULL
|| iconvctl == NULL || iconv_errno == NULL) {
iconv_end();
if (verbose && p_verbose > 0) {
verbose_enter();
EMSG2(_(e_loadfunc), "for libiconv");
verbose_leave();
}
return false;
}
return true;
}
void iconv_end(void)
{
if (hIconvDLL != 0) {
// TODO(justinmk): use uv_dlclose instead.
FreeLibrary(hIconvDLL);
}
if (hMsvcrtDLL != 0) {
FreeLibrary(hMsvcrtDLL);
}
hIconvDLL = 0;
hMsvcrtDLL = 0;
}
# endif /* DYNAMIC_ICONV */
# endif /* USE_ICONV */
# endif // HAVE_ICONV
@ -2372,10 +2220,11 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
int from_is_utf8;
int to_is_utf8;
/* Reset to no conversion. */
# ifdef USE_ICONV
if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1)
// Reset to no conversion.
# ifdef HAVE_ICONV
if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) {
iconv_close(vcp->vc_fd);
}
# endif
*vcp = (vimconv_T)MBYTE_NONE_CONV;
@ -2410,9 +2259,9 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
/* Internal utf-8 -> latin9 conversion. */
vcp->vc_type = CONV_TO_LATIN9;
}
# ifdef USE_ICONV
else {
/* Use iconv() for conversion. */
# ifdef HAVE_ICONV
else { // NOLINT(readability/braces)
// Use iconv() for conversion.
vcp->vc_fd = (iconv_t)my_iconv_open(
to_is_utf8 ? (char_u *)"utf-8" : to,
from_is_utf8 ? (char_u *)"utf-8" : from);
@ -2564,8 +2413,8 @@ char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
*lenp = (size_t)(d - retval);
break;
# ifdef USE_ICONV
case CONV_ICONV: /* conversion with vcp->vc_fd */
# ifdef HAVE_ICONV
case CONV_ICONV: // conversion with vcp->vc_fd
retval = iconv_string(vcp, ptr, len, unconvlenp, lenp);
break;
# endif

View File

@ -63,7 +63,7 @@ typedef enum {
typedef struct {
int vc_type; ///< Zero or more ConvFlags.
int vc_factor; ///< Maximal expansion factor.
# ifdef USE_ICONV
# ifdef HAVE_ICONV
iconv_t vc_fd; ///< Value for CONV_ICONV.
# endif
bool vc_fail; ///< What to do with invalid characters: if true, fail,

View File

@ -52,12 +52,8 @@ static char *features[] = {
"-acl",
#endif
#if (defined(HAVE_ICONV_H) && defined(USE_ICONV)) || defined(DYNAMIC_ICONV)
# ifdef DYNAMIC_ICONV
"+iconv/dyn",
# else
#if defined(HAVE_ICONV)
"+iconv",
# endif
#else
"-iconv",
#endif