mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 7.4.1369
Problem: Channels don't have a queue for stderr. Solution: Have a queue for each part of the channel.
This commit is contained in:
647
src/channel.c
647
src/channel.c
File diff suppressed because it is too large
Load Diff
36
src/eval.c
36
src/eval.c
@@ -10113,32 +10113,41 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
|
|||||||
f_ch_readraw(typval_T *argvars, typval_T *rettv)
|
f_ch_readraw(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
channel_T *channel;
|
channel_T *channel;
|
||||||
|
int part;
|
||||||
|
|
||||||
/* return an empty string by default */
|
/* return an empty string by default */
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = NULL;
|
rettv->vval.v_string = NULL;
|
||||||
|
|
||||||
/* TODO: use timeout from the options */
|
/* TODO: use timeout from the options */
|
||||||
|
/* TODO: read from stderr */
|
||||||
|
|
||||||
channel = get_channel_arg(&argvars[0]);
|
channel = get_channel_arg(&argvars[0]);
|
||||||
if (channel != NULL)
|
if (channel != NULL)
|
||||||
rettv->vval.v_string = channel_read_block(channel);
|
{
|
||||||
|
part = channel_part_read(channel);
|
||||||
|
rettv->vval.v_string = channel_read_block(channel, part);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* common for "sendexpr()" and "sendraw()"
|
* common for "sendexpr()" and "sendraw()"
|
||||||
* Returns the channel if the caller should read the response.
|
* Returns the channel if the caller should read the response.
|
||||||
|
* Sets "part_read" to the the read fd.
|
||||||
* Otherwise returns NULL.
|
* Otherwise returns NULL.
|
||||||
*/
|
*/
|
||||||
static channel_T *
|
static channel_T *
|
||||||
send_common(typval_T *argvars, char_u *text, int id, char *fun)
|
send_common(typval_T *argvars, char_u *text, int id, char *fun, int *part_read)
|
||||||
{
|
{
|
||||||
channel_T *channel;
|
channel_T *channel;
|
||||||
jobopt_T opt;
|
jobopt_T opt;
|
||||||
|
int part_send;
|
||||||
|
|
||||||
channel = get_channel_arg(&argvars[0]);
|
channel = get_channel_arg(&argvars[0]);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
part_send = channel_part_send(channel);
|
||||||
|
*part_read = channel_part_read(channel);
|
||||||
|
|
||||||
opt.jo_callback = NULL;
|
opt.jo_callback = NULL;
|
||||||
if (get_job_options(&argvars[2], &opt, JO_CALLBACK) == FAIL)
|
if (get_job_options(&argvars[2], &opt, JO_CALLBACK) == FAIL)
|
||||||
@@ -10147,9 +10156,10 @@ send_common(typval_T *argvars, char_u *text, int id, char *fun)
|
|||||||
/* Set the callback. An empty callback means no callback and not reading
|
/* Set the callback. An empty callback means no callback and not reading
|
||||||
* the response. */
|
* the response. */
|
||||||
if (opt.jo_callback != NULL && *opt.jo_callback != NUL)
|
if (opt.jo_callback != NULL && *opt.jo_callback != NUL)
|
||||||
channel_set_req_callback(channel, opt.jo_callback, id);
|
channel_set_req_callback(channel, part_send, opt.jo_callback, id);
|
||||||
|
|
||||||
if (channel_send(channel, text, fun) == OK && opt.jo_callback == NULL)
|
if (channel_send(channel, part_send, text, fun) == OK
|
||||||
|
&& opt.jo_callback == NULL)
|
||||||
return channel;
|
return channel;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -10165,6 +10175,8 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
|
|||||||
channel_T *channel;
|
channel_T *channel;
|
||||||
int id;
|
int id;
|
||||||
ch_mode_T ch_mode;
|
ch_mode_T ch_mode;
|
||||||
|
int part_send;
|
||||||
|
int part_read;
|
||||||
|
|
||||||
/* return an empty string by default */
|
/* return an empty string by default */
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
@@ -10173,11 +10185,12 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
|
|||||||
channel = get_channel_arg(&argvars[0]);
|
channel = get_channel_arg(&argvars[0]);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
return;
|
return;
|
||||||
|
part_send = channel_part_send(channel);
|
||||||
|
|
||||||
ch_mode = channel_get_mode(channel);
|
ch_mode = channel_get_mode(channel, part_send);
|
||||||
if (ch_mode == MODE_RAW)
|
if (ch_mode == MODE_RAW || ch_mode == MODE_NL)
|
||||||
{
|
{
|
||||||
EMSG(_("E912: cannot use ch_sendexpr() with a raw channel"));
|
EMSG(_("E912: cannot use ch_sendexpr() with a raw or nl channel"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10187,11 +10200,11 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
|
|||||||
if (text == NULL)
|
if (text == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
channel = send_common(argvars, text, id, "sendexpr");
|
channel = send_common(argvars, text, id, "sendexpr", &part_read);
|
||||||
vim_free(text);
|
vim_free(text);
|
||||||
if (channel != NULL)
|
if (channel != NULL)
|
||||||
{
|
{
|
||||||
if (channel_read_json_block(channel, id, &listtv) == OK)
|
if (channel_read_json_block(channel, part_read, id, &listtv) == OK)
|
||||||
{
|
{
|
||||||
list_T *list = listtv->vval.v_list;
|
list_T *list = listtv->vval.v_list;
|
||||||
|
|
||||||
@@ -10213,15 +10226,16 @@ f_ch_sendraw(typval_T *argvars, typval_T *rettv)
|
|||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
char_u *text;
|
char_u *text;
|
||||||
channel_T *channel;
|
channel_T *channel;
|
||||||
|
int part_read;
|
||||||
|
|
||||||
/* return an empty string by default */
|
/* return an empty string by default */
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = NULL;
|
rettv->vval.v_string = NULL;
|
||||||
|
|
||||||
text = get_tv_string_buf(&argvars[1], buf);
|
text = get_tv_string_buf(&argvars[1], buf);
|
||||||
channel = send_common(argvars, text, 0, "sendraw");
|
channel = send_common(argvars, text, 0, "sendraw", &part_read);
|
||||||
if (channel != NULL)
|
if (channel != NULL)
|
||||||
rettv->vval.v_string = channel_read_block(channel);
|
rettv->vval.v_string = channel_read_block(channel, part_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1930,15 +1930,15 @@ process_message(void)
|
|||||||
#ifdef FEAT_CHANNEL
|
#ifdef FEAT_CHANNEL
|
||||||
if (msg.message == WM_NETBEANS)
|
if (msg.message == WM_NETBEANS)
|
||||||
{
|
{
|
||||||
int what;
|
int part;
|
||||||
channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &what);
|
channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &part);
|
||||||
|
|
||||||
if (channel != NULL)
|
if (channel != NULL)
|
||||||
{
|
{
|
||||||
/* Disable error messages, they can mess up the display and throw
|
/* Disable error messages, they can mess up the display and throw
|
||||||
* an exception. */
|
* an exception. */
|
||||||
++emsg_off;
|
++emsg_off;
|
||||||
channel_read(channel, what, "process_message");
|
channel_read(channel, part, "process_message");
|
||||||
--emsg_off;
|
--emsg_off;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@@ -385,7 +385,7 @@ netbeans_parse_messages(void)
|
|||||||
|
|
||||||
while (nb_channel != NULL)
|
while (nb_channel != NULL)
|
||||||
{
|
{
|
||||||
buffer = channel_peek(nb_channel);
|
buffer = channel_peek(nb_channel, PART_SOCK);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
break; /* nothing to read */
|
break; /* nothing to read */
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ netbeans_parse_messages(void)
|
|||||||
/* Command isn't complete. If there is no following buffer,
|
/* Command isn't complete. If there is no following buffer,
|
||||||
* return (wait for more). If there is another buffer following,
|
* return (wait for more). If there is another buffer following,
|
||||||
* prepend the text to that buffer and delete this one. */
|
* prepend the text to that buffer and delete this one. */
|
||||||
if (channel_collapse(nb_channel) == FAIL)
|
if (channel_collapse(nb_channel, PART_SOCK) == FAIL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -409,7 +409,7 @@ netbeans_parse_messages(void)
|
|||||||
if (*p == NUL)
|
if (*p == NUL)
|
||||||
{
|
{
|
||||||
own_node = TRUE;
|
own_node = TRUE;
|
||||||
channel_get(nb_channel);
|
channel_get(nb_channel, PART_SOCK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
own_node = FALSE;
|
own_node = FALSE;
|
||||||
@@ -757,7 +757,7 @@ netbeans_end(void)
|
|||||||
nb_send(char *buf, char *fun)
|
nb_send(char *buf, char *fun)
|
||||||
{
|
{
|
||||||
if (nb_channel != NULL)
|
if (nb_channel != NULL)
|
||||||
channel_send(nb_channel, (char_u *)buf, fun);
|
channel_send(nb_channel, PART_SOCK, (char_u *)buf, fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -11,29 +11,30 @@ channel_T *channel_open(char *hostname, int port_in, int waittime, void (*close_
|
|||||||
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
||||||
void channel_set_job(channel_T *channel, job_T *job);
|
void channel_set_job(channel_T *channel, job_T *job);
|
||||||
void channel_set_options(channel_T *channel, jobopt_T *options);
|
void channel_set_options(channel_T *channel, jobopt_T *options);
|
||||||
void channel_set_req_callback(channel_T *channel, char_u *callback, int id);
|
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id);
|
||||||
char_u *channel_get(channel_T *channel);
|
char_u *channel_get(channel_T *channel, int part);
|
||||||
int channel_collapse(channel_T *channel);
|
int channel_collapse(channel_T *channel, int part);
|
||||||
int channel_can_write_to(channel_T *channel);
|
int channel_can_write_to(channel_T *channel);
|
||||||
int channel_is_open(channel_T *channel);
|
int channel_is_open(channel_T *channel);
|
||||||
char *channel_status(channel_T *channel);
|
char *channel_status(channel_T *channel);
|
||||||
void channel_close(channel_T *channel);
|
void channel_close(channel_T *channel);
|
||||||
int channel_save(channel_T *channel, char_u *buf, int len);
|
char_u *channel_peek(channel_T *channel, int part);
|
||||||
char_u *channel_peek(channel_T *channel);
|
|
||||||
void channel_clear(channel_T *channel);
|
void channel_clear(channel_T *channel);
|
||||||
void channel_free_all(void);
|
void channel_free_all(void);
|
||||||
int channel_get_id(void);
|
int channel_get_id(void);
|
||||||
void channel_read(channel_T *channel, int which, char *func);
|
void channel_read(channel_T *channel, int part, char *func);
|
||||||
char_u *channel_read_block(channel_T *channel);
|
char_u *channel_read_block(channel_T *channel, int part);
|
||||||
int channel_read_json_block(channel_T *channel, int id, typval_T **rettv);
|
int channel_read_json_block(channel_T *channel, int part, int id, typval_T **rettv);
|
||||||
channel_T *channel_fd2channel(sock_T fd, int *whichp);
|
channel_T *channel_fd2channel(sock_T fd, int *part);
|
||||||
void channel_handle_events(void);
|
void channel_handle_events(void);
|
||||||
int channel_send(channel_T *channel, char_u *buf, char *fun);
|
int channel_send(channel_T *channel, int part, char_u *buf, char *fun);
|
||||||
int channel_poll_setup(int nfd_in, void *fds_in);
|
int channel_poll_setup(int nfd_in, void *fds_in);
|
||||||
int channel_poll_check(int ret_in, void *fds_in);
|
int channel_poll_check(int ret_in, void *fds_in);
|
||||||
int channel_select_setup(int maxfd_in, void *rfds_in);
|
int channel_select_setup(int maxfd_in, void *rfds_in);
|
||||||
int channel_select_check(int ret_in, void *rfds_in);
|
int channel_select_check(int ret_in, void *rfds_in);
|
||||||
int channel_parse_messages(void);
|
int channel_parse_messages(void);
|
||||||
int set_ref_in_channel(int copyID);
|
int set_ref_in_channel(int copyID);
|
||||||
ch_mode_T channel_get_mode(channel_T *channel);
|
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);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -1303,19 +1303,19 @@ typedef enum
|
|||||||
|
|
||||||
/* Ordering matters, it is used in for loops: IN is last, only SOCK/OUT/ERR
|
/* Ordering matters, it is used in for loops: IN is last, only SOCK/OUT/ERR
|
||||||
* are polled. */
|
* are polled. */
|
||||||
#define CHAN_SOCK 0
|
#define PART_SOCK 0
|
||||||
#define CH_SOCK ch_pfd[CHAN_SOCK].ch_fd
|
#define CH_SOCK_FD ch_part[PART_SOCK].ch_fd
|
||||||
|
|
||||||
#if defined(UNIX) || defined(WIN32)
|
#if defined(UNIX) || defined(WIN32)
|
||||||
# define CHANNEL_PIPES
|
# define CHANNEL_PIPES
|
||||||
# define CHAN_FD_INVALID (-1)
|
# define INVALID_FD (-1)
|
||||||
|
|
||||||
# define CHAN_OUT 1
|
# define PART_OUT 1
|
||||||
# define CHAN_ERR 2
|
# define PART_ERR 2
|
||||||
# define CHAN_IN 3
|
# define PART_IN 3
|
||||||
# define CH_OUT ch_pfd[CHAN_OUT].ch_fd
|
# define CH_OUT_FD ch_part[PART_OUT].ch_fd
|
||||||
# define CH_ERR ch_pfd[CHAN_ERR].ch_fd
|
# define CH_ERR_FD ch_part[PART_ERR].ch_fd
|
||||||
# define CH_IN ch_pfd[CHAN_IN].ch_fd
|
# define CH_IN_FD ch_part[PART_IN].ch_fd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The per-fd info for a channel. */
|
/* The per-fd info for a channel. */
|
||||||
@@ -1335,7 +1335,18 @@ typedef struct {
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
int ch_inputHandler; /* ret.value of WSAAsyncSelect() */
|
int ch_inputHandler; /* ret.value of WSAAsyncSelect() */
|
||||||
#endif
|
#endif
|
||||||
} chan_fd_T;
|
|
||||||
|
ch_mode_T ch_mode;
|
||||||
|
int ch_timeout; /* request timeout in msec */
|
||||||
|
|
||||||
|
readq_T ch_head; /* header for circular raw read queue */
|
||||||
|
jsonq_T ch_json_head; /* header for circular json read queue */
|
||||||
|
int ch_block_id; /* ID that channel_read_json_block() is
|
||||||
|
waiting for */
|
||||||
|
|
||||||
|
cbq_T ch_cb_head; /* dummy node for per-request callbacks */
|
||||||
|
char_u *ch_callback; /* call when a msg is not handled */
|
||||||
|
} chanpart_T;
|
||||||
|
|
||||||
struct channel_S {
|
struct channel_S {
|
||||||
channel_T *ch_next;
|
channel_T *ch_next;
|
||||||
@@ -1343,9 +1354,7 @@ struct channel_S {
|
|||||||
|
|
||||||
int ch_id; /* ID of the channel */
|
int ch_id; /* ID of the channel */
|
||||||
|
|
||||||
chan_fd_T ch_pfd[4]; /* info for socket, out, err and in */
|
chanpart_T ch_part[4]; /* info for socket, out, err and in */
|
||||||
|
|
||||||
readq_T ch_head; /* dummy node, header for circular queue */
|
|
||||||
|
|
||||||
int ch_error; /* When TRUE an error was reported. Avoids
|
int ch_error; /* When TRUE an error was reported. Avoids
|
||||||
* giving pages full of error messages when
|
* giving pages full of error messages when
|
||||||
@@ -1355,15 +1364,7 @@ struct channel_S {
|
|||||||
|
|
||||||
void (*ch_close_cb)(void); /* callback for when channel is closed */
|
void (*ch_close_cb)(void); /* callback for when channel is closed */
|
||||||
|
|
||||||
int ch_block_id; /* ID that channel_read_json_block() is
|
char_u *ch_callback; /* call when any msg is not handled */
|
||||||
waiting for */
|
|
||||||
char_u *ch_callback; /* function to call when a msg is not handled */
|
|
||||||
cbq_T ch_cb_head; /* dummy node for pre-request callbacks */
|
|
||||||
|
|
||||||
ch_mode_T ch_mode;
|
|
||||||
jsonq_T ch_json_head; /* dummy node, header for circular queue */
|
|
||||||
|
|
||||||
int ch_timeout; /* request timeout in msec */
|
|
||||||
|
|
||||||
job_T *ch_job; /* Job that uses this channel; this does not
|
job_T *ch_job; /* Job that uses this channel; this does not
|
||||||
* count as a reference to avoid a circular
|
* count as a reference to avoid a circular
|
||||||
@@ -1372,10 +1373,10 @@ struct channel_S {
|
|||||||
int ch_refcount; /* reference count */
|
int ch_refcount; /* reference count */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JO_MODE 1
|
#define JO_MODE 1 /* all modes */
|
||||||
#define JO_CALLBACK 2
|
#define JO_CALLBACK 2 /* channel callback */
|
||||||
#define JO_WAITTIME 4
|
#define JO_WAITTIME 4 /* only for ch_open() */
|
||||||
#define JO_TIMEOUT 8
|
#define JO_TIMEOUT 8 /* all timeouts */
|
||||||
#define JO_ALL 0xffffff
|
#define JO_ALL 0xffffff
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -747,6 +747,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 */
|
||||||
|
/**/
|
||||||
|
1369,
|
||||||
/**/
|
/**/
|
||||||
1368,
|
1368,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user