Patch 7.4.1372
Problem:    channel read implementation is incomplete.
Solution:   Add ch_read() and options for ch_readraw().
Files:      src/channel.c, src/eval.c, src/structs.h, src/proto/channel.pro,
            src/testdir/test_channel.vim


*** ../vim-7.4.1371/src/channel.c       2016-02-20 18:44:34.320779512 +0100
--- src/channel.c       2016-02-20 19:33:21.437702415 +0100
***************
*** 1696,1707 ****
   * Returns NULL in case of error or timeout.
   */
      char_u *
! channel_read_block(channel_T *channel, int part)
  {
      char_u    *buf;
      char_u    *msg;
      ch_mode_T mode = channel->ch_part[part].ch_mode;
-     int               timeout = channel->ch_part[part].ch_timeout;
      sock_T    fd = channel->ch_part[part].ch_fd;
      char_u    *nl;
  
--- 1696,1706 ----
   * Returns NULL in case of error or timeout.
   */
      char_u *
! channel_read_block(channel_T *channel, int part, int timeout)
  {
      char_u    *buf;
      char_u    *msg;
      ch_mode_T mode = channel->ch_part[part].ch_mode;
      sock_T    fd = channel->ch_part[part].ch_fd;
      char_u    *nl;
  
***************
*** 1753,1768 ****
  /*
   * Read one JSON message with ID "id" from "channel"/"part" and store the
   * result in "rettv".
   * Blocks until the message is received or the timeout is reached.
   */
      int
! channel_read_json_block(channel_T *channel, int part, int id, typval_T 
**rettv)
  {
      int               more;
      sock_T    fd;
  
      ch_log(channel, "Reading JSON");
!     channel->ch_part[part].ch_block_id = id;
      for (;;)
      {
        more = channel_parse_json(channel, part);
--- 1752,1774 ----
  /*
   * Read one JSON message with ID "id" from "channel"/"part" and store the
   * result in "rettv".
+  * When "id" is -1 accept any message;
   * Blocks until the message is received or the timeout is reached.
   */
      int
! channel_read_json_block(
!       channel_T *channel,
!       int part,
!       int timeout,
!       int id,
!       typval_T **rettv)
  {
      int               more;
      sock_T    fd;
  
      ch_log(channel, "Reading JSON");
!     if (id != -1)
!       channel->ch_part[part].ch_block_id = id;
      for (;;)
      {
        more = channel_parse_json(channel, part);
***************
*** 1781,1790 ****
            if (channel_parse_messages())
                continue;
  
!           /* Wait for up to the channel timeout. */
            fd = channel->ch_part[part].ch_fd;
!           if (fd == INVALID_FD || channel_wait(channel, fd,
!                                  channel->ch_part[part].ch_timeout) == FAIL)
                break;
            channel_read(channel, part, "channel_read_json_block");
        }
--- 1787,1795 ----
            if (channel_parse_messages())
                continue;
  
!           /* Wait for up to the timeout. */
            fd = channel->ch_part[part].ch_fd;
!           if (fd == INVALID_FD || channel_wait(channel, fd, timeout) == FAIL)
                break;
            channel_read(channel, part, "channel_read_json_block");
        }
***************
*** 2161,2164 ****
--- 2166,2178 ----
      return channel->ch_part[part].ch_mode;
  }
  
+ /*
+  * Return the timeout of "channel"/"part"
+  */
+     int
+ channel_get_timeout(channel_T *channel, int part)
+ {
+     return channel->ch_part[part].ch_timeout;
+ }
+ 
  #endif /* FEAT_CHANNEL */
*** ../vim-7.4.1371/src/eval.c  2016-02-20 18:18:51.757033160 +0100
--- src/eval.c  2016-02-20 19:40:55.448896485 +0100
***************
*** 507,512 ****
--- 507,513 ----
  static void f_ch_log(typval_T *argvars, typval_T *rettv);
  static void f_ch_logfile(typval_T *argvars, typval_T *rettv);
  static void f_ch_open(typval_T *argvars, typval_T *rettv);
+ static void f_ch_read(typval_T *argvars, typval_T *rettv);
  static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
  static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
  static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
***************
*** 8129,8134 ****
--- 8130,8136 ----
      {"ch_log",                1, 2, f_ch_log},
      {"ch_logfile",    1, 2, f_ch_logfile},
      {"ch_open",               1, 2, f_ch_open},
+     {"ch_read",               1, 2, f_ch_read},
      {"ch_readraw",    1, 2, f_ch_readraw},
      {"ch_sendexpr",   2, 3, f_ch_sendexpr},
      {"ch_sendraw",    2, 3, f_ch_sendraw},
***************
*** 9881,9887 ****
  get_job_options(typval_T *tv, jobopt_T *opt, int supported)
  {
      typval_T  *item;
!     char_u    *mode;
      dict_T    *dict;
      int               todo;
      hashitem_T        *hi;
--- 9883,9889 ----
  get_job_options(typval_T *tv, jobopt_T *opt, int supported)
  {
      typval_T  *item;
!     char_u    *val;
      dict_T    *dict;
      int               todo;
      hashitem_T        *hi;
***************
*** 9909,9926 ****
                if (!(supported & JO_MODE))
                    break;
                opt->jo_set |= JO_MODE;
!               mode = get_tv_string(item);
!               if (STRCMP(mode, "nl") == 0)
                    opt->jo_mode = MODE_NL;
!               else if (STRCMP(mode, "raw") == 0)
                    opt->jo_mode = MODE_RAW;
!               else if (STRCMP(mode, "js") == 0)
                    opt->jo_mode = MODE_JS;
!               else if (STRCMP(mode, "json") == 0)
                    opt->jo_mode = MODE_JSON;
                else
                {
!                   EMSG2(_(e_invarg2), mode);
                    return FAIL;
                }
            }
--- 9911,9928 ----
                if (!(supported & JO_MODE))
                    break;
                opt->jo_set |= JO_MODE;
!               val = get_tv_string(item);
!               if (STRCMP(val, "nl") == 0)
                    opt->jo_mode = MODE_NL;
!               else if (STRCMP(val, "raw") == 0)
                    opt->jo_mode = MODE_RAW;
!               else if (STRCMP(val, "js") == 0)
                    opt->jo_mode = MODE_JS;
!               else if (STRCMP(val, "json") == 0)
                    opt->jo_mode = MODE_JSON;
                else
                {
!                   EMSG2(_(e_invarg2), val);
                    return FAIL;
                }
            }
***************
*** 9950,9955 ****
--- 9952,9978 ----
                opt->jo_set |= JO_TIMEOUT;
                opt->jo_timeout = get_tv_number(item);
            }
+           else if (STRCMP(hi->hi_key, "part") == 0)
+           {
+               if (!(supported & JO_PART))
+                   break;
+               opt->jo_set |= JO_PART;
+               val = get_tv_string(item);
+               if (STRCMP(val, "err") == 0)
+                   opt->jo_part = PART_ERR;
+               else
+               {
+                   EMSG2(_(e_invarg2), val);
+                   return FAIL;
+               }
+           }
+           else if (STRCMP(hi->hi_key, "id") == 0)
+           {
+               if (!(supported & JO_ID))
+                   break;
+               opt->jo_set |= JO_ID;
+               opt->jo_id = get_tv_number(item);
+           }
            else
                break;
            --todo;
***************
*** 10107,10136 ****
  }
  
  /*
!  * "ch_readraw()" function
   */
      static void
! f_ch_readraw(typval_T *argvars, typval_T *rettv)
  {
      channel_T *channel;
      int               part;
  
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     /* TODO: use timeout from the options */
!     /* TODO: read from stderr */
  
      channel = get_channel_arg(&argvars[0]);
      if (channel != NULL)
      {
!       part = channel_part_read(channel);
!       rettv->vval.v_string = channel_read_block(channel, part);
      }
  }
  
  /*
   * common for "sendexpr()" and "sendraw()"
   * Returns the channel if the caller should read the response.
   * Sets "part_read" to the the read fd.
--- 10130,10206 ----
  }
  
  /*
!  * Common for ch_read() and ch_readraw().
   */
      static void
! common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
  {
      channel_T *channel;
      int               part;
+     jobopt_T  opt;
+     int               mode;
+     int               timeout;
+     int               id = -1;
+     typval_T  *listtv = NULL;
  
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
!     opt.jo_set = 0;
!     if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID)
!                                                                     == FAIL)
!       return;
  
      channel = get_channel_arg(&argvars[0]);
      if (channel != NULL)
      {
!       if (opt.jo_set & JO_PART)
!           part = opt.jo_part;
!       else
!           part = channel_part_read(channel);
!       mode = channel_get_mode(channel, part);
!       timeout = channel_get_timeout(channel, part);
!       if (opt.jo_set & JO_TIMEOUT)
!           timeout = opt.jo_timeout;
! 
!       if (raw || mode == MODE_RAW || mode == MODE_NL)
!           rettv->vval.v_string = channel_read_block(channel, part, timeout);
!       else
!       {
!           if (opt.jo_set & JO_ID)
!               id = opt.jo_id;
!           channel_read_json_block(channel, part, timeout, id, &listtv);
!           if (listtv != NULL)
!               *rettv = *listtv;
!           else
!           {
!               rettv->v_type = VAR_SPECIAL;
!               rettv->vval.v_number = VVAL_NONE;
!           }
!       }
      }
  }
  
  /*
+  * "ch_read()" function
+  */
+     static void
+ f_ch_read(typval_T *argvars, typval_T *rettv)
+ {
+     common_channel_read(argvars, rettv, FALSE);
+ }
+ 
+ /*
+  * "ch_readraw()" function
+  */
+     static void
+ f_ch_readraw(typval_T *argvars, typval_T *rettv)
+ {
+     common_channel_read(argvars, rettv, TRUE);
+ }
+ 
+ /*
   * common for "sendexpr()" and "sendraw()"
   * Returns the channel if the caller should read the response.
   * Sets "part_read" to the the read fd.
***************
*** 10177,10182 ****
--- 10247,10253 ----
      ch_mode_T ch_mode;
      int               part_send;
      int               part_read;
+     int               timeout;
  
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
***************
*** 10204,10210 ****
      vim_free(text);
      if (channel != NULL)
      {
!       if (channel_read_json_block(channel, part_read, id, &listtv) == OK)
        {
            list_T *list = listtv->vval.v_list;
  
--- 10275,10284 ----
      vim_free(text);
      if (channel != NULL)
      {
!       /* TODO: timeout from options */
!       timeout = channel_get_timeout(channel, part_read);
!       if (channel_read_json_block(channel, part_read, timeout, id, &listtv)
!                                                                       == OK)
        {
            list_T *list = listtv->vval.v_list;
  
***************
*** 10227,10232 ****
--- 10301,10307 ----
      char_u    *text;
      channel_T *channel;
      int               part_read;
+     int               timeout;
  
      /* return an empty string by default */
      rettv->v_type = VAR_STRING;
***************
*** 10235,10241 ****
      text = get_tv_string_buf(&argvars[1], buf);
      channel = send_common(argvars, text, 0, "sendraw", &part_read);
      if (channel != NULL)
!       rettv->vval.v_string = channel_read_block(channel, part_read);
  }
  
  /*
--- 10310,10320 ----
      text = get_tv_string_buf(&argvars[1], buf);
      channel = send_common(argvars, text, 0, "sendraw", &part_read);
      if (channel != NULL)
!     {
!       /* TODO: timeout from options */
!       timeout = channel_get_timeout(channel, part_read);
!       rettv->vval.v_string = channel_read_block(channel, part_read, timeout);
!     }
  }
  
  /*
*** ../vim-7.4.1371/src/structs.h       2016-02-20 18:18:51.761033118 +0100
--- src/structs.h       2016-02-20 19:26:01.394367922 +0100
***************
*** 1377,1382 ****
--- 1377,1384 ----
  #define JO_CALLBACK   2       /* channel callback */
  #define JO_WAITTIME   4       /* only for ch_open() */
  #define JO_TIMEOUT    8       /* all timeouts */
+ #define JO_PART               16      /* "part" */
+ #define JO_ID         32      /* "id" */
  #define JO_ALL                0xffffff
  
  /*
***************
*** 1390,1395 ****
--- 1392,1399 ----
      char_u    *jo_callback;   /* not allocated! */
      int               jo_waittime;
      int               jo_timeout;
+     int               jo_part;
+     int               jo_id;
  } jobopt_T;
  
  
*** ../vim-7.4.1371/src/proto/channel.pro       2016-02-20 18:18:51.761033118 
+0100
--- src/proto/channel.pro       2016-02-20 19:30:05.387780642 +0100
***************
*** 23,31 ****
  void channel_free_all(void);
  int channel_get_id(void);
  void channel_read(channel_T *channel, int part, char *func);
! char_u *channel_read_block(channel_T *channel, int part);
! int channel_read_json_block(channel_T *channel, int part, int id, typval_T 
**rettv);
! channel_T *channel_fd2channel(sock_T fd, int *part);
  void channel_handle_events(void);
  int channel_send(channel_T *channel, int part, char_u *buf, char *fun);
  int channel_poll_setup(int nfd_in, void *fds_in);
--- 23,31 ----
  void channel_free_all(void);
  int channel_get_id(void);
  void channel_read(channel_T *channel, int part, char *func);
! char_u *channel_read_block(channel_T *channel, int part, int timeout);
! int channel_read_json_block(channel_T *channel, int part, int timeout, int 
id, typval_T **rettv);
! channel_T *channel_fd2channel(sock_T fd, int *partp);
  void channel_handle_events(void);
  int channel_send(channel_T *channel, int part, char_u *buf, char *fun);
  int channel_poll_setup(int nfd_in, void *fds_in);
***************
*** 37,40 ****
--- 37,41 ----
  int channel_part_send(channel_T *channel);
  int channel_part_read(channel_T *channel);
  ch_mode_T channel_get_mode(channel_T *channel, int part);
+ int channel_get_timeout(channel_T *channel, int part);
  /* vim: set ft=c : */
*** ../vim-7.4.1371/src/testdir/test_channel.vim        2016-02-19 
23:21:21.674060254 +0100
--- src/testdir/test_channel.vim        2016-02-20 19:54:01.924617414 +0100
***************
*** 184,189 ****
--- 184,204 ----
  
    call assert_equal('ok', ch_sendexpr(handle, 'empty-request'))
  
+   " Reading while there is nothing available.
+   call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
+   let start = reltime()
+   call assert_equal(v:none, ch_read(handle, {'timeout': 333}))
+   let elapsed = reltime(start)
+   call assert_true(reltimefloat(elapsed) > 0.3)
+   call assert_true(reltimefloat(elapsed) < 0.6)
+ 
+   " Send without waiting for a response, then wait for a response.
+   call ch_sendexpr(handle, 'wait a bit',  {'callback': 0})
+   let resp = ch_read(handle)
+   call assert_equal(type([]), type(resp))
+   call assert_equal(type(11), type(resp[0]))
+   call assert_equal('waited', resp[1])
+ 
    " make the server quit, can't check if this works, should not hang.
    call ch_sendexpr(handle, '!quit!', {'callback': 0})
  endfunc
***************
*** 292,299 ****
      " Oops, port does exists.
      call ch_close(handle)
    else
!     " Failed connection doesn't wait the full time on Unix.
!     " TODO: why is MS-Windows different?
      let elapsed = reltime(start)
      call assert_true(reltimefloat(elapsed) < 1.0)
    endif
--- 307,313 ----
      " Oops, port does exists.
      call ch_close(handle)
    else
!     " Failed connection should wait about 500 msec.
      let elapsed = reltime(start)
      call assert_true(reltimefloat(elapsed) < 1.0)
    endif
*** ../vim-7.4.1371/src/version.c       2016-02-20 18:44:34.320779512 +0100
--- src/version.c       2016-02-20 19:54:55.844049749 +0100
***************
*** 749,750 ****
--- 749,752 ----
  {   /* Add new patch number below this line */
+ /**/
+     1372,
  /**/

-- 
This is the polymorph virus!  Follow these instructions carefully:
1. Send this message to everybody you know.
2. Format your harddisk.
Thank you for your cooperation in spreading the most powerful virus ever!

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui