]> granicus.if.org Git - vim/commitdiff
patch 8.2.0256: time and timer related code is spread out v8.2.0256
authorBram Moolenaar <Bram@vim.org>
Fri, 14 Feb 2020 12:22:17 +0000 (13:22 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 14 Feb 2020 12:22:17 +0000 (13:22 +0100)
Problem:    Time and timer related code is spread out.
Solution:   Move time and timer related code to a new file. (Yegappan
            Lakshmanan, closes #5604)

24 files changed:
Filelist
src/Make_cyg_ming.mak
src/Make_morph.mak
src/Make_mvc.mak
src/Make_vms.mms
src/Makefile
src/README.md
src/evalfunc.c
src/ex_cmds.c
src/ex_cmds2.c
src/main.c
src/memline.c
src/misc1.c
src/misc2.c
src/proto.h
src/proto/ex_cmds.pro
src/proto/ex_cmds2.pro
src/proto/main.pro
src/proto/memline.pro
src/proto/misc1.pro
src/proto/misc2.pro
src/proto/time.pro [new file with mode: 0644]
src/time.c [new file with mode: 0644]
src/version.c

index 91e6b04325b36751e8ca7370a7f36fcb712c3c9e..41eb53f5a33256afd66057a58590663fa5a4ff18 100644 (file)
--- a/Filelist
+++ b/Filelist
@@ -127,6 +127,7 @@ SRC_ALL =   \
                src/termlib.c \
                src/testing.c \
                src/textprop.c \
+               src/time.c \
                src/ui.c \
                src/undo.c \
                src/usercmd.c \
@@ -275,6 +276,7 @@ SRC_ALL =   \
                src/proto/termlib.pro \
                src/proto/testing.pro \
                src/proto/textprop.pro \
+               src/proto/time.pro \
                src/proto/ui.pro \
                src/proto/undo.pro \
                src/proto/usercmd.pro \
index 639f3e5dcbcfbcb4eefa69ca3370bf707e5d2bde..99c004fc07d67035f2623d515be8ca67bcfebb42 100644 (file)
@@ -783,6 +783,7 @@ OBJ = \
        $(OUTDIR)/term.o \
        $(OUTDIR)/testing.o \
        $(OUTDIR)/textprop.o \
+       $(OUTDIR)/time.o \
        $(OUTDIR)/ui.o \
        $(OUTDIR)/undo.o \
        $(OUTDIR)/usercmd.o \
index bb5805c4d2d2a8e626b8b423eb93e6b13a90bb25..2c226de29805780c364bb1d5d921c5fefd9fa389 100644 (file)
@@ -102,6 +102,7 @@ SRC =       arabic.c                                                \
        term.c                                                  \
        testing.c                                               \
        textprop.c                                              \
+       time.c                                                  \
        ui.c                                                    \
        undo.c                                                  \
        usercmd.c                                               \
index da9a911d0ada31a2f8ab97ab52ea6970ce32855b..fd7a6ab5c36bf3678aee8c99a787c648534498c4 100644 (file)
@@ -799,6 +799,7 @@ OBJ = \
        $(OUTDIR)\term.obj \
        $(OUTDIR)\testing.obj \
        $(OUTDIR)\textprop.obj \
+       $(OUTDIR)\time.obj \
        $(OUTDIR)\ui.obj \
        $(OUTDIR)\undo.obj \
        $(OUTDIR)\usercmd.obj \
@@ -1733,6 +1734,8 @@ $(OUTDIR)/term.obj:       $(OUTDIR) testing.c  $(INCL)
 
 $(OUTDIR)/textprop.obj:        $(OUTDIR) textprop.c  $(INCL)
 
+$(OUTDIR)/time.obj:    $(OUTDIR) time.c  $(INCL)
+
 $(OUTDIR)/ui.obj:      $(OUTDIR) ui.c  $(INCL)
 
 $(OUTDIR)/undo.obj:    $(OUTDIR) undo.c  $(INCL)
@@ -1926,6 +1929,7 @@ proto.h: \
        proto/term.pro \
        proto/testing.pro \
        proto/textprop.pro \
+       proto/time.pro \
        proto/ui.pro \
        proto/undo.pro \
        proto/usercmd.pro \
index 8a74d3eb0e65b32ddd263a718f5cd6e0f4c2ba34..32857decc11fefc6ef3950f94830bd5333d8d323 100644 (file)
@@ -381,6 +381,7 @@ SRC = \
        termlib.c \
        testing.c \
        textprop.c \
+       time.c \
        ui.c \
        undo.c \
        usercmd.c \
@@ -487,6 +488,7 @@ OBJ = \
        termlib.obj \
        testing.obj \
        textprop.obj \
+       time.obj \
        ui.obj \
        undo.obj \
        usercmd.obj \
@@ -978,6 +980,9 @@ testing.obj : testing.c vim.h [.auto]config.h feature.h os_unix.h   \
 textprop.obj : textprop.c vim.h [.auto]config.h feature.h os_unix.h   \
  ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
  [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
+time.obj : time.c vim.h [.auto]config.h feature.h os_unix.h   \
+ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
+ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
 ui.obj : ui.c vim.h [.auto]config.h feature.h os_unix.h   \
  ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
  [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
index 912098f8b3bf5fa3bf436c4ec5f5c4dac814b0bb..e284530164e1331a7cae955527c363a6360dddf1 100644 (file)
@@ -1661,6 +1661,7 @@ BASIC_SRC = \
        terminal.c \
        testing.c \
        textprop.c \
+       time.c \
        ui.c \
        undo.c \
        usercmd.c \
@@ -1800,6 +1801,7 @@ OBJ_COMMON = \
        objects/terminal.o \
        objects/testing.o \
        objects/textprop.o \
+       objects/time.o \
        objects/ui.o \
        objects/undo.o \
        objects/usercmd.o \
@@ -1971,6 +1973,7 @@ PRO_AUTO = \
        termlib.pro \
        testing.pro \
        textprop.pro \
+       time.pro \
        ui.pro \
        undo.pro \
        usercmd.pro \
@@ -3433,6 +3436,9 @@ objects/testing.o: testing.c
 objects/textprop.o: textprop.c
        $(CCC) -o $@ textprop.c
 
+objects/time.o: time.c
+       $(CCC) -o $@ time.c
+
 objects/ui.o: ui.c
        $(CCC) -o $@ ui.c
 
@@ -3959,6 +3965,10 @@ objects/textprop.o: textprop.c vim.h protodef.h auto/config.h feature.h os_unix.
  auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
  proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
  proto.h globals.h
+objects/time.o: time.c vim.h protodef.h auto/config.h feature.h os_unix.h \
+ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
+ proto.h globals.h
 objects/ui.o: ui.c vim.h protodef.h auto/config.h feature.h os_unix.h \
  auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
  proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
index 0262a7a5bd1340da1291738cc77c7b675523c62a..4412d533ee8ec1668950102ec5cc739b3ff98be7 100644 (file)
@@ -79,6 +79,7 @@ tag.c         | tags
 term.c         | terminal handling, termcap codes
 testing.c      | testing: assert and test functions
 textprop.c     | text properties
+time.c         | time and timer functions
 undo.c         | undo and redo
 usercmd.c      | user defined commands
 userfunc.c     | user defined functions
index 6e96d0d1b8d907eaa9af1140fdefe073b6200025..b4009f0aefb58db14da57a2615bef79c3cfeaa45 100644 (file)
 # include <float.h>
 #endif
 
-#if defined(MACOS_X)
-# include <time.h>     // for time_t
-#endif
-
 #ifdef FEAT_FLOAT
 static void f_abs(typval_T *argvars, typval_T *rettv);
 static void f_acos(typval_T *argvars, typval_T *rettv);
@@ -126,7 +122,6 @@ static void f_libcall(typval_T *argvars, typval_T *rettv);
 static void f_libcallnr(typval_T *argvars, typval_T *rettv);
 static void f_line(typval_T *argvars, typval_T *rettv);
 static void f_line2byte(typval_T *argvars, typval_T *rettv);
-static void f_localtime(typval_T *argvars, typval_T *rettv);
 #ifdef FEAT_FLOAT
 static void f_log(typval_T *argvars, typval_T *rettv);
 static void f_log10(typval_T *argvars, typval_T *rettv);
@@ -173,11 +168,6 @@ static void f_rand(typval_T *argvars, typval_T *rettv);
 static void f_range(typval_T *argvars, typval_T *rettv);
 static void f_reg_executing(typval_T *argvars, typval_T *rettv);
 static void f_reg_recording(typval_T *argvars, typval_T *rettv);
-static void f_reltime(typval_T *argvars, typval_T *rettv);
-#ifdef FEAT_FLOAT
-static void f_reltimefloat(typval_T *argvars, typval_T *rettv);
-#endif
-static void f_reltimestr(typval_T *argvars, typval_T *rettv);
 static void f_remote_expr(typval_T *argvars, typval_T *rettv);
 static void f_remote_foreground(typval_T *argvars, typval_T *rettv);
 static void f_remote_peek(typval_T *argvars, typval_T *rettv);
@@ -234,17 +224,11 @@ static void f_str2float(typval_T *argvars, typval_T *rettv);
 static void f_str2list(typval_T *argvars, typval_T *rettv);
 static void f_str2nr(typval_T *argvars, typval_T *rettv);
 static void f_strchars(typval_T *argvars, typval_T *rettv);
-#ifdef HAVE_STRFTIME
-static void f_strftime(typval_T *argvars, typval_T *rettv);
-#endif
 static void f_strgetchar(typval_T *argvars, typval_T *rettv);
 static void f_stridx(typval_T *argvars, typval_T *rettv);
 static void f_strlen(typval_T *argvars, typval_T *rettv);
 static void f_strcharpart(typval_T *argvars, typval_T *rettv);
 static void f_strpart(typval_T *argvars, typval_T *rettv);
-#ifdef HAVE_STRPTIME
-static void f_strptime(typval_T *argvars, typval_T *rettv);
-#endif
 static void f_strridx(typval_T *argvars, typval_T *rettv);
 static void f_strtrans(typval_T *argvars, typval_T *rettv);
 static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
@@ -4512,15 +4496,6 @@ f_line2byte(typval_T *argvars UNUSED, typval_T *rettv)
 #endif
 }
 
-/*
- * "localtime()" function
- */
-    static void
-f_localtime(typval_T *argvars UNUSED, typval_T *rettv)
-{
-    rettv->vval.v_number = (varnumber_T)time(NULL);
-}
-
 #ifdef FEAT_FLOAT
 /*
  * "log()" function
@@ -5500,118 +5475,6 @@ f_reg_recording(typval_T *argvars UNUSED, typval_T *rettv)
     return_register(reg_recording, rettv);
 }
 
-#if defined(FEAT_RELTIME)
-/*
- * Convert a List to proftime_T.
- * Return FAIL when there is something wrong.
- */
-    static int
-list2proftime(typval_T *arg, proftime_T *tm)
-{
-    long       n1, n2;
-    int        error = FALSE;
-
-    if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL
-                                            || arg->vval.v_list->lv_len != 2)
-       return FAIL;
-    n1 = list_find_nr(arg->vval.v_list, 0L, &error);
-    n2 = list_find_nr(arg->vval.v_list, 1L, &error);
-# ifdef MSWIN
-    tm->HighPart = n1;
-    tm->LowPart = n2;
-# else
-    tm->tv_sec = n1;
-    tm->tv_usec = n2;
-# endif
-    return error ? FAIL : OK;
-}
-#endif // FEAT_RELTIME
-
-/*
- * "reltime()" function
- */
-    static void
-f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
-{
-#ifdef FEAT_RELTIME
-    proftime_T res;
-    proftime_T start;
-
-    if (argvars[0].v_type == VAR_UNKNOWN)
-    {
-       // No arguments: get current time.
-       profile_start(&res);
-    }
-    else if (argvars[1].v_type == VAR_UNKNOWN)
-    {
-       if (list2proftime(&argvars[0], &res) == FAIL)
-           return;
-       profile_end(&res);
-    }
-    else
-    {
-       // Two arguments: compute the difference.
-       if (list2proftime(&argvars[0], &start) == FAIL
-               || list2proftime(&argvars[1], &res) == FAIL)
-           return;
-       profile_sub(&res, &start);
-    }
-
-    if (rettv_list_alloc(rettv) == OK)
-    {
-       long    n1, n2;
-
-# ifdef MSWIN
-       n1 = res.HighPart;
-       n2 = res.LowPart;
-# else
-       n1 = res.tv_sec;
-       n2 = res.tv_usec;
-# endif
-       list_append_number(rettv->vval.v_list, (varnumber_T)n1);
-       list_append_number(rettv->vval.v_list, (varnumber_T)n2);
-    }
-#endif
-}
-
-#ifdef FEAT_FLOAT
-/*
- * "reltimefloat()" function
- */
-    static void
-f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv)
-{
-# ifdef FEAT_RELTIME
-    proftime_T tm;
-# endif
-
-    rettv->v_type = VAR_FLOAT;
-    rettv->vval.v_float = 0;
-# ifdef FEAT_RELTIME
-    if (list2proftime(&argvars[0], &tm) == OK)
-       rettv->vval.v_float = profile_float(&tm);
-# endif
-}
-#endif
-
-/*
- * "reltimestr()" function
- */
-    static void
-f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv)
-{
-#ifdef FEAT_RELTIME
-    proftime_T tm;
-#endif
-
-    rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = NULL;
-#ifdef FEAT_RELTIME
-    if (list2proftime(&argvars[0], &tm) == OK)
-       rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
-#endif
-}
-
 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
     static void
 make_connection(void)
@@ -7422,61 +7285,6 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
 
 }
 
-#ifdef HAVE_STRFTIME
-/*
- * "strftime({format}[, {time}])" function
- */
-    static void
-f_strftime(typval_T *argvars, typval_T *rettv)
-{
-    char_u     result_buf[256];
-    struct tm  tmval;
-    struct tm  *curtime;
-    time_t     seconds;
-    char_u     *p;
-
-    rettv->v_type = VAR_STRING;
-
-    p = tv_get_string(&argvars[0]);
-    if (argvars[1].v_type == VAR_UNKNOWN)
-       seconds = time(NULL);
-    else
-       seconds = (time_t)tv_get_number(&argvars[1]);
-    curtime = vim_localtime(&seconds, &tmval);
-    // MSVC returns NULL for an invalid value of seconds.
-    if (curtime == NULL)
-       rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
-    else
-    {
-       vimconv_T   conv;
-       char_u      *enc;
-
-       conv.vc_type = CONV_NONE;
-       enc = enc_locale();
-       convert_setup(&conv, p_enc, enc);
-       if (conv.vc_type != CONV_NONE)
-           p = string_convert(&conv, p, NULL);
-       if (p != NULL)
-           (void)strftime((char *)result_buf, sizeof(result_buf),
-                                                         (char *)p, curtime);
-       else
-           result_buf[0] = NUL;
-
-       if (conv.vc_type != CONV_NONE)
-           vim_free(p);
-       convert_setup(&conv, enc, p_enc);
-       if (conv.vc_type != CONV_NONE)
-           rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
-       else
-           rettv->vval.v_string = vim_strsave(result_buf);
-
-       // Release conversion descriptors
-       convert_setup(&conv, NULL, NULL);
-       vim_free(enc);
-    }
-}
-#endif
-
 /*
  * "strgetchar()" function
  */
@@ -7734,40 +7542,6 @@ f_strpart(typval_T *argvars, typval_T *rettv)
     rettv->vval.v_string = vim_strnsave(p + n, len);
 }
 
-#ifdef HAVE_STRPTIME
-/*
- * "strptime({format}, {timestring})" function
- */
-    static void
-f_strptime(typval_T *argvars, typval_T *rettv)
-{
-    struct tm  tmval;
-    char_u     *fmt;
-    char_u     *str;
-    vimconv_T   conv;
-    char_u     *enc;
-
-    vim_memset(&tmval, NUL, sizeof(tmval));
-    fmt = tv_get_string(&argvars[0]);
-    str = tv_get_string(&argvars[1]);
-
-    conv.vc_type = CONV_NONE;
-    enc = enc_locale();
-    convert_setup(&conv, p_enc, enc);
-    if (conv.vc_type != CONV_NONE)
-       fmt = string_convert(&conv, fmt, NULL);
-    if (fmt == NULL
-           || strptime((char *)str, (char *)fmt, &tmval) == NULL
-           || (rettv->vval.v_number = mktime(&tmval)) == -1)
-       rettv->vval.v_number = 0;
-
-    if (conv.vc_type != CONV_NONE)
-       vim_free(fmt);
-    convert_setup(&conv, NULL, NULL);
-    vim_free(enc);
-}
-#endif
-
 /*
  * "strridx()" function
  */
index 881e6f9265b995cee38fb20c149fee4c214b1d8e..0eeb3f33996ba79f6cbbec92fda99dde20753e62 100644 (file)
@@ -1678,20 +1678,6 @@ append_redir(
                (char *)opt, (char *)fname);
 }
 
-/*
- * Return the current time in seconds.  Calls time(), unless test_settime()
- * was used.
- */
-    time_T
-vim_time(void)
-{
-# ifdef FEAT_EVAL
-    return time_for_testing == 0 ? time(NULL) : time_for_testing;
-# else
-    return time(NULL);
-# endif
-}
-
 /*
  * Implementation of ":fixdel", also used by get_stty().
  *  <BS>    resulting <Del>
index 4f8f7fbf658083d7a20850a802ed6cdd2085bc6f..bbaff391e4197650a41e19398e0ab8d7fb8bc287 100644 (file)
 #include "vim.h"
 #include "version.h"
 
-#if defined(FEAT_EVAL) || defined(PROTO)
-# if defined(FEAT_TIMERS) || defined(PROTO)
-static timer_T *first_timer = NULL;
-static long    last_timer_id = 0;
-
-/*
- * Return time left until "due".  Negative if past "due".
- */
-    long
-proftime_time_left(proftime_T *due, proftime_T *now)
-{
-#  ifdef MSWIN
-    LARGE_INTEGER fr;
-
-    if (now->QuadPart > due->QuadPart)
-       return 0;
-    QueryPerformanceFrequency(&fr);
-    return (long)(((double)(due->QuadPart - now->QuadPart)
-                  / (double)fr.QuadPart) * 1000);
-#  else
-    if (now->tv_sec > due->tv_sec)
-       return 0;
-    return (due->tv_sec - now->tv_sec) * 1000
-       + (due->tv_usec - now->tv_usec) / 1000;
-#  endif
-}
-
-/*
- * Insert a timer in the list of timers.
- */
-    static void
-insert_timer(timer_T *timer)
-{
-    timer->tr_next = first_timer;
-    timer->tr_prev = NULL;
-    if (first_timer != NULL)
-       first_timer->tr_prev = timer;
-    first_timer = timer;
-    did_add_timer = TRUE;
-}
-
-/*
- * Take a timer out of the list of timers.
- */
-    static void
-remove_timer(timer_T *timer)
-{
-    if (timer->tr_prev == NULL)
-       first_timer = timer->tr_next;
-    else
-       timer->tr_prev->tr_next = timer->tr_next;
-    if (timer->tr_next != NULL)
-       timer->tr_next->tr_prev = timer->tr_prev;
-}
-
-    static void
-free_timer(timer_T *timer)
-{
-    free_callback(&timer->tr_callback);
-    vim_free(timer);
-}
-
-/*
- * Create a timer and return it.  NULL if out of memory.
- * Caller should set the callback.
- */
-    timer_T *
-create_timer(long msec, int repeat)
-{
-    timer_T    *timer = ALLOC_CLEAR_ONE(timer_T);
-    long       prev_id = last_timer_id;
-
-    if (timer == NULL)
-       return NULL;
-    if (++last_timer_id <= prev_id)
-       // Overflow!  Might cause duplicates...
-       last_timer_id = 0;
-    timer->tr_id = last_timer_id;
-    insert_timer(timer);
-    if (repeat != 0)
-       timer->tr_repeat = repeat - 1;
-    timer->tr_interval = msec;
-
-    profile_setlimit(msec, &timer->tr_due);
-    return timer;
-}
-
-/*
- * Invoke the callback of "timer".
- */
-    static void
-timer_callback(timer_T *timer)
-{
-    typval_T   rettv;
-    typval_T   argv[2];
-
-    argv[0].v_type = VAR_NUMBER;
-    argv[0].vval.v_number = (varnumber_T)timer->tr_id;
-    argv[1].v_type = VAR_UNKNOWN;
-
-    call_callback(&timer->tr_callback, -1, &rettv, 1, argv);
-    clear_tv(&rettv);
-}
-
-/*
- * Call timers that are due.
- * Return the time in msec until the next timer is due.
- * Returns -1 if there are no pending timers.
- */
-    long
-check_due_timer(void)
-{
-    timer_T    *timer;
-    timer_T    *timer_next;
-    long       this_due;
-    long       next_due = -1;
-    proftime_T now;
-    int                did_one = FALSE;
-    int                need_update_screen = FALSE;
-    long       current_id = last_timer_id;
-
-    // Don't run any timers while exiting or dealing with an error.
-    if (exiting || aborting())
-       return next_due;
-
-    profile_start(&now);
-    for (timer = first_timer; timer != NULL && !got_int; timer = timer_next)
-    {
-       timer_next = timer->tr_next;
-
-       if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused)
-           continue;
-       this_due = proftime_time_left(&timer->tr_due, &now);
-       if (this_due <= 1)
-       {
-           // Save and restore a lot of flags, because the timer fires while
-           // waiting for a character, which might be halfway a command.
-           int save_timer_busy = timer_busy;
-           int save_vgetc_busy = vgetc_busy;
-           int save_did_emsg = did_emsg;
-           int save_called_emsg = called_emsg;
-           int save_must_redraw = must_redraw;
-           int save_trylevel = trylevel;
-           int save_did_throw = did_throw;
-           int save_ex_pressedreturn = get_pressedreturn();
-           int save_may_garbage_collect = may_garbage_collect;
-           except_T *save_current_exception = current_exception;
-           vimvars_save_T vvsave;
-
-           // Create a scope for running the timer callback, ignoring most of
-           // the current scope, such as being inside a try/catch.
-           timer_busy = timer_busy > 0 || vgetc_busy > 0;
-           vgetc_busy = 0;
-           called_emsg = 0;
-           did_emsg = FALSE;
-           did_uncaught_emsg = FALSE;
-           must_redraw = 0;
-           trylevel = 0;
-           did_throw = FALSE;
-           current_exception = NULL;
-           may_garbage_collect = FALSE;
-           save_vimvars(&vvsave);
-
-           timer->tr_firing = TRUE;
-           timer_callback(timer);
-           timer->tr_firing = FALSE;
-
-           timer_next = timer->tr_next;
-           did_one = TRUE;
-           timer_busy = save_timer_busy;
-           vgetc_busy = save_vgetc_busy;
-           if (did_uncaught_emsg)
-               ++timer->tr_emsg_count;
-           did_emsg = save_did_emsg;
-           called_emsg = save_called_emsg;
-           trylevel = save_trylevel;
-           did_throw = save_did_throw;
-           current_exception = save_current_exception;
-           restore_vimvars(&vvsave);
-           if (must_redraw != 0)
-               need_update_screen = TRUE;
-           must_redraw = must_redraw > save_must_redraw
-                                             ? must_redraw : save_must_redraw;
-           set_pressedreturn(save_ex_pressedreturn);
-           may_garbage_collect = save_may_garbage_collect;
-
-           // Only fire the timer again if it repeats and stop_timer() wasn't
-           // called while inside the callback (tr_id == -1).
-           if (timer->tr_repeat != 0 && timer->tr_id != -1
-                   && timer->tr_emsg_count < 3)
-           {
-               profile_setlimit(timer->tr_interval, &timer->tr_due);
-               this_due = proftime_time_left(&timer->tr_due, &now);
-               if (this_due < 1)
-                   this_due = 1;
-               if (timer->tr_repeat > 0)
-                   --timer->tr_repeat;
-           }
-           else
-           {
-               this_due = -1;
-               remove_timer(timer);
-               free_timer(timer);
-           }
-       }
-       if (this_due > 0 && (next_due == -1 || next_due > this_due))
-           next_due = this_due;
-    }
-
-    if (did_one)
-       redraw_after_callback(need_update_screen);
-
-#ifdef FEAT_BEVAL_TERM
-    if (bevalexpr_due_set)
-    {
-       this_due = proftime_time_left(&bevalexpr_due, &now);
-       if (this_due <= 1)
-       {
-           bevalexpr_due_set = FALSE;
-           if (balloonEval == NULL)
-           {
-               balloonEval = ALLOC_CLEAR_ONE(BalloonEval);
-               balloonEvalForTerm = TRUE;
-           }
-           if (balloonEval != NULL)
-           {
-               general_beval_cb(balloonEval, 0);
-               setcursor();
-               out_flush();
-           }
-       }
-       else if (next_due == -1 || next_due > this_due)
-           next_due = this_due;
-    }
-#endif
-#ifdef FEAT_TERMINAL
-    // Some terminal windows may need their buffer updated.
-    next_due = term_check_timers(next_due, &now);
-#endif
-
-    return current_id != last_timer_id ? 1 : next_due;
-}
-
-/*
- * Find a timer by ID.  Returns NULL if not found;
- */
-    static timer_T *
-find_timer(long id)
-{
-    timer_T *timer;
-
-    if (id >= 0)
-    {
-       for (timer = first_timer; timer != NULL; timer = timer->tr_next)
-           if (timer->tr_id == id)
-               return timer;
-    }
-    return NULL;
-}
-
-
-/*
- * Stop a timer and delete it.
- */
-    void
-stop_timer(timer_T *timer)
-{
-    if (timer->tr_firing)
-       // Free the timer after the callback returns.
-       timer->tr_id = -1;
-    else
-    {
-       remove_timer(timer);
-       free_timer(timer);
-    }
-}
-
-    static void
-stop_all_timers(void)
-{
-    timer_T *timer;
-    timer_T *timer_next;
-
-    for (timer = first_timer; timer != NULL; timer = timer_next)
-    {
-       timer_next = timer->tr_next;
-       stop_timer(timer);
-    }
-}
-
-    static void
-add_timer_info(typval_T *rettv, timer_T *timer)
-{
-    list_T     *list = rettv->vval.v_list;
-    dict_T     *dict = dict_alloc();
-    dictitem_T *di;
-    long       remaining;
-    proftime_T now;
-
-    if (dict == NULL)
-       return;
-    list_append_dict(list, dict);
-
-    dict_add_number(dict, "id", timer->tr_id);
-    dict_add_number(dict, "time", (long)timer->tr_interval);
-
-    profile_start(&now);
-    remaining = proftime_time_left(&timer->tr_due, &now);
-    dict_add_number(dict, "remaining", (long)remaining);
-
-    dict_add_number(dict, "repeat",
-                   (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1));
-    dict_add_number(dict, "paused", (long)(timer->tr_paused));
-
-    di = dictitem_alloc((char_u *)"callback");
-    if (di != NULL)
-    {
-       if (dict_add(dict, di) == FAIL)
-           vim_free(di);
-       else
-           put_callback(&timer->tr_callback, &di->di_tv);
-    }
-}
-
-    static void
-add_timer_info_all(typval_T *rettv)
-{
-    timer_T *timer;
-
-    for (timer = first_timer; timer != NULL; timer = timer->tr_next)
-       if (timer->tr_id != -1)
-           add_timer_info(rettv, timer);
-}
-
-/*
- * Mark references in partials of timers.
- */
-    int
-set_ref_in_timer(int copyID)
-{
-    int                abort = FALSE;
-    timer_T    *timer;
-    typval_T   tv;
-
-    for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next)
-    {
-       if (timer->tr_callback.cb_partial != NULL)
-       {
-           tv.v_type = VAR_PARTIAL;
-           tv.vval.v_partial = timer->tr_callback.cb_partial;
-       }
-       else
-       {
-           tv.v_type = VAR_FUNC;
-           tv.vval.v_string = timer->tr_callback.cb_name;
-       }
-       abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
-    }
-    return abort;
-}
-
-# if defined(EXITFREE) || defined(PROTO)
-    void
-timer_free_all()
-{
-    timer_T *timer;
-
-    while (first_timer != NULL)
-    {
-       timer = first_timer;
-       remove_timer(timer);
-       free_timer(timer);
-    }
-}
-# endif
-
-/*
- * "timer_info([timer])" function
- */
-    void
-f_timer_info(typval_T *argvars, typval_T *rettv)
-{
-    timer_T *timer = NULL;
-
-    if (rettv_list_alloc(rettv) != OK)
-       return;
-    if (argvars[0].v_type != VAR_UNKNOWN)
-    {
-       if (argvars[0].v_type != VAR_NUMBER)
-           emsg(_(e_number_exp));
-       else
-       {
-           timer = find_timer((int)tv_get_number(&argvars[0]));
-           if (timer != NULL)
-               add_timer_info(rettv, timer);
-       }
-    }
-    else
-       add_timer_info_all(rettv);
-}
-
-/*
- * "timer_pause(timer, paused)" function
- */
-    void
-f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED)
-{
-    timer_T    *timer = NULL;
-    int                paused = (int)tv_get_number(&argvars[1]);
-
-    if (argvars[0].v_type != VAR_NUMBER)
-       emsg(_(e_number_exp));
-    else
-    {
-       timer = find_timer((int)tv_get_number(&argvars[0]));
-       if (timer != NULL)
-           timer->tr_paused = paused;
-    }
-}
-
-/*
- * "timer_start(time, callback [, options])" function
- */
-    void
-f_timer_start(typval_T *argvars, typval_T *rettv)
-{
-    long       msec = (long)tv_get_number(&argvars[0]);
-    timer_T    *timer;
-    int                repeat = 0;
-    callback_T callback;
-    dict_T     *dict;
-
-    rettv->vval.v_number = -1;
-    if (check_secure())
-       return;
-    if (argvars[2].v_type != VAR_UNKNOWN)
-    {
-       if (argvars[2].v_type != VAR_DICT
-                                  || (dict = argvars[2].vval.v_dict) == NULL)
-       {
-           semsg(_(e_invarg2), tv_get_string(&argvars[2]));
-           return;
-       }
-       if (dict_find(dict, (char_u *)"repeat", -1) != NULL)
-           repeat = dict_get_number(dict, (char_u *)"repeat");
-    }
-
-    callback = get_callback(&argvars[1]);
-    if (callback.cb_name == NULL)
-       return;
-
-    timer = create_timer(msec, repeat);
-    if (timer == NULL)
-       free_callback(&callback);
-    else
-    {
-       set_callback(&timer->tr_callback, &callback);
-       rettv->vval.v_number = (varnumber_T)timer->tr_id;
-    }
-}
-
-/*
- * "timer_stop(timer)" function
- */
-    void
-f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED)
-{
-    timer_T *timer;
-
-    if (argvars[0].v_type != VAR_NUMBER)
-    {
-       emsg(_(e_number_exp));
-       return;
-    }
-    timer = find_timer((int)tv_get_number(&argvars[0]));
-    if (timer != NULL)
-       stop_timer(timer);
-}
-
-/*
- * "timer_stopall()" function
- */
-    void
-f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
-{
-    stop_all_timers();
-}
-
-# endif // FEAT_TIMERS
-
-#endif // FEAT_EVAL
-
 /*
  * If 'autowrite' option set, try to write the file.
  * Careful: autocommands may make "buf" invalid!
index c747aba3d174ad46417f6a7c492f06e83c31b4b6..2d61c0682e599543d0dea3ef004c1b99387c2385 100644 (file)
@@ -3669,110 +3669,6 @@ check_swap_exists_action(void)
 
 #endif // NO_VIM_MAIN
 
-#if defined(STARTUPTIME) || defined(PROTO)
-static struct timeval  prev_timeval;
-
-# ifdef MSWIN
-/*
- * Windows doesn't have gettimeofday(), although it does have struct timeval.
- */
-    static int
-gettimeofday(struct timeval *tv, char *dummy UNUSED)
-{
-    long t = clock();
-    tv->tv_sec = t / CLOCKS_PER_SEC;
-    tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC;
-    return 0;
-}
-# endif
-
-/*
- * Save the previous time before doing something that could nest.
- * set "*tv_rel" to the time elapsed so far.
- */
-    void
-time_push(void *tv_rel, void *tv_start)
-{
-    *((struct timeval *)tv_rel) = prev_timeval;
-    gettimeofday(&prev_timeval, NULL);
-    ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec
-                                       - ((struct timeval *)tv_rel)->tv_usec;
-    ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec
-                                        - ((struct timeval *)tv_rel)->tv_sec;
-    if (((struct timeval *)tv_rel)->tv_usec < 0)
-    {
-       ((struct timeval *)tv_rel)->tv_usec += 1000000;
-       --((struct timeval *)tv_rel)->tv_sec;
-    }
-    *(struct timeval *)tv_start = prev_timeval;
-}
-
-/*
- * Compute the previous time after doing something that could nest.
- * Subtract "*tp" from prev_timeval;
- * Note: The arguments are (void *) to avoid trouble with systems that don't
- * have struct timeval.
- */
-    void
-time_pop(
-    void       *tp)    // actually (struct timeval *)
-{
-    prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec;
-    prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec;
-    if (prev_timeval.tv_usec < 0)
-    {
-       prev_timeval.tv_usec += 1000000;
-       --prev_timeval.tv_sec;
-    }
-}
-
-    static void
-time_diff(struct timeval *then, struct timeval *now)
-{
-    long       usec;
-    long       msec;
-
-    usec = now->tv_usec - then->tv_usec;
-    msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L,
-    usec = usec % 1000L;
-    fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L);
-}
-
-    void
-time_msg(
-    char       *mesg,
-    void       *tv_start)  // only for do_source: start time; actually
-                           // (struct timeval *)
-{
-    static struct timeval      start;
-    struct timeval             now;
-
-    if (time_fd != NULL)
-    {
-       if (strstr(mesg, "STARTING") != NULL)
-       {
-           gettimeofday(&start, NULL);
-           prev_timeval = start;
-           fprintf(time_fd, "\n\ntimes in msec\n");
-           fprintf(time_fd, " clock   self+sourced   self:  sourced script\n");
-           fprintf(time_fd, " clock   elapsed:              other lines\n\n");
-       }
-       gettimeofday(&now, NULL);
-       time_diff(&start, &now);
-       if (((struct timeval *)tv_start) != NULL)
-       {
-           fprintf(time_fd, "  ");
-           time_diff(((struct timeval *)tv_start), &now);
-       }
-       fprintf(time_fd, "  ");
-       time_diff(&prev_timeval, &now);
-       prev_timeval = now;
-       fprintf(time_fd, ": %s\n", mesg);
-    }
-}
-
-#endif
-
 #if !defined(NO_VIM_MAIN) && defined(FEAT_EVAL)
     static void
 set_progpath(char_u *argv0)
index c6db9136fe9596a2fff7b6477e5cbf2c96ac54aa..b409eb5553f0ca2a4b8fbf394f0d8acb7361c629 100644 (file)
@@ -2080,94 +2080,6 @@ get_b0_dict(char_u *fname, dict_T *d)
 }
 #endif
 
-/*
- * Cache of the current timezone name as retrieved from TZ, or an empty string
- * where unset, up to 64 octets long including trailing null byte.
- */
-#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET)
-static char    tz_cache[64];
-#endif
-
-/*
- * Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the
- * latter version preferred for reentrancy.
- *
- * If we use localtime_r(3) and we have tzset(3) available, check to see if the
- * environment variable TZ has changed since the last run, and call tzset(3) to
- * update the global timezone variables if it has.  This is because the POSIX
- * standard doesn't require localtime_r(3) implementations to do that as it
- * does with localtime(3), and we don't want to call tzset(3) every time.
- */
-    struct tm *
-vim_localtime(
-    const time_t       *timep,         // timestamp for local representation
-    struct tm          *result UNUSED) // pointer to caller return buffer
-{
-#ifdef HAVE_LOCALTIME_R
-# ifdef HAVE_TZSET
-    char               *tz;            // pointer for TZ environment var
-
-    tz = (char *)mch_getenv((char_u *)"TZ");
-    if (tz == NULL)
-       tz = "";
-    if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0)
-    {
-       tzset();
-       vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1);
-    }
-# endif        // HAVE_TZSET
-    return localtime_r(timep, result);
-#else
-    return localtime(timep);
-#endif // HAVE_LOCALTIME_R
-}
-
-/*
- * Replacement for ctime(), which is not safe to use.
- * Requires strftime(), otherwise returns "(unknown)".
- * If "thetime" is invalid returns "(invalid)".  Never returns NULL.
- * When "add_newline" is TRUE add a newline like ctime() does.
- * Uses a static buffer.
- */
-    char *
-get_ctime(time_t thetime, int add_newline)
-{
-    static char buf[50];
-#ifdef HAVE_STRFTIME
-    struct tm  tmval;
-    struct tm  *curtime;
-
-    curtime = vim_localtime(&thetime, &tmval);
-    // MSVC returns NULL for an invalid value of seconds.
-    if (curtime == NULL)
-       vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);
-    else
-    {
-       (void)strftime(buf, sizeof(buf) - 1, _("%a %b %d %H:%M:%S %Y"),
-                                                                   curtime);
-# ifdef MSWIN
-       if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-       {
-           char_u      *to_free = NULL;
-           int         len;
-
-           acp_to_enc((char_u *)buf, (int)strlen(buf), &to_free, &len);
-           if (to_free != NULL)
-           {
-               STRCPY(buf, to_free);
-               vim_free(to_free);
-           }
-       }
-# endif
-    }
-#else
-    STRCPY(buf, "(unknown)");
-#endif
-    if (add_newline)
-       STRCAT(buf, "\n");
-    return buf;
-}
-
 /*
  * Give information about an existing swap file.
  * Returns timestamp (0 when unknown).
index bb7137dc3a0e18bccebc56821bdfb9d39da7cb7b..635b87be2aa5b029ef47da98407444d8028d33ca 100644 (file)
@@ -2597,34 +2597,3 @@ path_with_url(char_u *fname)
        ;
     return path_is_url(p);
 }
-
-/*
- * Put timestamp "tt" in "buf[buflen]" in a nice format.
- */
-    void
-add_time(char_u *buf, size_t buflen, time_t tt)
-{
-#ifdef HAVE_STRFTIME
-    struct tm  tmval;
-    struct tm  *curtime;
-
-    if (vim_time() - tt >= 100)
-    {
-       curtime = vim_localtime(&tt, &tmval);
-       if (vim_time() - tt < (60L * 60L * 12L))
-           // within 12 hours
-           (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
-       else
-           // longer ago
-           (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
-    }
-    else
-#endif
-    {
-       long seconds = (long)(vim_time() - tt);
-
-       vim_snprintf((char *)buf, buflen,
-               NGETTEXT("%ld second ago", "%ld seconds ago", seconds),
-               seconds);
-    }
-}
index c0208de26e2346464fa80d9db21a9f1492b0220c..6ef420cabfbaf7c243a29192d1d6331ab2bc4004 100644 (file)
@@ -4126,26 +4126,6 @@ get4c(FILE *fd)
     return (int)n;
 }
 
-/*
- * Read 8 bytes from "fd" and turn them into a time_T, MSB first.
- * Returns -1 when encountering EOF.
- */
-    time_T
-get8ctime(FILE *fd)
-{
-    int                c;
-    time_T     n = 0;
-    int                i;
-
-    for (i = 0; i < 8; ++i)
-    {
-       c = getc(fd);
-       if (c == EOF) return -1;
-       n = (n << 8) + c;
-    }
-    return n;
-}
-
 /*
  * Read a string of length "cnt" from "fd" into allocated memory.
  * Returns NULL when out of memory or unable to read that many bytes.
@@ -4191,68 +4171,6 @@ put_bytes(FILE *fd, long_u nr, int len)
     return OK;
 }
 
-#ifdef _MSC_VER
-# if (_MSC_VER <= 1200)
-// This line is required for VC6 without the service pack.  Also see the
-// matching #pragma below.
- #  pragma optimize("", off)
-# endif
-#endif
-
-/*
- * Write time_T to file "fd" in 8 bytes.
- * Returns FAIL when the write failed.
- */
-    int
-put_time(FILE *fd, time_T the_time)
-{
-    char_u     buf[8];
-
-    time_to_bytes(the_time, buf);
-    return fwrite(buf, (size_t)8, (size_t)1, fd) == 1 ? OK : FAIL;
-}
-
-/*
- * Write time_T to "buf[8]".
- */
-    void
-time_to_bytes(time_T the_time, char_u *buf)
-{
-    int                c;
-    int                i;
-    int                bi = 0;
-    time_T     wtime = the_time;
-
-    // time_T can be up to 8 bytes in size, more than long_u, thus we
-    // can't use put_bytes() here.
-    // Another problem is that ">>" may do an arithmetic shift that keeps the
-    // sign.  This happens for large values of wtime.  A cast to long_u may
-    // truncate if time_T is 8 bytes.  So only use a cast when it is 4 bytes,
-    // it's safe to assume that long_u is 4 bytes or more and when using 8
-    // bytes the top bit won't be set.
-    for (i = 7; i >= 0; --i)
-    {
-       if (i + 1 > (int)sizeof(time_T))
-           // ">>" doesn't work well when shifting more bits than avail
-           buf[bi++] = 0;
-       else
-       {
-#if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4
-           c = (int)(wtime >> (i * 8));
-#else
-           c = (int)((long_u)wtime >> (i * 8));
-#endif
-           buf[bi++] = c;
-       }
-    }
-}
-
-#ifdef _MSC_VER
-# if (_MSC_VER <= 1200)
- #  pragma optimize("", on)
-# endif
-#endif
-
 #endif
 
 #if defined(FEAT_QUICKFIX) || defined(FEAT_SPELL) || defined(PROTO)
index 7836c528e55ed7b9b4a837a99f64cce0765a3a3a..31f75cfd8304087c8b7c69e4acfe9b315baa45fd 100644 (file)
@@ -221,6 +221,7 @@ void mbyte_im_set_active(int active_arg);
 #  include "textprop.pro"
 # endif
 # include "testing.pro"
+# include "time.pro"
 # include "ui.pro"
 # include "undo.pro"
 # include "usercmd.pro"
index 3693cf4265e8cadd04ef67f7c4d3d7b318efafdc..92887a6cf7f7741fa1e099c732f0a7c48efdd588 100644 (file)
@@ -9,7 +9,6 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out);
 void do_shell(char_u *cmd, int flags);
 char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp);
 void append_redir(char_u *buf, int buflen, char_u *opt, char_u *fname);
-time_T vim_time(void);
 void do_fixdel(exarg_T *eap);
 void print_line_no_prefix(linenr_T lnum, int use_number, int list);
 void print_line(linenr_T lnum, int use_number, int list);
index 9f694da93be4f3f6e255f5a285c36b14d691a732..b9d1929f7dd87b24e00adcdfe1c691893655951a 100644 (file)
@@ -1,15 +1,4 @@
 /* ex_cmds2.c */
-long proftime_time_left(proftime_T *due, proftime_T *now);
-timer_T *create_timer(long msec, int repeat);
-long check_due_timer(void);
-void stop_timer(timer_T *timer);
-int set_ref_in_timer(int copyID);
-void timer_free_all(void);
-void f_timer_info(typval_T *argvars, typval_T *rettv);
-void f_timer_pause(typval_T *argvars, typval_T *rettv);
-void f_timer_start(typval_T *argvars, typval_T *rettv);
-void f_timer_stop(typval_T *argvars, typval_T *rettv);
-void f_timer_stopall(typval_T *argvars, typval_T *rettv);
 int autowrite(buf_T *buf, int forceit);
 void autowrite_all(void);
 int check_changed(buf_T *buf, int flags);
index c663cd2b15252a0b2c68abf0d6589e860b48db92..5fa96c3903a8acbbe38f99ff7c249b4f2d99ffe2 100644 (file)
@@ -12,9 +12,6 @@ void getout_preserve_modified(int exitval);
 void getout(int exitval);
 int process_env(char_u *env, int is_viminit);
 void mainerr_arg_missing(char_u *str);
-void time_push(void *tv_rel, void *tv_start);
-void time_pop(void *tp);
-void time_msg(char *mesg, void *tv_start);
 void server_to_input_buf(char_u *str);
 char_u *eval_client_expr_to_string(char_u *expr);
 int sendToLocalVim(char_u *cmd, int asExpr, char_u **result);
index 663930dabdf3953bc60ae28d4d56ca80e4abc424..113417042ee8f1e63dcc287aeda81ac705ebe356 100644 (file)
@@ -13,8 +13,6 @@ void ml_recover(int checkext);
 int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
 char_u *make_percent_swname(char_u *dir, char_u *name);
 void get_b0_dict(char_u *fname, dict_T *d);
-struct tm *vim_localtime(const time_t *timep, struct tm *result);
-char *get_ctime(time_t thetime, int add_newline);
 void ml_sync_all(int check_file, int check_char);
 void ml_preserve(buf_T *buf, int message);
 char_u *ml_get(linenr_T lnum);
index e4f2c3d8b608097d44b26cd573080423d98596f9..1327701e0ac2aa2267ceb863f82979922334f05f 100644 (file)
@@ -47,5 +47,4 @@ int goto_im(void);
 char_u *get_isolated_shell_name(void);
 int path_is_url(char_u *p);
 int path_with_url(char_u *fname);
-void add_time(char_u *buf, size_t buflen, time_t tt);
 /* vim: set ft=c : */
index a52b462804ef628def03a9140e6284b2475f63e4..6c047f332d0c0754bf18e4de8202a411b0335676 100644 (file)
@@ -94,11 +94,8 @@ int filewritable(char_u *fname);
 int get2c(FILE *fd);
 int get3c(FILE *fd);
 int get4c(FILE *fd);
-time_T get8ctime(FILE *fd);
 char_u *read_string(FILE *fd, int cnt);
 int put_bytes(FILE *fd, long_u nr, int len);
-int put_time(FILE *fd, time_T the_time);
-void time_to_bytes(time_T the_time, char_u *buf);
 int has_non_ascii(char_u *s);
 int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
 int build_argv_from_string(char_u *cmd, char ***argv, int *argc);
diff --git a/src/proto/time.pro b/src/proto/time.pro
new file mode 100644 (file)
index 0000000..becafea
--- /dev/null
@@ -0,0 +1,28 @@
+/* time.c */
+char *get_ctime(time_t thetime, int add_newline);
+time_T vim_time(void);
+void f_localtime(typval_T *argvars, typval_T *rettv);
+void f_reltime(typval_T *argvars, typval_T *rettv);
+void f_reltimefloat(typval_T *argvars, typval_T *rettv);
+void f_reltimestr(typval_T *argvars, typval_T *rettv);
+void f_strftime(typval_T *argvars, typval_T *rettv);
+void f_strptime(typval_T *argvars, typval_T *rettv);
+long proftime_time_left(proftime_T *due, proftime_T *now);
+timer_T *create_timer(long msec, int repeat);
+long check_due_timer(void);
+void stop_timer(timer_T *timer);
+int set_ref_in_timer(int copyID);
+void timer_free_all(void);
+void f_timer_info(typval_T *argvars, typval_T *rettv);
+void f_timer_pause(typval_T *argvars, typval_T *rettv);
+void f_timer_start(typval_T *argvars, typval_T *rettv);
+void f_timer_stop(typval_T *argvars, typval_T *rettv);
+void f_timer_stopall(typval_T *argvars, typval_T *rettv);
+void time_push(void *tv_rel, void *tv_start);
+void time_pop(void *tp);
+void time_msg(char *mesg, void *tv_start);
+time_T get8ctime(FILE *fd);
+int put_time(FILE *fd, time_T the_time);
+void time_to_bytes(time_T the_time, char_u *buf);
+void add_time(char_u *buf, size_t buflen, time_t tt);
+/* vim: set ft=c : */
diff --git a/src/time.c b/src/time.c
new file mode 100644 (file)
index 0000000..2706ac2
--- /dev/null
@@ -0,0 +1,1041 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved   by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * time.c: functions related to time and timers
+ */
+
+#include "vim.h"
+
+/*
+ * Cache of the current timezone name as retrieved from TZ, or an empty string
+ * where unset, up to 64 octets long including trailing null byte.
+ */
+#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET)
+static char    tz_cache[64];
+#endif
+
+/*
+ * Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the
+ * latter version preferred for reentrancy.
+ *
+ * If we use localtime_r(3) and we have tzset(3) available, check to see if the
+ * environment variable TZ has changed since the last run, and call tzset(3) to
+ * update the global timezone variables if it has.  This is because the POSIX
+ * standard doesn't require localtime_r(3) implementations to do that as it
+ * does with localtime(3), and we don't want to call tzset(3) every time.
+ */
+    static struct tm *
+vim_localtime(
+    const time_t       *timep,         // timestamp for local representation
+    struct tm          *result UNUSED) // pointer to caller return buffer
+{
+#ifdef HAVE_LOCALTIME_R
+# ifdef HAVE_TZSET
+    char               *tz;            // pointer for TZ environment var
+
+    tz = (char *)mch_getenv((char_u *)"TZ");
+    if (tz == NULL)
+       tz = "";
+    if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0)
+    {
+       tzset();
+       vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1);
+    }
+# endif        // HAVE_TZSET
+    return localtime_r(timep, result);
+#else
+    return localtime(timep);
+#endif // HAVE_LOCALTIME_R
+}
+
+/*
+ * Return the current time in seconds.  Calls time(), unless test_settime()
+ * was used.
+ */
+    time_T
+vim_time(void)
+{
+# ifdef FEAT_EVAL
+    return time_for_testing == 0 ? time(NULL) : time_for_testing;
+# else
+    return time(NULL);
+# endif
+}
+
+/*
+ * Replacement for ctime(), which is not safe to use.
+ * Requires strftime(), otherwise returns "(unknown)".
+ * If "thetime" is invalid returns "(invalid)".  Never returns NULL.
+ * When "add_newline" is TRUE add a newline like ctime() does.
+ * Uses a static buffer.
+ */
+    char *
+get_ctime(time_t thetime, int add_newline)
+{
+    static char buf[50];
+#ifdef HAVE_STRFTIME
+    struct tm  tmval;
+    struct tm  *curtime;
+
+    curtime = vim_localtime(&thetime, &tmval);
+    // MSVC returns NULL for an invalid value of seconds.
+    if (curtime == NULL)
+       vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);
+    else
+    {
+       (void)strftime(buf, sizeof(buf) - 1, _("%a %b %d %H:%M:%S %Y"),
+                                                                   curtime);
+# ifdef MSWIN
+       if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+       {
+           char_u      *to_free = NULL;
+           int         len;
+
+           acp_to_enc((char_u *)buf, (int)strlen(buf), &to_free, &len);
+           if (to_free != NULL)
+           {
+               STRCPY(buf, to_free);
+               vim_free(to_free);
+           }
+       }
+# endif
+    }
+#else
+    STRCPY(buf, "(unknown)");
+#endif
+    if (add_newline)
+       STRCAT(buf, "\n");
+    return buf;
+}
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+
+#if defined(MACOS_X)
+# include <time.h>     // for time_t
+#endif
+
+/*
+ * "localtime()" function
+ */
+    void
+f_localtime(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    rettv->vval.v_number = (varnumber_T)time(NULL);
+}
+
+# if defined(FEAT_RELTIME)
+/*
+ * Convert a List to proftime_T.
+ * Return FAIL when there is something wrong.
+ */
+    static int
+list2proftime(typval_T *arg, proftime_T *tm)
+{
+    long       n1, n2;
+    int        error = FALSE;
+
+    if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL
+                                            || arg->vval.v_list->lv_len != 2)
+       return FAIL;
+    n1 = list_find_nr(arg->vval.v_list, 0L, &error);
+    n2 = list_find_nr(arg->vval.v_list, 1L, &error);
+#  ifdef MSWIN
+    tm->HighPart = n1;
+    tm->LowPart = n2;
+#  else
+    tm->tv_sec = n1;
+    tm->tv_usec = n2;
+#  endif
+    return error ? FAIL : OK;
+}
+# endif // FEAT_RELTIME
+
+/*
+ * "reltime()" function
+ */
+    void
+f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+# ifdef FEAT_RELTIME
+    proftime_T res;
+    proftime_T start;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+    {
+       // No arguments: get current time.
+       profile_start(&res);
+    }
+    else if (argvars[1].v_type == VAR_UNKNOWN)
+    {
+       if (list2proftime(&argvars[0], &res) == FAIL)
+           return;
+       profile_end(&res);
+    }
+    else
+    {
+       // Two arguments: compute the difference.
+       if (list2proftime(&argvars[0], &start) == FAIL
+               || list2proftime(&argvars[1], &res) == FAIL)
+           return;
+       profile_sub(&res, &start);
+    }
+
+    if (rettv_list_alloc(rettv) == OK)
+    {
+       long    n1, n2;
+
+#  ifdef MSWIN
+       n1 = res.HighPart;
+       n2 = res.LowPart;
+#  else
+       n1 = res.tv_sec;
+       n2 = res.tv_usec;
+#  endif
+       list_append_number(rettv->vval.v_list, (varnumber_T)n1);
+       list_append_number(rettv->vval.v_list, (varnumber_T)n2);
+    }
+# endif
+}
+
+# ifdef FEAT_FLOAT
+/*
+ * "reltimefloat()" function
+ */
+    void
+f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv)
+{
+#  ifdef FEAT_RELTIME
+    proftime_T tm;
+#  endif
+
+    rettv->v_type = VAR_FLOAT;
+    rettv->vval.v_float = 0;
+#  ifdef FEAT_RELTIME
+    if (list2proftime(&argvars[0], &tm) == OK)
+       rettv->vval.v_float = profile_float(&tm);
+#  endif
+}
+# endif
+
+/*
+ * "reltimestr()" function
+ */
+    void
+f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv)
+{
+# ifdef FEAT_RELTIME
+    proftime_T tm;
+# endif
+
+    rettv->v_type = VAR_STRING;
+    rettv->vval.v_string = NULL;
+# ifdef FEAT_RELTIME
+    if (list2proftime(&argvars[0], &tm) == OK)
+       rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
+# endif
+}
+
+# if defined(HAVE_STRFTIME) || defined(PROTO)
+/*
+ * "strftime({format}[, {time}])" function
+ */
+    void
+f_strftime(typval_T *argvars, typval_T *rettv)
+{
+    char_u     result_buf[256];
+    struct tm  tmval;
+    struct tm  *curtime;
+    time_t     seconds;
+    char_u     *p;
+
+    rettv->v_type = VAR_STRING;
+
+    p = tv_get_string(&argvars[0]);
+    if (argvars[1].v_type == VAR_UNKNOWN)
+       seconds = time(NULL);
+    else
+       seconds = (time_t)tv_get_number(&argvars[1]);
+    curtime = vim_localtime(&seconds, &tmval);
+    // MSVC returns NULL for an invalid value of seconds.
+    if (curtime == NULL)
+       rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
+    else
+    {
+       vimconv_T   conv;
+       char_u      *enc;
+
+       conv.vc_type = CONV_NONE;
+       enc = enc_locale();
+       convert_setup(&conv, p_enc, enc);
+       if (conv.vc_type != CONV_NONE)
+           p = string_convert(&conv, p, NULL);
+       if (p != NULL)
+           (void)strftime((char *)result_buf, sizeof(result_buf),
+                                                         (char *)p, curtime);
+       else
+           result_buf[0] = NUL;
+
+       if (conv.vc_type != CONV_NONE)
+           vim_free(p);
+       convert_setup(&conv, enc, p_enc);
+       if (conv.vc_type != CONV_NONE)
+           rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
+       else
+           rettv->vval.v_string = vim_strsave(result_buf);
+
+       // Release conversion descriptors
+       convert_setup(&conv, NULL, NULL);
+       vim_free(enc);
+    }
+}
+# endif
+
+# if defined(HAVE_STRPTIME) || defined(PROTO)
+/*
+ * "strptime({format}, {timestring})" function
+ */
+    void
+f_strptime(typval_T *argvars, typval_T *rettv)
+{
+    struct tm  tmval;
+    char_u     *fmt;
+    char_u     *str;
+    vimconv_T   conv;
+    char_u     *enc;
+
+    vim_memset(&tmval, NUL, sizeof(tmval));
+    fmt = tv_get_string(&argvars[0]);
+    str = tv_get_string(&argvars[1]);
+
+    conv.vc_type = CONV_NONE;
+    enc = enc_locale();
+    convert_setup(&conv, p_enc, enc);
+    if (conv.vc_type != CONV_NONE)
+       fmt = string_convert(&conv, fmt, NULL);
+    if (fmt == NULL
+           || strptime((char *)str, (char *)fmt, &tmval) == NULL
+           || (rettv->vval.v_number = mktime(&tmval)) == -1)
+       rettv->vval.v_number = 0;
+
+    if (conv.vc_type != CONV_NONE)
+       vim_free(fmt);
+    convert_setup(&conv, NULL, NULL);
+    vim_free(enc);
+}
+# endif
+
+# if defined(FEAT_TIMERS) || defined(PROTO)
+static timer_T *first_timer = NULL;
+static long    last_timer_id = 0;
+
+/*
+ * Return time left until "due".  Negative if past "due".
+ */
+    long
+proftime_time_left(proftime_T *due, proftime_T *now)
+{
+#  ifdef MSWIN
+    LARGE_INTEGER fr;
+
+    if (now->QuadPart > due->QuadPart)
+       return 0;
+    QueryPerformanceFrequency(&fr);
+    return (long)(((double)(due->QuadPart - now->QuadPart)
+                  / (double)fr.QuadPart) * 1000);
+#  else
+    if (now->tv_sec > due->tv_sec)
+       return 0;
+    return (due->tv_sec - now->tv_sec) * 1000
+       + (due->tv_usec - now->tv_usec) / 1000;
+#  endif
+}
+
+/*
+ * Insert a timer in the list of timers.
+ */
+    static void
+insert_timer(timer_T *timer)
+{
+    timer->tr_next = first_timer;
+    timer->tr_prev = NULL;
+    if (first_timer != NULL)
+       first_timer->tr_prev = timer;
+    first_timer = timer;
+    did_add_timer = TRUE;
+}
+
+/*
+ * Take a timer out of the list of timers.
+ */
+    static void
+remove_timer(timer_T *timer)
+{
+    if (timer->tr_prev == NULL)
+       first_timer = timer->tr_next;
+    else
+       timer->tr_prev->tr_next = timer->tr_next;
+    if (timer->tr_next != NULL)
+       timer->tr_next->tr_prev = timer->tr_prev;
+}
+
+    static void
+free_timer(timer_T *timer)
+{
+    free_callback(&timer->tr_callback);
+    vim_free(timer);
+}
+
+/*
+ * Create a timer and return it.  NULL if out of memory.
+ * Caller should set the callback.
+ */
+    timer_T *
+create_timer(long msec, int repeat)
+{
+    timer_T    *timer = ALLOC_CLEAR_ONE(timer_T);
+    long       prev_id = last_timer_id;
+
+    if (timer == NULL)
+       return NULL;
+    if (++last_timer_id <= prev_id)
+       // Overflow!  Might cause duplicates...
+       last_timer_id = 0;
+    timer->tr_id = last_timer_id;
+    insert_timer(timer);
+    if (repeat != 0)
+       timer->tr_repeat = repeat - 1;
+    timer->tr_interval = msec;
+
+    profile_setlimit(msec, &timer->tr_due);
+    return timer;
+}
+
+/*
+ * Invoke the callback of "timer".
+ */
+    static void
+timer_callback(timer_T *timer)
+{
+    typval_T   rettv;
+    typval_T   argv[2];
+
+    argv[0].v_type = VAR_NUMBER;
+    argv[0].vval.v_number = (varnumber_T)timer->tr_id;
+    argv[1].v_type = VAR_UNKNOWN;
+
+    call_callback(&timer->tr_callback, -1, &rettv, 1, argv);
+    clear_tv(&rettv);
+}
+
+/*
+ * Call timers that are due.
+ * Return the time in msec until the next timer is due.
+ * Returns -1 if there are no pending timers.
+ */
+    long
+check_due_timer(void)
+{
+    timer_T    *timer;
+    timer_T    *timer_next;
+    long       this_due;
+    long       next_due = -1;
+    proftime_T now;
+    int                did_one = FALSE;
+    int                need_update_screen = FALSE;
+    long       current_id = last_timer_id;
+
+    // Don't run any timers while exiting or dealing with an error.
+    if (exiting || aborting())
+       return next_due;
+
+    profile_start(&now);
+    for (timer = first_timer; timer != NULL && !got_int; timer = timer_next)
+    {
+       timer_next = timer->tr_next;
+
+       if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused)
+           continue;
+       this_due = proftime_time_left(&timer->tr_due, &now);
+       if (this_due <= 1)
+       {
+           // Save and restore a lot of flags, because the timer fires while
+           // waiting for a character, which might be halfway a command.
+           int save_timer_busy = timer_busy;
+           int save_vgetc_busy = vgetc_busy;
+           int save_did_emsg = did_emsg;
+           int save_called_emsg = called_emsg;
+           int save_must_redraw = must_redraw;
+           int save_trylevel = trylevel;
+           int save_did_throw = did_throw;
+           int save_ex_pressedreturn = get_pressedreturn();
+           int save_may_garbage_collect = may_garbage_collect;
+           except_T *save_current_exception = current_exception;
+           vimvars_save_T vvsave;
+
+           // Create a scope for running the timer callback, ignoring most of
+           // the current scope, such as being inside a try/catch.
+           timer_busy = timer_busy > 0 || vgetc_busy > 0;
+           vgetc_busy = 0;
+           called_emsg = 0;
+           did_emsg = FALSE;
+           did_uncaught_emsg = FALSE;
+           must_redraw = 0;
+           trylevel = 0;
+           did_throw = FALSE;
+           current_exception = NULL;
+           may_garbage_collect = FALSE;
+           save_vimvars(&vvsave);
+
+           timer->tr_firing = TRUE;
+           timer_callback(timer);
+           timer->tr_firing = FALSE;
+
+           timer_next = timer->tr_next;
+           did_one = TRUE;
+           timer_busy = save_timer_busy;
+           vgetc_busy = save_vgetc_busy;
+           if (did_uncaught_emsg)
+               ++timer->tr_emsg_count;
+           did_emsg = save_did_emsg;
+           called_emsg = save_called_emsg;
+           trylevel = save_trylevel;
+           did_throw = save_did_throw;
+           current_exception = save_current_exception;
+           restore_vimvars(&vvsave);
+           if (must_redraw != 0)
+               need_update_screen = TRUE;
+           must_redraw = must_redraw > save_must_redraw
+                                             ? must_redraw : save_must_redraw;
+           set_pressedreturn(save_ex_pressedreturn);
+           may_garbage_collect = save_may_garbage_collect;
+
+           // Only fire the timer again if it repeats and stop_timer() wasn't
+           // called while inside the callback (tr_id == -1).
+           if (timer->tr_repeat != 0 && timer->tr_id != -1
+                   && timer->tr_emsg_count < 3)
+           {
+               profile_setlimit(timer->tr_interval, &timer->tr_due);
+               this_due = proftime_time_left(&timer->tr_due, &now);
+               if (this_due < 1)
+                   this_due = 1;
+               if (timer->tr_repeat > 0)
+                   --timer->tr_repeat;
+           }
+           else
+           {
+               this_due = -1;
+               remove_timer(timer);
+               free_timer(timer);
+           }
+       }
+       if (this_due > 0 && (next_due == -1 || next_due > this_due))
+           next_due = this_due;
+    }
+
+    if (did_one)
+       redraw_after_callback(need_update_screen);
+
+#ifdef FEAT_BEVAL_TERM
+    if (bevalexpr_due_set)
+    {
+       this_due = proftime_time_left(&bevalexpr_due, &now);
+       if (this_due <= 1)
+       {
+           bevalexpr_due_set = FALSE;
+           if (balloonEval == NULL)
+           {
+               balloonEval = ALLOC_CLEAR_ONE(BalloonEval);
+               balloonEvalForTerm = TRUE;
+           }
+           if (balloonEval != NULL)
+           {
+               general_beval_cb(balloonEval, 0);
+               setcursor();
+               out_flush();
+           }
+       }
+       else if (next_due == -1 || next_due > this_due)
+           next_due = this_due;
+    }
+#endif
+#ifdef FEAT_TERMINAL
+    // Some terminal windows may need their buffer updated.
+    next_due = term_check_timers(next_due, &now);
+#endif
+
+    return current_id != last_timer_id ? 1 : next_due;
+}
+
+/*
+ * Find a timer by ID.  Returns NULL if not found;
+ */
+    static timer_T *
+find_timer(long id)
+{
+    timer_T *timer;
+
+    if (id >= 0)
+    {
+       for (timer = first_timer; timer != NULL; timer = timer->tr_next)
+           if (timer->tr_id == id)
+               return timer;
+    }
+    return NULL;
+}
+
+
+/*
+ * Stop a timer and delete it.
+ */
+    void
+stop_timer(timer_T *timer)
+{
+    if (timer->tr_firing)
+       // Free the timer after the callback returns.
+       timer->tr_id = -1;
+    else
+    {
+       remove_timer(timer);
+       free_timer(timer);
+    }
+}
+
+    static void
+stop_all_timers(void)
+{
+    timer_T *timer;
+    timer_T *timer_next;
+
+    for (timer = first_timer; timer != NULL; timer = timer_next)
+    {
+       timer_next = timer->tr_next;
+       stop_timer(timer);
+    }
+}
+
+    static void
+add_timer_info(typval_T *rettv, timer_T *timer)
+{
+    list_T     *list = rettv->vval.v_list;
+    dict_T     *dict = dict_alloc();
+    dictitem_T *di;
+    long       remaining;
+    proftime_T now;
+
+    if (dict == NULL)
+       return;
+    list_append_dict(list, dict);
+
+    dict_add_number(dict, "id", timer->tr_id);
+    dict_add_number(dict, "time", (long)timer->tr_interval);
+
+    profile_start(&now);
+    remaining = proftime_time_left(&timer->tr_due, &now);
+    dict_add_number(dict, "remaining", (long)remaining);
+
+    dict_add_number(dict, "repeat",
+                   (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1));
+    dict_add_number(dict, "paused", (long)(timer->tr_paused));
+
+    di = dictitem_alloc((char_u *)"callback");
+    if (di != NULL)
+    {
+       if (dict_add(dict, di) == FAIL)
+           vim_free(di);
+       else
+           put_callback(&timer->tr_callback, &di->di_tv);
+    }
+}
+
+    static void
+add_timer_info_all(typval_T *rettv)
+{
+    timer_T *timer;
+
+    for (timer = first_timer; timer != NULL; timer = timer->tr_next)
+       if (timer->tr_id != -1)
+           add_timer_info(rettv, timer);
+}
+
+/*
+ * Mark references in partials of timers.
+ */
+    int
+set_ref_in_timer(int copyID)
+{
+    int                abort = FALSE;
+    timer_T    *timer;
+    typval_T   tv;
+
+    for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next)
+    {
+       if (timer->tr_callback.cb_partial != NULL)
+       {
+           tv.v_type = VAR_PARTIAL;
+           tv.vval.v_partial = timer->tr_callback.cb_partial;
+       }
+       else
+       {
+           tv.v_type = VAR_FUNC;
+           tv.vval.v_string = timer->tr_callback.cb_name;
+       }
+       abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
+    }
+    return abort;
+}
+
+# if defined(EXITFREE) || defined(PROTO)
+    void
+timer_free_all()
+{
+    timer_T *timer;
+
+    while (first_timer != NULL)
+    {
+       timer = first_timer;
+       remove_timer(timer);
+       free_timer(timer);
+    }
+}
+# endif
+
+/*
+ * "timer_info([timer])" function
+ */
+    void
+f_timer_info(typval_T *argvars, typval_T *rettv)
+{
+    timer_T *timer = NULL;
+
+    if (rettv_list_alloc(rettv) != OK)
+       return;
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+       if (argvars[0].v_type != VAR_NUMBER)
+           emsg(_(e_number_exp));
+       else
+       {
+           timer = find_timer((int)tv_get_number(&argvars[0]));
+           if (timer != NULL)
+               add_timer_info(rettv, timer);
+       }
+    }
+    else
+       add_timer_info_all(rettv);
+}
+
+/*
+ * "timer_pause(timer, paused)" function
+ */
+    void
+f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    timer_T    *timer = NULL;
+    int                paused = (int)tv_get_number(&argvars[1]);
+
+    if (argvars[0].v_type != VAR_NUMBER)
+       emsg(_(e_number_exp));
+    else
+    {
+       timer = find_timer((int)tv_get_number(&argvars[0]));
+       if (timer != NULL)
+           timer->tr_paused = paused;
+    }
+}
+
+/*
+ * "timer_start(time, callback [, options])" function
+ */
+    void
+f_timer_start(typval_T *argvars, typval_T *rettv)
+{
+    long       msec = (long)tv_get_number(&argvars[0]);
+    timer_T    *timer;
+    int                repeat = 0;
+    callback_T callback;
+    dict_T     *dict;
+
+    rettv->vval.v_number = -1;
+    if (check_secure())
+       return;
+    if (argvars[2].v_type != VAR_UNKNOWN)
+    {
+       if (argvars[2].v_type != VAR_DICT
+                                  || (dict = argvars[2].vval.v_dict) == NULL)
+       {
+           semsg(_(e_invarg2), tv_get_string(&argvars[2]));
+           return;
+       }
+       if (dict_find(dict, (char_u *)"repeat", -1) != NULL)
+           repeat = dict_get_number(dict, (char_u *)"repeat");
+    }
+
+    callback = get_callback(&argvars[1]);
+    if (callback.cb_name == NULL)
+       return;
+
+    timer = create_timer(msec, repeat);
+    if (timer == NULL)
+       free_callback(&callback);
+    else
+    {
+       set_callback(&timer->tr_callback, &callback);
+       rettv->vval.v_number = (varnumber_T)timer->tr_id;
+    }
+}
+
+/*
+ * "timer_stop(timer)" function
+ */
+    void
+f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    timer_T *timer;
+
+    if (argvars[0].v_type != VAR_NUMBER)
+    {
+       emsg(_(e_number_exp));
+       return;
+    }
+    timer = find_timer((int)tv_get_number(&argvars[0]));
+    if (timer != NULL)
+       stop_timer(timer);
+}
+
+/*
+ * "timer_stopall()" function
+ */
+    void
+f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+    stop_all_timers();
+}
+
+# endif // FEAT_TIMERS
+
+# if defined(STARTUPTIME) || defined(PROTO)
+static struct timeval  prev_timeval;
+
+#  ifdef MSWIN
+/*
+ * Windows doesn't have gettimeofday(), although it does have struct timeval.
+ */
+    static int
+gettimeofday(struct timeval *tv, char *dummy UNUSED)
+{
+    long t = clock();
+    tv->tv_sec = t / CLOCKS_PER_SEC;
+    tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC;
+    return 0;
+}
+#  endif
+
+/*
+ * Save the previous time before doing something that could nest.
+ * set "*tv_rel" to the time elapsed so far.
+ */
+    void
+time_push(void *tv_rel, void *tv_start)
+{
+    *((struct timeval *)tv_rel) = prev_timeval;
+    gettimeofday(&prev_timeval, NULL);
+    ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec
+                                       - ((struct timeval *)tv_rel)->tv_usec;
+    ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec
+                                        - ((struct timeval *)tv_rel)->tv_sec;
+    if (((struct timeval *)tv_rel)->tv_usec < 0)
+    {
+       ((struct timeval *)tv_rel)->tv_usec += 1000000;
+       --((struct timeval *)tv_rel)->tv_sec;
+    }
+    *(struct timeval *)tv_start = prev_timeval;
+}
+
+/*
+ * Compute the previous time after doing something that could nest.
+ * Subtract "*tp" from prev_timeval;
+ * Note: The arguments are (void *) to avoid trouble with systems that don't
+ * have struct timeval.
+ */
+    void
+time_pop(
+    void       *tp)    // actually (struct timeval *)
+{
+    prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec;
+    prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec;
+    if (prev_timeval.tv_usec < 0)
+    {
+       prev_timeval.tv_usec += 1000000;
+       --prev_timeval.tv_sec;
+    }
+}
+
+    static void
+time_diff(struct timeval *then, struct timeval *now)
+{
+    long       usec;
+    long       msec;
+
+    usec = now->tv_usec - then->tv_usec;
+    msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L,
+    usec = usec % 1000L;
+    fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L);
+}
+
+    void
+time_msg(
+    char       *mesg,
+    void       *tv_start)  // only for do_source: start time; actually
+                           // (struct timeval *)
+{
+    static struct timeval      start;
+    struct timeval             now;
+
+    if (time_fd != NULL)
+    {
+       if (strstr(mesg, "STARTING") != NULL)
+       {
+           gettimeofday(&start, NULL);
+           prev_timeval = start;
+           fprintf(time_fd, "\n\ntimes in msec\n");
+           fprintf(time_fd, " clock   self+sourced   self:  sourced script\n");
+           fprintf(time_fd, " clock   elapsed:              other lines\n\n");
+       }
+       gettimeofday(&now, NULL);
+       time_diff(&start, &now);
+       if (((struct timeval *)tv_start) != NULL)
+       {
+           fprintf(time_fd, "  ");
+           time_diff(((struct timeval *)tv_start), &now);
+       }
+       fprintf(time_fd, "  ");
+       time_diff(&prev_timeval, &now);
+       prev_timeval = now;
+       fprintf(time_fd, ": %s\n", mesg);
+    }
+}
+# endif        // STARTUPTIME
+#endif // FEAT_EVAL
+
+#if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
+/*
+ * Read 8 bytes from "fd" and turn them into a time_T, MSB first.
+ * Returns -1 when encountering EOF.
+ */
+    time_T
+get8ctime(FILE *fd)
+{
+    int                c;
+    time_T     n = 0;
+    int                i;
+
+    for (i = 0; i < 8; ++i)
+    {
+       c = getc(fd);
+       if (c == EOF) return -1;
+       n = (n << 8) + c;
+    }
+    return n;
+}
+
+#ifdef _MSC_VER
+# if (_MSC_VER <= 1200)
+// This line is required for VC6 without the service pack.  Also see the
+// matching #pragma below.
+ #  pragma optimize("", off)
+# endif
+#endif
+
+/*
+ * Write time_T to file "fd" in 8 bytes.
+ * Returns FAIL when the write failed.
+ */
+    int
+put_time(FILE *fd, time_T the_time)
+{
+    char_u     buf[8];
+
+    time_to_bytes(the_time, buf);
+    return fwrite(buf, (size_t)8, (size_t)1, fd) == 1 ? OK : FAIL;
+}
+
+/*
+ * Write time_T to "buf[8]".
+ */
+    void
+time_to_bytes(time_T the_time, char_u *buf)
+{
+    int                c;
+    int                i;
+    int                bi = 0;
+    time_T     wtime = the_time;
+
+    // time_T can be up to 8 bytes in size, more than long_u, thus we
+    // can't use put_bytes() here.
+    // Another problem is that ">>" may do an arithmetic shift that keeps the
+    // sign.  This happens for large values of wtime.  A cast to long_u may
+    // truncate if time_T is 8 bytes.  So only use a cast when it is 4 bytes,
+    // it's safe to assume that long_u is 4 bytes or more and when using 8
+    // bytes the top bit won't be set.
+    for (i = 7; i >= 0; --i)
+    {
+       if (i + 1 > (int)sizeof(time_T))
+           // ">>" doesn't work well when shifting more bits than avail
+           buf[bi++] = 0;
+       else
+       {
+#if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4
+           c = (int)(wtime >> (i * 8));
+#else
+           c = (int)((long_u)wtime >> (i * 8));
+#endif
+           buf[bi++] = c;
+       }
+    }
+}
+
+#ifdef _MSC_VER
+# if (_MSC_VER <= 1200)
+ #  pragma optimize("", on)
+# endif
+#endif
+
+#endif
+
+/*
+ * Put timestamp "tt" in "buf[buflen]" in a nice format.
+ */
+    void
+add_time(char_u *buf, size_t buflen, time_t tt)
+{
+#ifdef HAVE_STRFTIME
+    struct tm  tmval;
+    struct tm  *curtime;
+
+    if (vim_time() - tt >= 100)
+    {
+       curtime = vim_localtime(&tt, &tmval);
+       if (vim_time() - tt < (60L * 60L * 12L))
+           // within 12 hours
+           (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
+       else
+           // longer ago
+           (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
+    }
+    else
+#endif
+    {
+       long seconds = (long)(vim_time() - tt);
+
+       vim_snprintf((char *)buf, buflen,
+               NGETTEXT("%ld second ago", "%ld seconds ago", seconds),
+               seconds);
+    }
+}
index 49a4b08ea31e407ff3b4c3473f466f159cf24d05..73ea73690cffc4f8c1d8e2c304f8cefcccef53d8 100644 (file)
@@ -742,6 +742,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    256,
 /**/
     255,
 /**/