mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.5057: using gettimeofday() for timeout is very inefficient
Problem: Using gettimeofday() for timeout is very inefficient. Solution: Set a platform dependent timer. (Paul Ollis, closes #10505)
This commit is contained in:
parent
1d97db3d98
commit
6574577cac
94
src/auto/configure
vendored
94
src/auto/configure
vendored
@ -762,7 +762,6 @@ infodir
|
|||||||
docdir
|
docdir
|
||||||
oldincludedir
|
oldincludedir
|
||||||
includedir
|
includedir
|
||||||
runstatedir
|
|
||||||
localstatedir
|
localstatedir
|
||||||
sharedstatedir
|
sharedstatedir
|
||||||
sysconfdir
|
sysconfdir
|
||||||
@ -898,7 +897,6 @@ datadir='${datarootdir}'
|
|||||||
sysconfdir='${prefix}/etc'
|
sysconfdir='${prefix}/etc'
|
||||||
sharedstatedir='${prefix}/com'
|
sharedstatedir='${prefix}/com'
|
||||||
localstatedir='${prefix}/var'
|
localstatedir='${prefix}/var'
|
||||||
runstatedir='${localstatedir}/run'
|
|
||||||
includedir='${prefix}/include'
|
includedir='${prefix}/include'
|
||||||
oldincludedir='/usr/include'
|
oldincludedir='/usr/include'
|
||||||
docdir='${datarootdir}/doc/${PACKAGE}'
|
docdir='${datarootdir}/doc/${PACKAGE}'
|
||||||
@ -1151,15 +1149,6 @@ do
|
|||||||
| -silent | --silent | --silen | --sile | --sil)
|
| -silent | --silent | --silen | --sile | --sil)
|
||||||
silent=yes ;;
|
silent=yes ;;
|
||||||
|
|
||||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
|
||||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
|
||||||
| --run | --ru | --r)
|
|
||||||
ac_prev=runstatedir ;;
|
|
||||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
|
||||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
|
||||||
| --run=* | --ru=* | --r=*)
|
|
||||||
runstatedir=$ac_optarg ;;
|
|
||||||
|
|
||||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||||
ac_prev=sbindir ;;
|
ac_prev=sbindir ;;
|
||||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||||
@ -1297,7 +1286,7 @@ fi
|
|||||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||||
libdir localedir mandir runstatedir
|
libdir localedir mandir
|
||||||
do
|
do
|
||||||
eval ac_val=\$$ac_var
|
eval ac_val=\$$ac_var
|
||||||
# Remove trailing slashes.
|
# Remove trailing slashes.
|
||||||
@ -1450,7 +1439,6 @@ Fine tuning of the installation directories:
|
|||||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
|
||||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||||
--includedir=DIR C header files [PREFIX/include]
|
--includedir=DIR C header files [PREFIX/include]
|
||||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||||
@ -12737,7 +12725,7 @@ else
|
|||||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||||
since some C++ compilers masquerading as C compilers
|
since some C++ compilers masquerading as C compilers
|
||||||
incorrectly reject 9223372036854775807. */
|
incorrectly reject 9223372036854775807. */
|
||||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||||
&& LARGE_OFF_T % 2147483647 == 1)
|
&& LARGE_OFF_T % 2147483647 == 1)
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
@ -12783,7 +12771,7 @@ else
|
|||||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||||
since some C++ compilers masquerading as C compilers
|
since some C++ compilers masquerading as C compilers
|
||||||
incorrectly reject 9223372036854775807. */
|
incorrectly reject 9223372036854775807. */
|
||||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||||
&& LARGE_OFF_T % 2147483647 == 1)
|
&& LARGE_OFF_T % 2147483647 == 1)
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
@ -12807,7 +12795,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||||
since some C++ compilers masquerading as C compilers
|
since some C++ compilers masquerading as C compilers
|
||||||
incorrectly reject 9223372036854775807. */
|
incorrectly reject 9223372036854775807. */
|
||||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||||
&& LARGE_OFF_T % 2147483647 == 1)
|
&& LARGE_OFF_T % 2147483647 == 1)
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
@ -12852,7 +12840,7 @@ else
|
|||||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||||
since some C++ compilers masquerading as C compilers
|
since some C++ compilers masquerading as C compilers
|
||||||
incorrectly reject 9223372036854775807. */
|
incorrectly reject 9223372036854775807. */
|
||||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||||
&& LARGE_OFF_T % 2147483647 == 1)
|
&& LARGE_OFF_T % 2147483647 == 1)
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
@ -12876,7 +12864,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||||
since some C++ compilers masquerading as C compilers
|
since some C++ compilers masquerading as C compilers
|
||||||
incorrectly reject 9223372036854775807. */
|
incorrectly reject 9223372036854775807. */
|
||||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||||
&& LARGE_OFF_T % 2147483647 == 1)
|
&& LARGE_OFF_T % 2147483647 == 1)
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
@ -13080,6 +13068,76 @@ $as_echo "no" >&6; }
|
|||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for timer_create" >&5
|
||||||
|
$as_echo_n "checking for timer_create... " >&6; }
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lrt"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#include<signal.h>
|
||||||
|
#include<time.h>
|
||||||
|
static void set_flag(union sigval) {}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
struct sigevent action = {0};
|
||||||
|
timer_t timer_id;
|
||||||
|
|
||||||
|
action.sigev_notify = SIGEV_THREAD;
|
||||||
|
action.sigev_notify_function = set_flag;
|
||||||
|
timer_create(CLOCK_REALTIME, &action, &timer_id);
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes; with -lrt" >&5
|
||||||
|
$as_echo "yes; with -lrt" >&6; }; $as_echo "#define HAVE_TIMER_CREATE 1" >>confdefs.h
|
||||||
|
|
||||||
|
else
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#include<signal.h>
|
||||||
|
#include<time.h>
|
||||||
|
static void set_flag(union sigval) {}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
struct sigevent action = {0};
|
||||||
|
timer_t timer_id;
|
||||||
|
|
||||||
|
action.sigev_notify = SIGEV_THREAD;
|
||||||
|
action.sigev_notify_function = set_flag;
|
||||||
|
timer_create(CLOCK_REALTIME, &action, &timer_id);
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }; $as_echo "#define HAVE_TIMER_CREATE 1" >>confdefs.h
|
||||||
|
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat() ignores a trailing slash" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat() ignores a trailing slash" >&5
|
||||||
$as_echo_n "checking whether stat() ignores a trailing slash... " >&6; }
|
$as_echo_n "checking whether stat() ignores a trailing slash... " >&6; }
|
||||||
if ${vim_cv_stat_ignores_slash+:} false; then :
|
if ${vim_cv_stat_ignores_slash+:} false; then :
|
||||||
|
@ -231,6 +231,7 @@
|
|||||||
#undef HAVE_UTIME
|
#undef HAVE_UTIME
|
||||||
#undef HAVE_BIND_TEXTDOMAIN_CODESET
|
#undef HAVE_BIND_TEXTDOMAIN_CODESET
|
||||||
#undef HAVE_MBLEN
|
#undef HAVE_MBLEN
|
||||||
|
#undef HAVE_TIMER_CREATE
|
||||||
|
|
||||||
/* Define, if needed, for accessing large files. */
|
/* Define, if needed, for accessing large files. */
|
||||||
#undef _LARGE_FILES
|
#undef _LARGE_FILES
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
dnl configure.ac: autoconf script for Vim
|
dnl configure.ac: autoconf script for Vim
|
||||||
|
|
||||||
dnl Process this file with autoconf 2.12 or 2.13 to produce "configure".
|
dnl Process this file with autoconf 2.69 to produce "configure".
|
||||||
dnl Should also work with autoconf 2.54 and later.
|
dnl This should also work with other versions of autoconf, but 2.70 and later
|
||||||
|
dnl generate lots of hard to fix "obsolete" warnings.
|
||||||
|
|
||||||
AC_INIT(vim.h)
|
AC_INIT(vim.h)
|
||||||
AC_CONFIG_HEADER(auto/config.h:config.h.in)
|
AC_CONFIG_HEADER(auto/config.h:config.h.in)
|
||||||
@ -3812,6 +3813,41 @@ AC_TRY_COMPILE(
|
|||||||
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_ST_BLKSIZE),
|
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_ST_BLKSIZE),
|
||||||
AC_MSG_RESULT(no))
|
AC_MSG_RESULT(no))
|
||||||
|
|
||||||
|
dnl Check for timer_create. It probably requires the 'rt' library.
|
||||||
|
AC_MSG_CHECKING([for timer_create])
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lrt"
|
||||||
|
AC_TRY_LINK([
|
||||||
|
#include<signal.h>
|
||||||
|
#include<time.h>
|
||||||
|
static void set_flag(union sigval) {}
|
||||||
|
], [
|
||||||
|
struct timespec ts;
|
||||||
|
struct sigevent action = {0};
|
||||||
|
timer_t timer_id;
|
||||||
|
|
||||||
|
action.sigev_notify = SIGEV_THREAD;
|
||||||
|
action.sigev_notify_function = set_flag;
|
||||||
|
timer_create(CLOCK_REALTIME, &action, &timer_id);
|
||||||
|
],
|
||||||
|
AC_MSG_RESULT(yes; with -lrt); AC_DEFINE(HAVE_TIMER_CREATE),
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
AC_TRY_LINK([
|
||||||
|
#include<signal.h>
|
||||||
|
#include<time.h>
|
||||||
|
static void set_flag(union sigval) {}
|
||||||
|
], [
|
||||||
|
struct timespec ts;
|
||||||
|
struct sigevent action = {0};
|
||||||
|
timer_t timer_id;
|
||||||
|
|
||||||
|
action.sigev_notify = SIGEV_THREAD;
|
||||||
|
action.sigev_notify_function = set_flag;
|
||||||
|
timer_create(CLOCK_REALTIME, &action, &timer_id);
|
||||||
|
],
|
||||||
|
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_TIMER_CREATE),
|
||||||
|
AC_MSG_RESULT(no)))
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether stat() ignores a trailing slash], [vim_cv_stat_ignores_slash],
|
AC_CACHE_CHECK([whether stat() ignores a trailing slash], [vim_cv_stat_ignores_slash],
|
||||||
[
|
[
|
||||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||||
|
@ -1474,9 +1474,6 @@ win_update(win_T *wp)
|
|||||||
#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
|
#if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA)
|
||||||
int save_got_int;
|
int save_got_int;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SYN_TIME_LIMIT
|
|
||||||
proftime_T syntax_tm;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
|
#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
|
||||||
// This needs to be done only for the first window when update_screen() is
|
// This needs to be done only for the first window when update_screen() is
|
||||||
@ -2182,8 +2179,7 @@ win_update(win_T *wp)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef SYN_TIME_LIMIT
|
#ifdef SYN_TIME_LIMIT
|
||||||
// Set the time limit to 'redrawtime'.
|
// Set the time limit to 'redrawtime'.
|
||||||
profile_setlimit(p_rdt, &syntax_tm);
|
init_regexp_timeout(p_rdt);
|
||||||
syn_set_timeout(&syntax_tm);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
win_foldinfo.fi_level = 0;
|
win_foldinfo.fi_level = 0;
|
||||||
@ -2695,7 +2691,7 @@ win_update(win_T *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYN_TIME_LIMIT
|
#ifdef SYN_TIME_LIMIT
|
||||||
syn_set_timeout(NULL);
|
disable_regexp_timeout();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reset the type of redrawing required, the window has been updated.
|
// Reset the type of redrawing required, the window has been updated.
|
||||||
|
12
src/errors.h
12
src/errors.h
@ -3288,3 +3288,15 @@ EXTERN char e_bitshift_ops_must_be_postive[]
|
|||||||
EXTERN char e_argument_1_list_item_nr_dictionary_required[]
|
EXTERN char e_argument_1_list_item_nr_dictionary_required[]
|
||||||
INIT(= N_("E1284: Argument 1, list item %d: Dictionary required"));
|
INIT(= N_("E1284: Argument 1, list item %d: Dictionary required"));
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
EXTERN char e_could_not_clear_timeout_str[]
|
||||||
|
INIT(= N_("E1285: Could not clear timeout: %s"));
|
||||||
|
EXTERN char e_could_not_set_timeout_str[]
|
||||||
|
INIT(= N_("E1286: Could not set timeout: %s"));
|
||||||
|
EXTERN char e_could_not_set_handler_for_timeout_str[]
|
||||||
|
INIT(= N_("E1287: Could not set handler for timeout: %s"));
|
||||||
|
EXTERN char e_could_not_reset_handler_for_timeout_str[]
|
||||||
|
INIT(= N_("E1288: Could not reset handler for timeout: %s"));
|
||||||
|
EXTERN char e_could_not_check_for_pending_sigalrm_str[]
|
||||||
|
INIT(= N_("E1289: Could not check for pending SIGALRM: %s"));
|
||||||
|
#endif
|
||||||
|
@ -8439,7 +8439,6 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
|||||||
int retval = 0; // default: FAIL
|
int retval = 0; // default: FAIL
|
||||||
long lnum_stop = 0;
|
long lnum_stop = 0;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
proftime_T tm;
|
|
||||||
long time_limit = 0;
|
long time_limit = 0;
|
||||||
#endif
|
#endif
|
||||||
int options = SEARCH_KEEP;
|
int options = SEARCH_KEEP;
|
||||||
@ -8486,11 +8485,6 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
// Set the time limit, if there is one.
|
|
||||||
profile_setlimit(time_limit, &tm);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function does not accept SP_REPEAT and SP_RETCOUNT flags.
|
* This function does not accept SP_REPEAT and SP_RETCOUNT flags.
|
||||||
* Check to make sure only those flags are set.
|
* Check to make sure only those flags are set.
|
||||||
@ -8509,7 +8503,7 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
|||||||
CLEAR_FIELD(sia);
|
CLEAR_FIELD(sia);
|
||||||
sia.sa_stop_lnum = (linenr_T)lnum_stop;
|
sia.sa_stop_lnum = (linenr_T)lnum_stop;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
sia.sa_tm = &tm;
|
sia.sa_tm = time_limit;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Repeat until {skip} returns FALSE.
|
// Repeat until {skip} returns FALSE.
|
||||||
@ -8955,19 +8949,11 @@ do_searchpair(
|
|||||||
int use_skip = FALSE;
|
int use_skip = FALSE;
|
||||||
int err;
|
int err;
|
||||||
int options = SEARCH_KEEP;
|
int options = SEARCH_KEEP;
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
proftime_T tm;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Make 'cpoptions' empty, the 'l' flag should not be used here.
|
// Make 'cpoptions' empty, the 'l' flag should not be used here.
|
||||||
save_cpo = p_cpo;
|
save_cpo = p_cpo;
|
||||||
p_cpo = empty_option;
|
p_cpo = empty_option;
|
||||||
|
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
// Set the time limit, if there is one.
|
|
||||||
profile_setlimit(time_limit, &tm);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Make two search patterns: start/end (pat2, for in nested pairs) and
|
// Make two search patterns: start/end (pat2, for in nested pairs) and
|
||||||
// start/middle/end (pat3, for the top pair).
|
// start/middle/end (pat3, for the top pair).
|
||||||
pat2 = alloc(STRLEN(spat) + STRLEN(epat) + 17);
|
pat2 = alloc(STRLEN(spat) + STRLEN(epat) + 17);
|
||||||
@ -8998,7 +8984,7 @@ do_searchpair(
|
|||||||
CLEAR_FIELD(sia);
|
CLEAR_FIELD(sia);
|
||||||
sia.sa_stop_lnum = lnum_stop;
|
sia.sa_stop_lnum = lnum_stop;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
sia.sa_tm = &tm;
|
sia.sa_tm = time_limit;
|
||||||
#endif
|
#endif
|
||||||
n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
|
n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
|
||||||
options, RE_SEARCH, &sia);
|
options, RE_SEARCH, &sia);
|
||||||
|
@ -4006,7 +4006,7 @@ ex_substitute(exarg_T *eap)
|
|||||||
); ++lnum)
|
); ++lnum)
|
||||||
{
|
{
|
||||||
nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||||
(colnr_T)0, NULL, NULL);
|
(colnr_T)0, NULL);
|
||||||
if (nmatch)
|
if (nmatch)
|
||||||
{
|
{
|
||||||
colnr_T copycol;
|
colnr_T copycol;
|
||||||
@ -4663,7 +4663,7 @@ skip:
|
|||||||
|| nmatch_tl > 0
|
|| nmatch_tl > 0
|
||||||
|| (nmatch = vim_regexec_multi(®match, curwin,
|
|| (nmatch = vim_regexec_multi(®match, curwin,
|
||||||
curbuf, sub_firstlnum,
|
curbuf, sub_firstlnum,
|
||||||
matchcol, NULL, NULL)) == 0
|
matchcol, NULL)) == 0
|
||||||
|| regmatch.startpos[0].lnum > 0)
|
|| regmatch.startpos[0].lnum > 0)
|
||||||
{
|
{
|
||||||
if (new_start != NULL)
|
if (new_start != NULL)
|
||||||
@ -4728,7 +4728,7 @@ skip:
|
|||||||
}
|
}
|
||||||
if (nmatch == -1 && !lastone)
|
if (nmatch == -1 && !lastone)
|
||||||
nmatch = vim_regexec_multi(®match, curwin, curbuf,
|
nmatch = vim_regexec_multi(®match, curwin, curbuf,
|
||||||
sub_firstlnum, matchcol, NULL, NULL);
|
sub_firstlnum, matchcol, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 5. break if there isn't another match in this line
|
* 5. break if there isn't another match in this line
|
||||||
@ -4992,7 +4992,7 @@ ex_global(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
lnum = curwin->w_cursor.lnum;
|
lnum = curwin->w_cursor.lnum;
|
||||||
match = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
match = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||||
(colnr_T)0, NULL, NULL);
|
(colnr_T)0, NULL);
|
||||||
if ((type == 'g' && match) || (type == 'v' && !match))
|
if ((type == 'g' && match) || (type == 'v' && !match))
|
||||||
global_exe_one(cmd, lnum);
|
global_exe_one(cmd, lnum);
|
||||||
}
|
}
|
||||||
@ -5005,7 +5005,7 @@ ex_global(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
// a match on this line?
|
// a match on this line?
|
||||||
match = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
match = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||||
(colnr_T)0, NULL, NULL);
|
(colnr_T)0, NULL);
|
||||||
if (regmatch.regprog == NULL)
|
if (regmatch.regprog == NULL)
|
||||||
break; // re-compiling regprog failed
|
break; // re-compiling regprog failed
|
||||||
if ((type == 'g' && match) || (type == 'v' && !match))
|
if ((type == 'g' && match) || (type == 'v' && !match))
|
||||||
|
@ -417,7 +417,6 @@ may_do_incsearch_highlighting(
|
|||||||
int found; // do_search() result
|
int found; // do_search() result
|
||||||
pos_T end_pos;
|
pos_T end_pos;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
proftime_T tm;
|
|
||||||
searchit_arg_T sia;
|
searchit_arg_T sia;
|
||||||
#endif
|
#endif
|
||||||
int next_char;
|
int next_char;
|
||||||
@ -484,10 +483,6 @@ may_do_incsearch_highlighting(
|
|||||||
cursor_off(); // so the user knows we're busy
|
cursor_off(); // so the user knows we're busy
|
||||||
out_flush();
|
out_flush();
|
||||||
++emsg_off; // so it doesn't beep if bad expr
|
++emsg_off; // so it doesn't beep if bad expr
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
// Set the time limit to half a second.
|
|
||||||
profile_setlimit(500L, &tm);
|
|
||||||
#endif
|
|
||||||
if (!p_hls)
|
if (!p_hls)
|
||||||
search_flags += SEARCH_KEEP;
|
search_flags += SEARCH_KEEP;
|
||||||
if (search_first_line != 0)
|
if (search_first_line != 0)
|
||||||
@ -495,7 +490,8 @@ may_do_incsearch_highlighting(
|
|||||||
ccline.cmdbuff[skiplen + patlen] = NUL;
|
ccline.cmdbuff[skiplen + patlen] = NUL;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
CLEAR_FIELD(sia);
|
CLEAR_FIELD(sia);
|
||||||
sia.sa_tm = &tm;
|
// Set the time limit to half a second.
|
||||||
|
sia.sa_tm = 500;
|
||||||
#endif
|
#endif
|
||||||
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
|
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
|
||||||
ccline.cmdbuff + skiplen, count, search_flags,
|
ccline.cmdbuff + skiplen, count, search_flags,
|
||||||
|
16
src/match.c
16
src/match.c
@ -330,10 +330,6 @@ init_search_hl(win_T *wp, match_T *search_hl)
|
|||||||
cur->hl.buf = wp->w_buffer;
|
cur->hl.buf = wp->w_buffer;
|
||||||
cur->hl.lnum = 0;
|
cur->hl.lnum = 0;
|
||||||
cur->hl.first_lnum = 0;
|
cur->hl.first_lnum = 0;
|
||||||
# ifdef FEAT_RELTIME
|
|
||||||
// Set the time limit to 'redrawtime'.
|
|
||||||
profile_setlimit(p_rdt, &(cur->hl.tm));
|
|
||||||
# endif
|
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
search_hl->buf = wp->w_buffer;
|
search_hl->buf = wp->w_buffer;
|
||||||
@ -424,6 +420,7 @@ next_search_hl(
|
|||||||
colnr_T matchcol;
|
colnr_T matchcol;
|
||||||
long nmatched;
|
long nmatched;
|
||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
|
int timed_out = FALSE;
|
||||||
|
|
||||||
// for :{range}s/pat only highlight inside the range
|
// for :{range}s/pat only highlight inside the range
|
||||||
if ((lnum < search_first_line || lnum > search_last_line) && cur == NULL)
|
if ((lnum < search_first_line || lnum > search_last_line) && cur == NULL)
|
||||||
@ -451,7 +448,7 @@ next_search_hl(
|
|||||||
{
|
{
|
||||||
# ifdef FEAT_RELTIME
|
# ifdef FEAT_RELTIME
|
||||||
// Stop searching after passing the time limit.
|
// Stop searching after passing the time limit.
|
||||||
if (profile_passed_limit(&(shl->tm)))
|
if (timed_out)
|
||||||
{
|
{
|
||||||
shl->lnum = 0; // no match found in time
|
shl->lnum = 0; // no match found in time
|
||||||
break;
|
break;
|
||||||
@ -494,16 +491,9 @@ next_search_hl(
|
|||||||
int regprog_is_copy = (shl != search_hl && cur != NULL
|
int regprog_is_copy = (shl != search_hl && cur != NULL
|
||||||
&& shl == &cur->hl
|
&& shl == &cur->hl
|
||||||
&& cur->match.regprog == cur->hl.rm.regprog);
|
&& cur->match.regprog == cur->hl.rm.regprog);
|
||||||
int timed_out = FALSE;
|
|
||||||
|
|
||||||
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
|
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
|
||||||
matchcol,
|
matchcol, &timed_out);
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
&(shl->tm), &timed_out
|
|
||||||
#else
|
|
||||||
NULL, NULL
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
// Copy the regprog, in case it got freed and recompiled.
|
// Copy the regprog, in case it got freed and recompiled.
|
||||||
if (regprog_is_copy)
|
if (regprog_is_copy)
|
||||||
cur->match.regprog = cur->hl.rm.regprog;
|
cur->match.regprog = cur->hl.rm.regprog;
|
||||||
|
52
src/os_mac.h
52
src/os_mac.h
@ -6,6 +6,9 @@
|
|||||||
* Do ":help credits" in Vim to see a list of people who contributed.
|
* Do ":help credits" in Vim to see a list of people who contributed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef OS_MAC__H
|
||||||
|
#define OS_MAC__H
|
||||||
|
|
||||||
// Before Including the MacOS specific files,
|
// Before Including the MacOS specific files,
|
||||||
// let's set the OPAQUE_TOOLBOX_STRUCTS to 0 so we
|
// let's set the OPAQUE_TOOLBOX_STRUCTS to 0 so we
|
||||||
// can access the internal structures.
|
// can access the internal structures.
|
||||||
@ -266,3 +269,52 @@
|
|||||||
|
|
||||||
// A Mac constant causing big problem to syntax highlighting
|
// A Mac constant causing big problem to syntax highlighting
|
||||||
#define UNKNOWN_CREATOR '\?\?\?\?'
|
#define UNKNOWN_CREATOR '\?\?\?\?'
|
||||||
|
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
|
||||||
|
# include <dispatch/dispatch.h>
|
||||||
|
|
||||||
|
# if !defined(MAC_OS_X_VERSION_10_12) || \
|
||||||
|
(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12)
|
||||||
|
typedef int clockid_t;
|
||||||
|
# endif
|
||||||
|
# ifndef CLOCK_REALTIME
|
||||||
|
# define CLOCK_REALTIME 0
|
||||||
|
# endif
|
||||||
|
# ifndef CLOCK_MONOTONIC
|
||||||
|
# define CLOCK_MONOTONIC 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
struct itimerspec
|
||||||
|
{
|
||||||
|
struct timespec it_interval; // timer period
|
||||||
|
struct timespec it_value; // initial expiration
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sigevent;
|
||||||
|
|
||||||
|
struct macos_timer
|
||||||
|
{
|
||||||
|
dispatch_queue_t tim_queue;
|
||||||
|
dispatch_source_t tim_timer;
|
||||||
|
void (*tim_func)(union sigval);
|
||||||
|
void *tim_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct macos_timer *timer_t;
|
||||||
|
|
||||||
|
extern int timer_create(
|
||||||
|
clockid_t clockid,
|
||||||
|
struct sigevent *sevp,
|
||||||
|
timer_t *timerid);
|
||||||
|
|
||||||
|
extern int timer_delete(timer_t timerid);
|
||||||
|
|
||||||
|
extern int timer_settime(
|
||||||
|
timer_t timerid, int flags,
|
||||||
|
const struct itimerspec *new_value,
|
||||||
|
struct itimerspec *unused);
|
||||||
|
|
||||||
|
#endif // FEAT_RELTIME
|
||||||
|
|
||||||
|
#endif // OS_MAC__H
|
||||||
|
176
src/os_macosx.m
176
src/os_macosx.m
@ -23,6 +23,13 @@
|
|||||||
* X11 header files. */
|
* X11 header files. */
|
||||||
#define NO_X11_INCLUDES
|
#define NO_X11_INCLUDES
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <mach/boolean.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
|
||||||
#include "vim.h"
|
#include "vim.h"
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
@ -208,6 +215,175 @@ releasepool:
|
|||||||
|
|
||||||
#endif /* FEAT_CLIPBOARD */
|
#endif /* FEAT_CLIPBOARD */
|
||||||
|
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
/*
|
||||||
|
* The following timer code is based on a Gist by Jorgen Lundman:
|
||||||
|
*
|
||||||
|
* https://gist.github.com/lundman
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct macos_timer macos_timer_T;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_timer_cancel(void *arg UNUSED)
|
||||||
|
{
|
||||||
|
// This is not currently used, but it might be useful in the future and
|
||||||
|
// it is non-trivial enough to provide as usable implementation.
|
||||||
|
# if 0
|
||||||
|
macos_timer_T *timerid = (macos_timer_T *)arg;
|
||||||
|
|
||||||
|
dispatch_release(timerid->tim_timer);
|
||||||
|
dispatch_release(timerid->tim_queue);
|
||||||
|
timerid->tim_timer = NULL;
|
||||||
|
timerid->tim_queue = NULL;
|
||||||
|
free(timerid);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_timer_handler(void *arg)
|
||||||
|
{
|
||||||
|
macos_timer_T *timerid = (macos_timer_T *)arg;
|
||||||
|
union sigval sv;
|
||||||
|
|
||||||
|
sv.sival_ptr = timerid->tim_arg;
|
||||||
|
|
||||||
|
if (timerid->tim_func != NULL)
|
||||||
|
timerid->tim_func(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
itime_to_ns(const struct timespec *it)
|
||||||
|
{
|
||||||
|
time_t sec = it->tv_sec;
|
||||||
|
long nsec = it->tv_nsec;
|
||||||
|
uint64_t ns = NSEC_PER_SEC * sec + nsec;
|
||||||
|
|
||||||
|
return ns == 0 ? DISPATCH_TIME_FOREVER : ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A partial emulation of the POSIX timer_create function.
|
||||||
|
*
|
||||||
|
* The limitations and differences include:
|
||||||
|
*
|
||||||
|
* - Only CLOCK_REALTIME and CLOCK_MONOTONIC are supported as clockid
|
||||||
|
* values.
|
||||||
|
* - Even if CLOCK_REALTIME is specified, internally the mach_absolute_time
|
||||||
|
* source is used internally.
|
||||||
|
* - The only notification method supported is SIGEV_THREAD.
|
||||||
|
*/
|
||||||
|
inline int
|
||||||
|
timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid)
|
||||||
|
{
|
||||||
|
macos_timer_T *timer = NULL;
|
||||||
|
|
||||||
|
// We only support real time and monotonic clocks; and SIGEV_THREAD
|
||||||
|
// notification. In practice, there is no difference between the two
|
||||||
|
// types of clocks on MacOS - we always use the mach_machine_time
|
||||||
|
// source.
|
||||||
|
if ( (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
|
||||||
|
|| sevp->sigev_notify != SIGEV_THREAD)
|
||||||
|
{
|
||||||
|
semsg("clockid: %d %d", clockid, CLOCK_REALTIME);
|
||||||
|
semsg("notify: %d %d", sevp->sigev_notify, SIGEV_THREAD);
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = (macos_timer_T *)malloc(sizeof(macos_timer_T));
|
||||||
|
if (timer == NULL)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*timerid = timer;
|
||||||
|
|
||||||
|
timer->tim_queue = dispatch_queue_create(
|
||||||
|
"org.vim.timerqueue", NULL);
|
||||||
|
if (timer->tim_queue == NULL)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer->tim_timer = dispatch_source_create(
|
||||||
|
DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timer->tim_queue);
|
||||||
|
if (timer->tim_timer == NULL)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer->tim_func = sevp->sigev_notify_function;
|
||||||
|
timer->tim_arg = sevp->sigev_value.sival_ptr;
|
||||||
|
|
||||||
|
dispatch_set_context(timer->tim_timer, timer);
|
||||||
|
dispatch_source_set_event_handler_f(timer->tim_timer, _timer_handler);
|
||||||
|
dispatch_source_set_cancel_handler_f(timer->tim_timer, _timer_cancel);
|
||||||
|
|
||||||
|
dispatch_resume(timer->tim_timer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A partial emulation of the POSIX timer_settime function.
|
||||||
|
*
|
||||||
|
* The limitations and differences include:
|
||||||
|
*
|
||||||
|
* - The flags argument is ignored. The supplied new_value is therfore
|
||||||
|
* always treated as a relative time.
|
||||||
|
* - The old_value argument is ignored.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
timer_settime(
|
||||||
|
timer_t timerid,
|
||||||
|
int unused_flags UNUSED,
|
||||||
|
const struct itimerspec *new_value,
|
||||||
|
struct itimerspec *old_value UNUSED)
|
||||||
|
{
|
||||||
|
uint64_t first_shot = itime_to_ns(&new_value->it_value);
|
||||||
|
|
||||||
|
if (timerid == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (first_shot == DISPATCH_TIME_FOREVER)
|
||||||
|
{
|
||||||
|
dispatch_source_set_timer(
|
||||||
|
timerid->tim_timer, first_shot, first_shot, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t interval = itime_to_ns(&new_value->it_interval);
|
||||||
|
|
||||||
|
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, first_shot);
|
||||||
|
dispatch_source_set_timer(timerid->tim_timer, start, interval, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An emulation of the POSIX timer_delete function.
|
||||||
|
*
|
||||||
|
* Disabled because it is not currently used, but an implemented provided
|
||||||
|
* for completeness and possible future use.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
int
|
||||||
|
timer_delete(timer_t timerid)
|
||||||
|
{
|
||||||
|
/* Calls _timer_cancel() */
|
||||||
|
if (timerid != NULL)
|
||||||
|
dispatch_source_cancel(timerid->tim_timer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FEAT_RELTIME */
|
||||||
|
|
||||||
/* Lift the compiler warning suppression. */
|
/* Lift the compiler warning suppression. */
|
||||||
#if defined(__clang__) && defined(__STRICT_ANSI__)
|
#if defined(__clang__) && defined(__STRICT_ANSI__)
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
|
214
src/os_unix.c
214
src/os_unix.c
@ -8256,3 +8256,217 @@ xsmp_close(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_XSMP
|
#endif // USE_XSMP
|
||||||
|
|
||||||
|
#if defined(FEAT_RELTIME) || defined(PROTO)
|
||||||
|
# if defined(HAVE_TIMER_CREATE) || defined(MACOS_X)
|
||||||
|
/*
|
||||||
|
* Implement timeout with timer_create() and timer_settime().
|
||||||
|
*/
|
||||||
|
static int timeout_flag = FALSE;
|
||||||
|
static timer_t timer_id;
|
||||||
|
static int timer_created = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback for when the timer expires.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_flag(union sigval _unused UNUSED)
|
||||||
|
{
|
||||||
|
timeout_flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop any active timeout.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
stop_timeout(void)
|
||||||
|
{
|
||||||
|
static struct itimerspec disarm = {{0, 0}, {0, 0}};
|
||||||
|
|
||||||
|
if (timer_created)
|
||||||
|
{
|
||||||
|
int ret = timer_settime(timer_id, 0, &disarm, NULL);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
semsg(_(e_could_not_clear_timeout_str), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the current timeout flag; any previous timeout should be
|
||||||
|
// considered _not_ triggered.
|
||||||
|
timeout_flag = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timeout timer.
|
||||||
|
*
|
||||||
|
* The return value is a pointer to a flag that is initialised to FALSE. If the
|
||||||
|
* timeout expires, the flag is set to TRUE. This will only return pointers to
|
||||||
|
* static memory; i.e. any pointer returned by this function may always be
|
||||||
|
* safely dereferenced.
|
||||||
|
*
|
||||||
|
* This function is not expected to fail, but if it does it will still return a
|
||||||
|
* valid flag pointer; the flag will remain stuck as FALSE .
|
||||||
|
*/
|
||||||
|
const int *
|
||||||
|
start_timeout(long msec)
|
||||||
|
{
|
||||||
|
struct itimerspec interval = {
|
||||||
|
{0, 0}, // Do not repeat.
|
||||||
|
{msec / 1000, (msec % 1000) * 1000000}}; // Timeout interval
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// This is really the caller's responsibility, but let's make sure the
|
||||||
|
// previous timer has been stopped.
|
||||||
|
stop_timeout();
|
||||||
|
timeout_flag = FALSE;
|
||||||
|
|
||||||
|
if (!timer_created)
|
||||||
|
{
|
||||||
|
struct sigevent action = {0};
|
||||||
|
|
||||||
|
action.sigev_notify = SIGEV_THREAD;
|
||||||
|
action.sigev_notify_function = set_flag;
|
||||||
|
ret = timer_create(CLOCK_MONOTONIC, &action, &timer_id);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
semsg(_(e_could_not_set_timeout_str), strerror(errno));
|
||||||
|
return &timeout_flag;
|
||||||
|
}
|
||||||
|
timer_created = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = timer_settime(timer_id, 0, &interval, NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
semsg(_(e_could_not_set_timeout_str), strerror(errno));
|
||||||
|
|
||||||
|
return &timeout_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement timeout with setitimer()
|
||||||
|
*/
|
||||||
|
static struct itimerval prev_interval;
|
||||||
|
static struct sigaction prev_sigaction;
|
||||||
|
static int timeout_flag = FALSE;
|
||||||
|
static int timer_active = FALSE;
|
||||||
|
static int timer_handler_active = FALSE;
|
||||||
|
static int alarm_pending = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle SIGALRM for a timeout.
|
||||||
|
*/
|
||||||
|
static RETSIGTYPE
|
||||||
|
set_flag SIGDEFARG(sigarg)
|
||||||
|
{
|
||||||
|
if (alarm_pending)
|
||||||
|
alarm_pending = FALSE;
|
||||||
|
else
|
||||||
|
timeout_flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop any active timeout.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
stop_timeout(void)
|
||||||
|
{
|
||||||
|
static struct itimerval disarm = {{0, 0}, {0, 0}};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (timer_active)
|
||||||
|
{
|
||||||
|
timer_active = FALSE;
|
||||||
|
ret = setitimer(ITIMER_REAL, &disarm, &prev_interval);
|
||||||
|
if (ret < 0)
|
||||||
|
// Should only get here as a result of coding errors.
|
||||||
|
semsg(_(e_could_not_clear_timeout_str), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer_handler_active)
|
||||||
|
{
|
||||||
|
timer_handler_active = FALSE;
|
||||||
|
ret = sigaction(SIGALRM, &prev_sigaction, NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
// Should only get here as a result of coding errors.
|
||||||
|
semsg(_(e_could_not_reset_handler_for_timeout_str),
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
timeout_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timeout timer.
|
||||||
|
*
|
||||||
|
* The return value is a pointer to a flag that is initialised to FALSE. If the
|
||||||
|
* timeout expires, the flag is set to TRUE. This will only return pointers to
|
||||||
|
* static memory; i.e. any pointer returned by this function may always be
|
||||||
|
* safely dereferenced.
|
||||||
|
*
|
||||||
|
* This function is not expected to fail, but if it does it will still return a
|
||||||
|
* valid flag pointer; the flag will remain stuck as FALSE .
|
||||||
|
*/
|
||||||
|
const int *
|
||||||
|
start_timeout(long msec)
|
||||||
|
{
|
||||||
|
struct itimerval interval = {
|
||||||
|
{0, 0}, // Do not repeat.
|
||||||
|
{msec / 1000, (msec % 1000) * 1000}}; // Timeout interval
|
||||||
|
struct sigaction handle_alarm;
|
||||||
|
int ret;
|
||||||
|
sigset_t sigs;
|
||||||
|
sigset_t saved_sigs;
|
||||||
|
|
||||||
|
// This is really the caller's responsibility, but let's make sure the
|
||||||
|
// previous timer has been stopped.
|
||||||
|
stop_timeout();
|
||||||
|
|
||||||
|
// There is a small chance that SIGALRM is pending and so the handler must
|
||||||
|
// ignore it on the first call.
|
||||||
|
alarm_pending = FALSE;
|
||||||
|
ret = sigemptyset(&sigs);
|
||||||
|
ret = ret == 0 ? sigaddset(&sigs, SIGALRM) : ret;
|
||||||
|
ret = ret == 0 ? sigprocmask(SIG_BLOCK, &sigs, &saved_sigs) : ret;
|
||||||
|
timeout_flag = FALSE;
|
||||||
|
ret = ret == 0 ? sigpending(&sigs) : ret;
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
alarm_pending = sigismember(&sigs, SIGALRM);
|
||||||
|
ret = ret == 0 ? sigprocmask(SIG_SETMASK, &saved_sigs, NULL) : ret;
|
||||||
|
}
|
||||||
|
if (unlikely(ret != 0 || alarm_pending < 0))
|
||||||
|
{
|
||||||
|
// Just catching coding errors. Write an error message, but carry on.
|
||||||
|
semsg(_(e_could_not_check_for_pending_sigalrm_str), strerror(errno));
|
||||||
|
alarm_pending = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the alarm handler first.
|
||||||
|
ret = sigemptyset(&handle_alarm.sa_mask);
|
||||||
|
handle_alarm.sa_handler = set_flag;
|
||||||
|
handle_alarm.sa_flags = 0;
|
||||||
|
ret = ret == 0 ? sigaction(SIGALRM, &handle_alarm, &prev_sigaction) : ret;
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
// Should only get here as a result of coding errors.
|
||||||
|
semsg(_(e_could_not_set_handler_for_timeout_str), strerror(errno));
|
||||||
|
return &timeout_flag;
|
||||||
|
}
|
||||||
|
timer_handler_active = TRUE;
|
||||||
|
|
||||||
|
// Set up the interval timer once the alarm handler is in place.
|
||||||
|
ret = setitimer(ITIMER_REAL, &interval, &prev_interval);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
// Should only get here as a result of coding errors.
|
||||||
|
semsg(_(e_could_not_set_timeout_str), strerror(errno));
|
||||||
|
stop_timeout();
|
||||||
|
return &timeout_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_active = TRUE;
|
||||||
|
return &timeout_flag;
|
||||||
|
}
|
||||||
|
# endif // HAVE_TIMER_CREATE
|
||||||
|
#endif // FEAT_RELTIME
|
||||||
|
@ -100,6 +100,8 @@ typedef char * LPCSTR;
|
|||||||
typedef char * LPWSTR;
|
typedef char * LPWSTR;
|
||||||
typedef int ACCESS_MASK;
|
typedef int ACCESS_MASK;
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
|
typedef int BOOLEAN;
|
||||||
|
typedef int CALLBACK;
|
||||||
typedef int COLORREF;
|
typedef int COLORREF;
|
||||||
typedef int CONSOLE_CURSOR_INFO;
|
typedef int CONSOLE_CURSOR_INFO;
|
||||||
typedef int COORD;
|
typedef int COORD;
|
||||||
@ -7327,6 +7329,7 @@ typedef struct _FILE_EA_INFORMATION_ {
|
|||||||
ULONG EaSize;
|
ULONG EaSize;
|
||||||
} FILE_EA_INFORMATION_, *PFILE_EA_INFORMATION_;
|
} FILE_EA_INFORMATION_, *PFILE_EA_INFORMATION_;
|
||||||
|
|
||||||
|
#ifndef PROTO
|
||||||
typedef NTSTATUS (NTAPI *PfnNtOpenFile)(
|
typedef NTSTATUS (NTAPI *PfnNtOpenFile)(
|
||||||
PHANDLE FileHandle,
|
PHANDLE FileHandle,
|
||||||
ACCESS_MASK DesiredAccess,
|
ACCESS_MASK DesiredAccess,
|
||||||
@ -7367,6 +7370,7 @@ PfnNtSetEaFile pNtSetEaFile = NULL;
|
|||||||
PfnNtQueryEaFile pNtQueryEaFile = NULL;
|
PfnNtQueryEaFile pNtQueryEaFile = NULL;
|
||||||
PfnNtQueryInformationFile pNtQueryInformationFile = NULL;
|
PfnNtQueryInformationFile pNtQueryInformationFile = NULL;
|
||||||
PfnRtlInitUnicodeString pRtlInitUnicodeString = NULL;
|
PfnRtlInitUnicodeString pRtlInitUnicodeString = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load ntdll.dll functions.
|
* Load ntdll.dll functions.
|
||||||
@ -8315,3 +8319,85 @@ GetWin32Error(void)
|
|||||||
}
|
}
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_RELTIME) || defined(PROTO)
|
||||||
|
static HANDLE timer_handle;
|
||||||
|
static int timer_active = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calls to start_timeout alternate the return value pointer between the two
|
||||||
|
* entries in timeout_flags. If the previously active timeout is very close to
|
||||||
|
* expiring when start_timeout() is called then a race condition means that the
|
||||||
|
* set_flag() function may still be invoked after the previous timer is
|
||||||
|
* deleted. Ping-ponging between the two flags prevents this causing 'fake'
|
||||||
|
* timeouts.
|
||||||
|
*/
|
||||||
|
static int timeout_flags[2];
|
||||||
|
static int flag_idx = 0;
|
||||||
|
static int *timeout_flag = &timeout_flags[0];
|
||||||
|
|
||||||
|
|
||||||
|
static void CALLBACK
|
||||||
|
set_flag(void *param, BOOLEAN unused2)
|
||||||
|
{
|
||||||
|
int *timeout_flag = (int *)param;
|
||||||
|
|
||||||
|
*timeout_flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop any active timeout.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
stop_timeout(void)
|
||||||
|
{
|
||||||
|
if (timer_active)
|
||||||
|
{
|
||||||
|
BOOL ret = DeleteTimerQueueTimer(NULL, timer_handle, NULL);
|
||||||
|
timer_active = FALSE;
|
||||||
|
if (!ret && GetLastError() != ERROR_IO_PENDING)
|
||||||
|
{
|
||||||
|
semsg(_(e_could_not_clear_timeout_str), GetWin32Error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*timeout_flag = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timeout timer.
|
||||||
|
*
|
||||||
|
* The period is defined in milliseconds.
|
||||||
|
*
|
||||||
|
* The return value is a pointer to a flag that is initialised to 0. If the
|
||||||
|
* timeout expires, the flag is set to 1. This will only return pointers to
|
||||||
|
* static memory; i.e. any pointer returned by this function may always be
|
||||||
|
* safely dereferenced.
|
||||||
|
*
|
||||||
|
* This function is not expected to fail, but if it does it still returns a
|
||||||
|
* valid flag pointer; the flag will remain stuck at zero.
|
||||||
|
*/
|
||||||
|
const int *
|
||||||
|
start_timeout(long msec)
|
||||||
|
{
|
||||||
|
UINT interval = (UINT)msec;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
timeout_flag = &timeout_flags[flag_idx];
|
||||||
|
|
||||||
|
stop_timeout();
|
||||||
|
ret = CreateTimerQueueTimer(
|
||||||
|
&timer_handle, NULL, set_flag, timeout_flag,
|
||||||
|
(DWORD)msec, 0, WT_EXECUTEDEFAULT);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
semsg(_(e_could_not_set_timeout_str), GetWin32Error());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag_idx = (flag_idx + 1) % 2;
|
||||||
|
timer_active = TRUE;
|
||||||
|
*timeout_flag = FALSE;
|
||||||
|
}
|
||||||
|
return timeout_flag;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -72,6 +72,7 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***fil
|
|||||||
int mch_has_exp_wildcard(char_u *p);
|
int mch_has_exp_wildcard(char_u *p);
|
||||||
int mch_has_wildcard(char_u *p);
|
int mch_has_wildcard(char_u *p);
|
||||||
int mch_rename(const char *src, const char *dest);
|
int mch_rename(const char *src, const char *dest);
|
||||||
|
int gpm_available(void);
|
||||||
int gpm_enabled(void);
|
int gpm_enabled(void);
|
||||||
int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result);
|
int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result);
|
||||||
void setup_term_clip(void);
|
void setup_term_clip(void);
|
||||||
@ -85,5 +86,6 @@ void clip_xterm_set_selection(Clipboard_T *cbd);
|
|||||||
int xsmp_handle_requests(void);
|
int xsmp_handle_requests(void);
|
||||||
void xsmp_init(void);
|
void xsmp_init(void);
|
||||||
void xsmp_close(void);
|
void xsmp_close(void);
|
||||||
int gpm_available(void);
|
void stop_timeout(void);
|
||||||
|
const int *start_timeout(long msec);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -83,5 +83,7 @@ int get_conpty_type(void);
|
|||||||
int is_conpty_stable(void);
|
int is_conpty_stable(void);
|
||||||
int get_conpty_fix_type(void);
|
int get_conpty_fix_type(void);
|
||||||
void resize_console_buf(void);
|
void resize_console_buf(void);
|
||||||
char * GetWin32Error(void);
|
char *GetWin32Error(void);
|
||||||
|
void stop_timeout(void);
|
||||||
|
const int *start_timeout(long msec);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
/* regexp.c */
|
/* regexp.c */
|
||||||
|
void init_regexp_timeout(long msec);
|
||||||
|
void disable_regexp_timeout(void);
|
||||||
int re_multiline(regprog_T *prog);
|
int re_multiline(regprog_T *prog);
|
||||||
char_u *skip_regexp(char_u *startp, int delim, int magic);
|
char_u *skip_regexp(char_u *startp, int delim, int magic);
|
||||||
char_u *skip_regexp_err(char_u *startp, int delim, int magic);
|
char_u *skip_regexp_err(char_u *startp, int delim, int magic);
|
||||||
@ -18,5 +20,5 @@ int regprog_in_use(regprog_T *prog);
|
|||||||
int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col);
|
int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col);
|
||||||
int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col);
|
int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col);
|
||||||
int vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col);
|
int vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col);
|
||||||
long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm, int *timed_out);
|
long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, int *timed_out);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -5990,7 +5990,7 @@ vgr_match_buflines(
|
|||||||
{
|
{
|
||||||
// Regular expression match
|
// Regular expression match
|
||||||
while (vim_regexec_multi(regmatch, curwin, buf, lnum,
|
while (vim_regexec_multi(regmatch, curwin, buf, lnum,
|
||||||
col, NULL, NULL) > 0)
|
col, NULL) > 0)
|
||||||
{
|
{
|
||||||
// Pass the buffer number so that it gets used even for a
|
// Pass the buffer number so that it gets used even for a
|
||||||
// dummy buffer, unless duplicate_name is set, then the
|
// dummy buffer, unless duplicate_name is set, then the
|
||||||
|
31
src/regexp.c
31
src/regexp.c
@ -20,6 +20,11 @@
|
|||||||
# define BT_REGEXP_DEBUG_LOG_NAME "bt_regexp_debug.log"
|
# define BT_REGEXP_DEBUG_LOG_NAME "bt_regexp_debug.log"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
static int dummy_timeout_flag = 0;
|
||||||
|
static const int *timeout_flag = &dummy_timeout_flag;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Magic characters have a special meaning, they don't match literally.
|
* Magic characters have a special meaning, they don't match literally.
|
||||||
* Magic characters are negative. This separates them from literal characters
|
* Magic characters are negative. This separates them from literal characters
|
||||||
@ -45,6 +50,20 @@ toggle_Magic(int x)
|
|||||||
return Magic(x);
|
return Magic(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
void
|
||||||
|
init_regexp_timeout(long msec)
|
||||||
|
{
|
||||||
|
timeout_flag = start_timeout(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
disable_regexp_timeout(void)
|
||||||
|
{
|
||||||
|
stop_timeout();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first byte of the BT regexp internal "program" is actually this magic
|
* The first byte of the BT regexp internal "program" is actually this magic
|
||||||
* number; the start node begins in the second byte. It's used to catch the
|
* number; the start node begins in the second byte. It's used to catch the
|
||||||
@ -1944,8 +1963,9 @@ vim_regsub_both(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
// To make sure that the length doesn't change between checking the
|
// To make sure that the length doesn't change between checking the
|
||||||
// length and copying the string, and to speed up things, the
|
// length and copying the string, and to speed up things, the
|
||||||
// resulting string is saved from the call with "flags & REGSUB_COPY"
|
// resulting string is saved from the call with
|
||||||
// == 0 to the // call with "flags & REGSUB_COPY" != 0.
|
// "flags & REGSUB_COPY" == 0 to the call with
|
||||||
|
// "flags & REGSUB_COPY" != 0.
|
||||||
if (copy)
|
if (copy)
|
||||||
{
|
{
|
||||||
if (eval_result != NULL)
|
if (eval_result != NULL)
|
||||||
@ -1960,7 +1980,7 @@ vim_regsub_both(
|
|||||||
int prev_can_f_submatch = can_f_submatch;
|
int prev_can_f_submatch = can_f_submatch;
|
||||||
regsubmatch_T rsm_save;
|
regsubmatch_T rsm_save;
|
||||||
|
|
||||||
vim_free(eval_result);
|
VIM_CLEAR(eval_result);
|
||||||
|
|
||||||
// The expression may contain substitute(), which calls us
|
// The expression may contain substitute(), which calls us
|
||||||
// recursively. Make sure submatch() gets the text from the first
|
// recursively. Make sure submatch() gets the text from the first
|
||||||
@ -2905,7 +2925,6 @@ vim_regexec_multi(
|
|||||||
buf_T *buf, // buffer in which to search
|
buf_T *buf, // buffer in which to search
|
||||||
linenr_T lnum, // nr of line to start looking for match
|
linenr_T lnum, // nr of line to start looking for match
|
||||||
colnr_T col, // column to start looking for match
|
colnr_T col, // column to start looking for match
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag is set when timeout limit reached
|
int *timed_out) // flag is set when timeout limit reached
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -2926,7 +2945,7 @@ vim_regexec_multi(
|
|||||||
rex_in_use = TRUE;
|
rex_in_use = TRUE;
|
||||||
|
|
||||||
result = rmp->regprog->engine->regexec_multi(
|
result = rmp->regprog->engine->regexec_multi(
|
||||||
rmp, win, buf, lnum, col, tm, timed_out);
|
rmp, win, buf, lnum, col, timed_out);
|
||||||
rmp->regprog->re_in_use = FALSE;
|
rmp->regprog->re_in_use = FALSE;
|
||||||
|
|
||||||
// NFA engine aborted because it's very slow.
|
// NFA engine aborted because it's very slow.
|
||||||
@ -2966,7 +2985,7 @@ vim_regexec_multi(
|
|||||||
|
|
||||||
rmp->regprog->re_in_use = TRUE;
|
rmp->regprog->re_in_use = TRUE;
|
||||||
result = rmp->regprog->engine->regexec_multi(
|
result = rmp->regprog->engine->regexec_multi(
|
||||||
rmp, win, buf, lnum, col, tm, timed_out);
|
rmp, win, buf, lnum, col, timed_out);
|
||||||
rmp->regprog->re_in_use = FALSE;
|
rmp->regprog->re_in_use = FALSE;
|
||||||
}
|
}
|
||||||
vim_free(pat);
|
vim_free(pat);
|
||||||
|
@ -173,7 +173,7 @@ struct regengine
|
|||||||
// bt_regexec_nl or nfa_regexec_nl
|
// bt_regexec_nl or nfa_regexec_nl
|
||||||
int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, int);
|
int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, int);
|
||||||
// bt_regexec_mult or nfa_regexec_mult
|
// bt_regexec_mult or nfa_regexec_mult
|
||||||
long (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, proftime_T *, int *);
|
long (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, int *);
|
||||||
//char_u *expr;
|
//char_u *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3228,7 +3228,6 @@ restore_subexpr(regbehind_T *bp)
|
|||||||
static int
|
static int
|
||||||
regmatch(
|
regmatch(
|
||||||
char_u *scan, // Current node.
|
char_u *scan, // Current node.
|
||||||
proftime_T *tm UNUSED, // timeout limit or NULL
|
|
||||||
int *timed_out UNUSED) // flag set on timeout or NULL
|
int *timed_out UNUSED) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
char_u *next; // Next node.
|
char_u *next; // Next node.
|
||||||
@ -3237,9 +3236,6 @@ regmatch(
|
|||||||
regitem_T *rp;
|
regitem_T *rp;
|
||||||
int no;
|
int no;
|
||||||
int status; // one of the RA_ values:
|
int status; // one of the RA_ values:
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
int tm_count = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Make "regstack" and "backpos" empty. They are allocated and freed in
|
// Make "regstack" and "backpos" empty. They are allocated and freed in
|
||||||
// bt_regexec_both() to reduce malloc()/free() calls.
|
// bt_regexec_both() to reduce malloc()/free() calls.
|
||||||
@ -3271,19 +3267,12 @@ regmatch(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
// Check for timeout once in 250 times to avoid excessive overhead from
|
if (*timeout_flag)
|
||||||
// reading the clock. The value has been picked to check about once
|
|
||||||
// per msec on a modern CPU.
|
|
||||||
if (tm != NULL && ++tm_count == 250)
|
|
||||||
{
|
{
|
||||||
tm_count = 0;
|
if (timed_out != NULL)
|
||||||
if (profile_passed_limit(tm))
|
*timed_out = TRUE;
|
||||||
{
|
status = RA_FAIL;
|
||||||
if (timed_out != NULL)
|
break;
|
||||||
*timed_out = TRUE;
|
|
||||||
status = RA_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
status = RA_CONT;
|
status = RA_CONT;
|
||||||
@ -3315,7 +3304,7 @@ regmatch(
|
|||||||
op = OP(scan);
|
op = OP(scan);
|
||||||
// Check for character class with NL added.
|
// Check for character class with NL added.
|
||||||
if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI
|
if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI
|
||||||
&& *rex.input == NUL && rex.lnum <= rex.reg_maxline)
|
&& *rex.input == NUL && rex.lnum <= rex.reg_maxline)
|
||||||
{
|
{
|
||||||
reg_nextline();
|
reg_nextline();
|
||||||
}
|
}
|
||||||
@ -4732,7 +4721,6 @@ regmatch(
|
|||||||
regtry(
|
regtry(
|
||||||
bt_regprog_T *prog,
|
bt_regprog_T *prog,
|
||||||
colnr_T col,
|
colnr_T col,
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag set on timeout or NULL
|
int *timed_out) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
rex.input = rex.line + col;
|
rex.input = rex.line + col;
|
||||||
@ -4742,7 +4730,7 @@ regtry(
|
|||||||
rex.need_clear_zsubexpr = (prog->reghasz == REX_SET);
|
rex.need_clear_zsubexpr = (prog->reghasz == REX_SET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (regmatch(prog->program + 1, tm, timed_out) == 0)
|
if (regmatch(prog->program + 1, timed_out) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup_subexpr();
|
cleanup_subexpr();
|
||||||
@ -4817,7 +4805,6 @@ regtry(
|
|||||||
bt_regexec_both(
|
bt_regexec_both(
|
||||||
char_u *line,
|
char_u *line,
|
||||||
colnr_T col, // column to start looking for match
|
colnr_T col, // column to start looking for match
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag set on timeout or NULL
|
int *timed_out) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
bt_regprog_T *prog;
|
bt_regprog_T *prog;
|
||||||
@ -4940,15 +4927,12 @@ bt_regexec_both(
|
|||||||
&& (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
|
&& (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
|
||||||
|| (c < 255 && prog->regstart < 255 &&
|
|| (c < 255 && prog->regstart < 255 &&
|
||||||
MB_TOLOWER(prog->regstart) == MB_TOLOWER(c)))))
|
MB_TOLOWER(prog->regstart) == MB_TOLOWER(c)))))
|
||||||
retval = regtry(prog, col, tm, timed_out);
|
retval = regtry(prog, col, timed_out);
|
||||||
else
|
else
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
int tm_count = 0;
|
|
||||||
#endif
|
|
||||||
// Messy cases: unanchored match.
|
// Messy cases: unanchored match.
|
||||||
while (!got_int)
|
while (!got_int)
|
||||||
{
|
{
|
||||||
@ -4975,7 +4959,7 @@ bt_regexec_both(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = regtry(prog, col, tm, timed_out);
|
retval = regtry(prog, col, timed_out);
|
||||||
if (retval > 0)
|
if (retval > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4992,18 +4976,11 @@ bt_regexec_both(
|
|||||||
else
|
else
|
||||||
++col;
|
++col;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
// Check for timeout once in 500 times to avoid excessive overhead
|
if (*timeout_flag)
|
||||||
// from reading the clock. The value has been picked to check
|
|
||||||
// about once per msec on a modern CPU.
|
|
||||||
if (tm != NULL && ++tm_count == 500)
|
|
||||||
{
|
{
|
||||||
tm_count = 0;
|
if (timed_out != NULL)
|
||||||
if (profile_passed_limit(tm))
|
*timed_out = TRUE;
|
||||||
{
|
break;
|
||||||
if (timed_out != NULL)
|
|
||||||
*timed_out = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -5067,7 +5044,7 @@ bt_regexec_nl(
|
|||||||
rex.reg_icombine = FALSE;
|
rex.reg_icombine = FALSE;
|
||||||
rex.reg_maxcol = 0;
|
rex.reg_maxcol = 0;
|
||||||
|
|
||||||
return bt_regexec_both(line, col, NULL, NULL);
|
return bt_regexec_both(line, col, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5085,11 +5062,10 @@ bt_regexec_multi(
|
|||||||
buf_T *buf, // buffer in which to search
|
buf_T *buf, // buffer in which to search
|
||||||
linenr_T lnum, // nr of line to start looking for match
|
linenr_T lnum, // nr of line to start looking for match
|
||||||
colnr_T col, // column to start looking for match
|
colnr_T col, // column to start looking for match
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag set on timeout or NULL
|
int *timed_out) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
init_regexec_multi(rmp, win, buf, lnum);
|
init_regexec_multi(rmp, win, buf, lnum);
|
||||||
return bt_regexec_both(NULL, col, tm, timed_out);
|
return bt_regexec_both(NULL, col, timed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4051,7 +4051,6 @@ pim_info(nfa_pim_T *pim)
|
|||||||
// Used during execution: whether a match has been found.
|
// Used during execution: whether a match has been found.
|
||||||
static int nfa_match;
|
static int nfa_match;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
static proftime_T *nfa_time_limit;
|
|
||||||
static int *nfa_timed_out;
|
static int *nfa_timed_out;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -5650,29 +5649,13 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
|
|||||||
* To reduce overhead, only check one in "count" times.
|
* To reduce overhead, only check one in "count" times.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nfa_did_time_out(int count)
|
nfa_did_time_out(void)
|
||||||
{
|
{
|
||||||
static int tm_count = 0;
|
if (*timeout_flag)
|
||||||
|
|
||||||
// Check for timeout once in "count" times to avoid excessive overhead from
|
|
||||||
// reading the clock.
|
|
||||||
if (nfa_time_limit != NULL)
|
|
||||||
{
|
{
|
||||||
if (tm_count >= count)
|
if (nfa_timed_out != NULL)
|
||||||
{
|
*nfa_timed_out = TRUE;
|
||||||
if (profile_passed_limit(nfa_time_limit))
|
return TRUE;
|
||||||
{
|
|
||||||
if (nfa_timed_out != NULL)
|
|
||||||
*nfa_timed_out = TRUE;
|
|
||||||
tm_count = 99999;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
// Only reset the count when not timed out, so that when it did
|
|
||||||
// timeout it keeps timing out until the time limit is changed.
|
|
||||||
tm_count = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++tm_count;
|
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -5726,7 +5709,7 @@ nfa_regmatch(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
// Check relatively often here, since this is the toplevel matching.
|
// Check relatively often here, since this is the toplevel matching.
|
||||||
if (nfa_did_time_out(100))
|
if (nfa_did_time_out())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -5880,8 +5863,7 @@ nfa_regmatch(
|
|||||||
if (got_int)
|
if (got_int)
|
||||||
break;
|
break;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
// do not check very often here, since this is a loop in a loop
|
if (nfa_did_time_out())
|
||||||
if (nfa_did_time_out(2000))
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
t = &thislist->t[listidx];
|
t = &thislist->t[listidx];
|
||||||
@ -7127,8 +7109,8 @@ nextchar:
|
|||||||
if (got_int)
|
if (got_int)
|
||||||
break;
|
break;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
// check regularly but not too often here
|
// Check for timeout once in a twenty times to avoid overhead.
|
||||||
if (nfa_did_time_out(800))
|
if (nfa_did_time_out())
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -7160,7 +7142,6 @@ theend:
|
|||||||
nfa_regtry(
|
nfa_regtry(
|
||||||
nfa_regprog_T *prog,
|
nfa_regprog_T *prog,
|
||||||
colnr_T col,
|
colnr_T col,
|
||||||
proftime_T *tm UNUSED, // timeout limit or NULL
|
|
||||||
int *timed_out UNUSED) // flag set on timeout or NULL
|
int *timed_out UNUSED) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -7173,7 +7154,6 @@ nfa_regtry(
|
|||||||
|
|
||||||
rex.input = rex.line + col;
|
rex.input = rex.line + col;
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
nfa_time_limit = tm;
|
|
||||||
nfa_timed_out = timed_out;
|
nfa_timed_out = timed_out;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7301,7 +7281,6 @@ nfa_regtry(
|
|||||||
nfa_regexec_both(
|
nfa_regexec_both(
|
||||||
char_u *line,
|
char_u *line,
|
||||||
colnr_T startcol, // column to start looking for match
|
colnr_T startcol, // column to start looking for match
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag set on timeout or NULL
|
int *timed_out) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
nfa_regprog_T *prog;
|
nfa_regprog_T *prog;
|
||||||
@ -7397,7 +7376,7 @@ nfa_regexec_both(
|
|||||||
prog->state[i].lastlist[1] = 0;
|
prog->state[i].lastlist[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = nfa_regtry(prog, col, tm, timed_out);
|
retval = nfa_regtry(prog, col, timed_out);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
nfa_regengine.expr = NULL;
|
nfa_regengine.expr = NULL;
|
||||||
@ -7577,7 +7556,7 @@ nfa_regexec_nl(
|
|||||||
rex.reg_ic = rmp->rm_ic;
|
rex.reg_ic = rmp->rm_ic;
|
||||||
rex.reg_icombine = FALSE;
|
rex.reg_icombine = FALSE;
|
||||||
rex.reg_maxcol = 0;
|
rex.reg_maxcol = 0;
|
||||||
return nfa_regexec_both(line, col, NULL, NULL);
|
return nfa_regexec_both(line, col, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7613,11 +7592,10 @@ nfa_regexec_multi(
|
|||||||
buf_T *buf, // buffer in which to search
|
buf_T *buf, // buffer in which to search
|
||||||
linenr_T lnum, // nr of line to start looking for match
|
linenr_T lnum, // nr of line to start looking for match
|
||||||
colnr_T col, // column to start looking for match
|
colnr_T col, // column to start looking for match
|
||||||
proftime_T *tm, // timeout limit or NULL
|
|
||||||
int *timed_out) // flag set on timeout or NULL
|
int *timed_out) // flag set on timeout or NULL
|
||||||
{
|
{
|
||||||
init_regexec_multi(rmp, win, buf, lnum);
|
init_regexec_multi(rmp, win, buf, lnum);
|
||||||
return nfa_regexec_both(NULL, col, tm, timed_out);
|
return nfa_regexec_both(NULL, col, timed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -1760,10 +1760,6 @@ start_search_hl(void)
|
|||||||
end_search_hl(); // just in case it wasn't called before
|
end_search_hl(); // just in case it wasn't called before
|
||||||
last_pat_prog(&screen_search_hl.rm);
|
last_pat_prog(&screen_search_hl.rm);
|
||||||
screen_search_hl.attr = HL_ATTR(HLF_L);
|
screen_search_hl.attr = HL_ATTR(HLF_L);
|
||||||
# ifdef FEAT_RELTIME
|
|
||||||
// Set the time limit to 'redrawtime'.
|
|
||||||
profile_setlimit(p_rdt, &screen_search_hl.tm);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5029,4 +5025,3 @@ set_chars_option(win_T *wp, char_u **varp)
|
|||||||
|
|
||||||
return NULL; // no error
|
return NULL; // no error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
82
src/search.c
82
src/search.c
@ -658,19 +658,8 @@ searchit(
|
|||||||
int break_loop = FALSE;
|
int break_loop = FALSE;
|
||||||
#endif
|
#endif
|
||||||
linenr_T stop_lnum = 0; // stop after this line number when != 0
|
linenr_T stop_lnum = 0; // stop after this line number when != 0
|
||||||
#ifdef FEAT_RELTIME
|
int unused_timeout_flag = FALSE;
|
||||||
proftime_T *tm = NULL; // timeout limit or NULL
|
int *timed_out = &unused_timeout_flag; // set when timed out.
|
||||||
int *timed_out = NULL; // set when timed out or NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (extra_arg != NULL)
|
|
||||||
{
|
|
||||||
stop_lnum = extra_arg->sa_stop_lnum;
|
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
tm = extra_arg->sa_tm;
|
|
||||||
timed_out = &extra_arg->sa_timed_out;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (search_regcomp(pat, RE_SEARCH, pat_use,
|
if (search_regcomp(pat, RE_SEARCH, pat_use,
|
||||||
(options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL)
|
(options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL)
|
||||||
@ -680,6 +669,18 @@ searchit(
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extra_arg != NULL)
|
||||||
|
{
|
||||||
|
stop_lnum = extra_arg->sa_stop_lnum;
|
||||||
|
#ifdef FEAT_RELTIME
|
||||||
|
if (extra_arg->sa_tm > 0)
|
||||||
|
{
|
||||||
|
init_regexp_timeout(extra_arg->sa_tm);
|
||||||
|
timed_out = &extra_arg->sa_timed_out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* find the string
|
* find the string
|
||||||
*/
|
*/
|
||||||
@ -753,11 +754,9 @@ searchit(
|
|||||||
if (stop_lnum != 0 && (dir == FORWARD
|
if (stop_lnum != 0 && (dir == FORWARD
|
||||||
? lnum > stop_lnum : lnum < stop_lnum))
|
? lnum > stop_lnum : lnum < stop_lnum))
|
||||||
break;
|
break;
|
||||||
#ifdef FEAT_RELTIME
|
// Stop after passing the time limit.
|
||||||
// Stop after passing the "tm" time limit.
|
if (*timed_out)
|
||||||
if (tm != NULL && profile_passed_limit(tm))
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look for a match somewhere in line "lnum".
|
* Look for a match somewhere in line "lnum".
|
||||||
@ -765,22 +764,12 @@ searchit(
|
|||||||
col = at_first_line && (options & SEARCH_COL) ? pos->col
|
col = at_first_line && (options & SEARCH_COL) ? pos->col
|
||||||
: (colnr_T)0;
|
: (colnr_T)0;
|
||||||
nmatched = vim_regexec_multi(®match, win, buf,
|
nmatched = vim_regexec_multi(®match, win, buf,
|
||||||
lnum, col,
|
lnum, col, timed_out);
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
tm, timed_out
|
|
||||||
#else
|
|
||||||
NULL, NULL
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
// vim_regexec_multi() may clear "regprog"
|
// vim_regexec_multi() may clear "regprog"
|
||||||
if (regmatch.regprog == NULL)
|
if (regmatch.regprog == NULL)
|
||||||
break;
|
break;
|
||||||
// Abort searching on an error (e.g., out of stack).
|
// Abort searching on an error (e.g., out of stack).
|
||||||
if (called_emsg > called_emsg_before
|
if (called_emsg > called_emsg_before || *timed_out)
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
|| (timed_out != NULL && *timed_out)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
break;
|
break;
|
||||||
if (nmatched > 0)
|
if (nmatched > 0)
|
||||||
{
|
{
|
||||||
@ -863,13 +852,7 @@ searchit(
|
|||||||
if (ptr[matchcol] == NUL
|
if (ptr[matchcol] == NUL
|
||||||
|| (nmatched = vim_regexec_multi(®match,
|
|| (nmatched = vim_regexec_multi(®match,
|
||||||
win, buf, lnum + matchpos.lnum,
|
win, buf, lnum + matchpos.lnum,
|
||||||
matchcol,
|
matchcol, timed_out)) == 0)
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
tm, timed_out
|
|
||||||
#else
|
|
||||||
NULL, NULL
|
|
||||||
#endif
|
|
||||||
)) == 0)
|
|
||||||
{
|
{
|
||||||
match_ok = FALSE;
|
match_ok = FALSE;
|
||||||
break;
|
break;
|
||||||
@ -974,21 +957,13 @@ searchit(
|
|||||||
if (ptr[matchcol] == NUL
|
if (ptr[matchcol] == NUL
|
||||||
|| (nmatched = vim_regexec_multi(®match,
|
|| (nmatched = vim_regexec_multi(®match,
|
||||||
win, buf, lnum + matchpos.lnum,
|
win, buf, lnum + matchpos.lnum,
|
||||||
matchcol,
|
matchcol, timed_out)) == 0)
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
tm, timed_out
|
|
||||||
#else
|
|
||||||
NULL, NULL
|
|
||||||
#endif
|
|
||||||
)) == 0)
|
|
||||||
{
|
{
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
// If the search timed out, we did find a match
|
// If the search timed out, we did find a match
|
||||||
// but it might be the wrong one, so that's not
|
// but it might be the wrong one, so that's not
|
||||||
// OK.
|
// OK.
|
||||||
if (timed_out != NULL && *timed_out)
|
if (*timed_out)
|
||||||
match_ok = FALSE;
|
match_ok = FALSE;
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// vim_regexec_multi() may clear "regprog"
|
// vim_regexec_multi() may clear "regprog"
|
||||||
@ -1097,10 +1072,7 @@ searchit(
|
|||||||
* twice.
|
* twice.
|
||||||
*/
|
*/
|
||||||
if (!p_ws || stop_lnum != 0 || got_int
|
if (!p_ws || stop_lnum != 0 || got_int
|
||||||
|| called_emsg > called_emsg_before
|
|| called_emsg > called_emsg_before || *timed_out
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
|| (timed_out != NULL && *timed_out)
|
|
||||||
#endif
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|| break_loop
|
|| break_loop
|
||||||
#endif
|
#endif
|
||||||
@ -1124,10 +1096,7 @@ searchit(
|
|||||||
if (extra_arg != NULL)
|
if (extra_arg != NULL)
|
||||||
extra_arg->sa_wrapped = TRUE;
|
extra_arg->sa_wrapped = TRUE;
|
||||||
}
|
}
|
||||||
if (got_int || called_emsg > called_emsg_before
|
if (got_int || called_emsg > called_emsg_before || *timed_out
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
|| (timed_out != NULL && *timed_out)
|
|
||||||
#endif
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|| break_loop
|
|| break_loop
|
||||||
#endif
|
#endif
|
||||||
@ -1136,6 +1105,9 @@ searchit(
|
|||||||
}
|
}
|
||||||
while (--count > 0 && found); // stop after count matches or no match
|
while (--count > 0 && found); // stop after count matches or no match
|
||||||
|
|
||||||
|
# ifdef FEAT_RELTIME
|
||||||
|
disable_regexp_timeout();
|
||||||
|
# endif
|
||||||
vim_regfree(regmatch.regprog);
|
vim_regfree(regmatch.regprog);
|
||||||
|
|
||||||
if (!found) // did not find it
|
if (!found) // did not find it
|
||||||
@ -2915,7 +2887,7 @@ is_zero_width(char_u *pattern, int move, pos_T *cur, int direction)
|
|||||||
{
|
{
|
||||||
regmatch.startpos[0].col++;
|
regmatch.startpos[0].col++;
|
||||||
nmatched = vim_regexec_multi(®match, curwin, curbuf,
|
nmatched = vim_regexec_multi(®match, curwin, curbuf,
|
||||||
pos.lnum, regmatch.startpos[0].col, NULL, NULL);
|
pos.lnum, regmatch.startpos[0].col, NULL);
|
||||||
if (nmatched != 0)
|
if (nmatched != 0)
|
||||||
break;
|
break;
|
||||||
} while (regmatch.regprog != NULL
|
} while (regmatch.regprog != NULL
|
||||||
|
@ -3329,9 +3329,6 @@ typedef struct
|
|||||||
// matchaddpos(). TRUE/FALSE
|
// matchaddpos(). TRUE/FALSE
|
||||||
char has_cursor; // TRUE if the cursor is inside the match, used for
|
char has_cursor; // TRUE if the cursor is inside the match, used for
|
||||||
// CurSearch
|
// CurSearch
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
proftime_T tm; // for a time limit
|
|
||||||
#endif
|
|
||||||
} match_T;
|
} match_T;
|
||||||
|
|
||||||
// number of positions supported by matchaddpos()
|
// number of positions supported by matchaddpos()
|
||||||
@ -4419,7 +4416,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
linenr_T sa_stop_lnum; // stop after this line number when != 0
|
linenr_T sa_stop_lnum; // stop after this line number when != 0
|
||||||
#ifdef FEAT_RELTIME
|
#ifdef FEAT_RELTIME
|
||||||
proftime_T *sa_tm; // timeout limit or NULL
|
long sa_tm; // timeout limit or zero
|
||||||
int sa_timed_out; // set when timed out
|
int sa_timed_out; // set when timed out
|
||||||
#endif
|
#endif
|
||||||
int sa_wrapped; // search wrapped around
|
int sa_wrapped; // search wrapped around
|
||||||
|
25
src/syntax.c
25
src/syntax.c
@ -266,9 +266,6 @@ static reg_extmatch_T *next_match_extmatch = NULL;
|
|||||||
static win_T *syn_win; // current window for highlighting
|
static win_T *syn_win; // current window for highlighting
|
||||||
static buf_T *syn_buf; // current buffer for highlighting
|
static buf_T *syn_buf; // current buffer for highlighting
|
||||||
static synblock_T *syn_block; // current buffer for highlighting
|
static synblock_T *syn_block; // current buffer for highlighting
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
static proftime_T *syn_tm; // timeout limit
|
|
||||||
#endif
|
|
||||||
static linenr_T current_lnum = 0; // lnum of current state
|
static linenr_T current_lnum = 0; // lnum of current state
|
||||||
static colnr_T current_col = 0; // column of current state
|
static colnr_T current_col = 0; // column of current state
|
||||||
static int current_state_stored = 0; // TRUE if stored current state
|
static int current_state_stored = 0; // TRUE if stored current state
|
||||||
@ -350,18 +347,6 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci);
|
|||||||
static int get_id_list(char_u **arg, int keylen, short **list, int skip);
|
static int get_id_list(char_u **arg, int keylen, short **list, int skip);
|
||||||
static void syn_combine_list(short **clstr1, short **clstr2, int list_op);
|
static void syn_combine_list(short **clstr1, short **clstr2, int list_op);
|
||||||
|
|
||||||
#if defined(FEAT_RELTIME) || defined(PROTO)
|
|
||||||
/*
|
|
||||||
* Set the timeout used for syntax highlighting.
|
|
||||||
* Use NULL to reset, no timeout.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
syn_set_timeout(proftime_T *tm)
|
|
||||||
{
|
|
||||||
syn_tm = tm;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the syntax recognition for a line. This function is normally called
|
* Start the syntax recognition for a line. This function is normally called
|
||||||
* from the screen updating, once for each displayed line.
|
* from the screen updating, once for each displayed line.
|
||||||
@ -3166,9 +3151,7 @@ syn_regexec(
|
|||||||
syn_time_T *st UNUSED)
|
syn_time_T *st UNUSED)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
int timed_out = FALSE;
|
int timed_out = FALSE;
|
||||||
#endif
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
proftime_T pt;
|
proftime_T pt;
|
||||||
|
|
||||||
@ -3183,13 +3166,7 @@ syn_regexec(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
rmp->rmm_maxcol = syn_buf->b_p_smc;
|
rmp->rmm_maxcol = syn_buf->b_p_smc;
|
||||||
r = vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col,
|
r = vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, &timed_out);
|
||||||
#ifdef FEAT_RELTIME
|
|
||||||
syn_tm, &timed_out
|
|
||||||
#else
|
|
||||||
NULL, NULL
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (syn_time_on)
|
if (syn_time_on)
|
||||||
|
@ -37,6 +37,15 @@ endfunc
|
|||||||
func Test_hlsearch_hangs()
|
func Test_hlsearch_hangs()
|
||||||
CheckFunction reltimefloat
|
CheckFunction reltimefloat
|
||||||
|
|
||||||
|
" So, it turns out the Windows 7 implements TimerQueue timers differently
|
||||||
|
" and they can expire *before* the requested time has elapsed. So allow for
|
||||||
|
" the timeout occurring after 80 ms (5 * 16 (the typical clock tick)).
|
||||||
|
if has("win32")
|
||||||
|
let min_timeout = 0.08
|
||||||
|
else
|
||||||
|
let min_timeout = 0.1
|
||||||
|
endif
|
||||||
|
|
||||||
" This pattern takes a long time to match, it should timeout.
|
" This pattern takes a long time to match, it should timeout.
|
||||||
new
|
new
|
||||||
call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
|
call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
|
||||||
@ -45,7 +54,7 @@ func Test_hlsearch_hangs()
|
|||||||
let @/ = '\%#=1a*.*X\@<=b*'
|
let @/ = '\%#=1a*.*X\@<=b*'
|
||||||
redraw
|
redraw
|
||||||
let elapsed = reltimefloat(reltime(start))
|
let elapsed = reltimefloat(reltime(start))
|
||||||
call assert_true(elapsed > 0.1)
|
call assert_true(elapsed > min_timeout)
|
||||||
call assert_true(elapsed < 1.0)
|
call assert_true(elapsed < 1.0)
|
||||||
set nohlsearch redrawtime&
|
set nohlsearch redrawtime&
|
||||||
bwipe!
|
bwipe!
|
||||||
|
@ -1550,6 +1550,32 @@ func Test_search_errors()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_search_timeout()
|
||||||
|
new
|
||||||
|
let pattern = '\%#=1a*.*X\@<=b*'
|
||||||
|
let search_timeout = 0.02
|
||||||
|
let slow_target_timeout = search_timeout * 15.0
|
||||||
|
|
||||||
|
for n in range(40, 400, 30)
|
||||||
|
call setline(1, ['aaa', repeat('abc ', n), 'ccc'])
|
||||||
|
let start = reltime()
|
||||||
|
call search(pattern, '', 0)
|
||||||
|
let elapsed = reltimefloat(reltime(start))
|
||||||
|
if elapsed > slow_target_timeout
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
call assert_true(elapsed > slow_target_timeout)
|
||||||
|
|
||||||
|
let max_time = elapsed / 2.0
|
||||||
|
let start = reltime()
|
||||||
|
call search(pattern, '', 0, float2nr(search_timeout * 1000))
|
||||||
|
let elapsed = reltimefloat(reltime(start))
|
||||||
|
call assert_true(elapsed < max_time)
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_search_display_pattern()
|
func Test_search_display_pattern()
|
||||||
new
|
new
|
||||||
call setline(1, ['foo', 'bar', 'foobar'])
|
call setline(1, ['foo', 'bar', 'foobar'])
|
||||||
|
@ -527,6 +527,15 @@ func Test_syntax_hangs()
|
|||||||
CheckFunction reltimefloat
|
CheckFunction reltimefloat
|
||||||
CheckFeature syntax
|
CheckFeature syntax
|
||||||
|
|
||||||
|
" So, it turns out the Windows 7 implements TimerQueue timers differently
|
||||||
|
" and they can expire *before* the requested time has elapsed. So allow for
|
||||||
|
" the timeout occurring after 80 ms (5 * 16 (the typical clock tick)).
|
||||||
|
if has("win32")
|
||||||
|
let min_timeout = 0.08
|
||||||
|
else
|
||||||
|
let min_timeout = 0.1
|
||||||
|
endif
|
||||||
|
|
||||||
" This pattern takes a long time to match, it should timeout.
|
" This pattern takes a long time to match, it should timeout.
|
||||||
new
|
new
|
||||||
call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
|
call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
|
||||||
@ -535,7 +544,7 @@ func Test_syntax_hangs()
|
|||||||
syn match Error /\%#=1a*.*X\@<=b*/
|
syn match Error /\%#=1a*.*X\@<=b*/
|
||||||
redraw
|
redraw
|
||||||
let elapsed = reltimefloat(reltime(start))
|
let elapsed = reltimefloat(reltime(start))
|
||||||
call assert_true(elapsed > 0.1)
|
call assert_true(elapsed > min_timeout)
|
||||||
call assert_true(elapsed < 1.0)
|
call assert_true(elapsed < 1.0)
|
||||||
|
|
||||||
" second time syntax HL is disabled
|
" second time syntax HL is disabled
|
||||||
@ -549,7 +558,7 @@ func Test_syntax_hangs()
|
|||||||
exe "normal \<C-L>"
|
exe "normal \<C-L>"
|
||||||
redraw
|
redraw
|
||||||
let elapsed = reltimefloat(reltime(start))
|
let elapsed = reltimefloat(reltime(start))
|
||||||
call assert_true(elapsed > 0.1)
|
call assert_true(elapsed > min_timeout)
|
||||||
call assert_true(elapsed < 1.0)
|
call assert_true(elapsed < 1.0)
|
||||||
|
|
||||||
set redrawtime&
|
set redrawtime&
|
||||||
@ -642,7 +651,7 @@ func Test_syntax_c()
|
|||||||
\ "\tNote: asdf",
|
\ "\tNote: asdf",
|
||||||
\ '}',
|
\ '}',
|
||||||
\ ], 'Xtest.c')
|
\ ], 'Xtest.c')
|
||||||
|
|
||||||
" This makes the default for 'background' use "dark", check that the
|
" This makes the default for 'background' use "dark", check that the
|
||||||
" response to t_RB corrects it to "light".
|
" response to t_RB corrects it to "light".
|
||||||
let $COLORFGBG = '15;0'
|
let $COLORFGBG = '15;0'
|
||||||
|
@ -734,6 +734,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
5057,
|
||||||
/**/
|
/**/
|
||||||
5056,
|
5056,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user