comparison src/channel.c @ 16872:a836d122231a v8.1.1437

patch 8.1.1437: code to handle callbacks is duplicated commit https://github.com/vim/vim/commit/3a97bb3f0f8bd118ae23f1c97e55d84ff42eef20 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 1 13:28:35 2019 +0200 patch 8.1.1437: code to handle callbacks is duplicated Problem: Code to handle callbacks is duplicated. Solution: Add callback_T and functions to deal with it.
author Bram Moolenaar <Bram@vim.org>
date Sat, 01 Jun 2019 13:30:07 +0200
parents ce04ebdf26b8
children a5e3509b33ca
comparison
equal deleted inserted replaced
16871:e5dab34ded73 16872:a836d122231a
346 /* If the job was killed the channel is not expected to work anymore. */ 346 /* If the job was killed the channel is not expected to work anymore. */
347 if (channel->ch_job_killed && channel->ch_job == NULL) 347 if (channel->ch_job_killed && channel->ch_job == NULL)
348 return FALSE; 348 return FALSE;
349 349
350 /* If there is a close callback it may still need to be invoked. */ 350 /* If there is a close callback it may still need to be invoked. */
351 if (channel->ch_close_cb != NULL) 351 if (channel->ch_close_cb.cb_name != NULL)
352 return TRUE; 352 return TRUE;
353 353
354 /* If reading from or a buffer it's still useful. */ 354 /* If reading from or a buffer it's still useful. */
355 if (channel->ch_part[PART_IN].ch_bufref.br_buf != NULL) 355 if (channel->ch_part[PART_IN].ch_bufref.br_buf != NULL)
356 return TRUE; 356 return TRUE;
364 || channel->ch_part[PART_OUT].ch_head.rq_next != NULL 364 || channel->ch_part[PART_OUT].ch_head.rq_next != NULL
365 || channel->ch_part[PART_OUT].ch_json_head.jq_next != NULL; 365 || channel->ch_part[PART_OUT].ch_json_head.jq_next != NULL;
366 has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD 366 has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD
367 || channel->ch_part[PART_ERR].ch_head.rq_next != NULL 367 || channel->ch_part[PART_ERR].ch_head.rq_next != NULL
368 || channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL; 368 || channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL;
369 return (channel->ch_callback != NULL && (has_sock_msg 369 return (channel->ch_callback.cb_name != NULL && (has_sock_msg
370 || has_out_msg || has_err_msg)) 370 || has_out_msg || has_err_msg))
371 || ((channel->ch_part[PART_OUT].ch_callback != NULL 371 || ((channel->ch_part[PART_OUT].ch_callback.cb_name != NULL
372 || channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL) 372 || channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL)
373 && has_out_msg) 373 && has_out_msg)
374 || ((channel->ch_part[PART_ERR].ch_callback != NULL 374 || ((channel->ch_part[PART_ERR].ch_callback.cb_name != NULL
375 || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL) 375 || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL)
376 && has_err_msg); 376 && has_err_msg);
377 } 377 }
378 378
379 /* 379 /*
1176 } 1176 }
1177 1177
1178 return buf; 1178 return buf;
1179 } 1179 }
1180 1180
1181 /*
1182 * Copy callback from "src" to "dest", incrementing the refcounts.
1183 */
1181 static void 1184 static void
1182 set_callback( 1185 copy_callback(callback_T *dest, callback_T *src)
1183 char_u **cbp, 1186 {
1184 partial_T **pp, 1187 dest->cb_partial = src->cb_partial;
1185 char_u *callback, 1188 if (dest->cb_partial != NULL)
1186 partial_T *partial) 1189 {
1187 { 1190 dest->cb_name = src->cb_name;
1188 free_callback(*cbp, *pp); 1191 dest->cb_free_name = FALSE;
1189 if (callback != NULL && *callback != NUL) 1192 ++dest->cb_partial->pt_refcount;
1190 {
1191 if (partial != NULL)
1192 *cbp = partial_name(partial);
1193 else
1194 {
1195 *cbp = vim_strsave(callback);
1196 func_ref(*cbp);
1197 }
1198 } 1193 }
1199 else 1194 else
1200 *cbp = NULL; 1195 {
1201 *pp = partial; 1196 dest->cb_name = vim_strsave(src->cb_name);
1202 if (partial != NULL) 1197 dest->cb_free_name = TRUE;
1203 ++partial->pt_refcount; 1198 func_ref(src->cb_name);
1199 }
1200 }
1201
1202 static void
1203 free_set_callback(callback_T *cbp, callback_T *callback)
1204 {
1205 free_callback(cbp);
1206
1207 if (callback->cb_name != NULL && *callback->cb_name != NUL)
1208 copy_callback(cbp, callback);
1209 else
1210 cbp->cb_name = NULL;
1204 } 1211 }
1205 1212
1206 /* 1213 /*
1207 * Set various properties from an "opt" argument. 1214 * Set various properties from an "opt" argument.
1208 */ 1215 */
1231 channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout; 1238 channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout;
1232 if (opt->jo_set & JO_BLOCK_WRITE) 1239 if (opt->jo_set & JO_BLOCK_WRITE)
1233 channel->ch_part[PART_IN].ch_block_write = 1; 1240 channel->ch_part[PART_IN].ch_block_write = 1;
1234 1241
1235 if (opt->jo_set & JO_CALLBACK) 1242 if (opt->jo_set & JO_CALLBACK)
1236 set_callback(&channel->ch_callback, &channel->ch_partial, 1243 free_set_callback(&channel->ch_callback, &opt->jo_callback);
1237 opt->jo_callback, opt->jo_partial);
1238 if (opt->jo_set & JO_OUT_CALLBACK) 1244 if (opt->jo_set & JO_OUT_CALLBACK)
1239 set_callback(&channel->ch_part[PART_OUT].ch_callback, 1245 free_set_callback(&channel->ch_part[PART_OUT].ch_callback,
1240 &channel->ch_part[PART_OUT].ch_partial, 1246 &opt->jo_out_cb);
1241 opt->jo_out_cb, opt->jo_out_partial);
1242 if (opt->jo_set & JO_ERR_CALLBACK) 1247 if (opt->jo_set & JO_ERR_CALLBACK)
1243 set_callback(&channel->ch_part[PART_ERR].ch_callback, 1248 free_set_callback(&channel->ch_part[PART_ERR].ch_callback,
1244 &channel->ch_part[PART_ERR].ch_partial, 1249 &opt->jo_err_cb);
1245 opt->jo_err_cb, opt->jo_err_partial);
1246 if (opt->jo_set & JO_CLOSE_CALLBACK) 1250 if (opt->jo_set & JO_CLOSE_CALLBACK)
1247 set_callback(&channel->ch_close_cb, &channel->ch_close_partial, 1251 free_set_callback(&channel->ch_close_cb, &opt->jo_close_cb);
1248 opt->jo_close_cb, opt->jo_close_partial);
1249 channel->ch_drop_never = opt->jo_drop_never; 1252 channel->ch_drop_never = opt->jo_drop_never;
1250 1253
1251 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER) 1254 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
1252 { 1255 {
1253 buf_T *buf; 1256 buf_T *buf;
1347 */ 1350 */
1348 void 1351 void
1349 channel_set_req_callback( 1352 channel_set_req_callback(
1350 channel_T *channel, 1353 channel_T *channel,
1351 ch_part_T part, 1354 ch_part_T part,
1352 char_u *callback, 1355 callback_T *callback,
1353 partial_T *partial,
1354 int id) 1356 int id)
1355 { 1357 {
1356 cbq_T *head = &channel->ch_part[part].ch_cb_head; 1358 cbq_T *head = &channel->ch_part[part].ch_cb_head;
1357 cbq_T *item = ALLOC_ONE(cbq_T); 1359 cbq_T *item = ALLOC_ONE(cbq_T);
1358 1360
1359 if (item != NULL) 1361 if (item != NULL)
1360 { 1362 {
1361 item->cq_partial = partial; 1363 copy_callback(&item->cq_callback, callback);
1362 if (partial != NULL)
1363 {
1364 ++partial->pt_refcount;
1365 item->cq_callback = callback;
1366 }
1367 else
1368 {
1369 item->cq_callback = vim_strsave(callback);
1370 func_ref(item->cq_callback);
1371 }
1372 item->cq_seq_nr = id; 1364 item->cq_seq_nr = id;
1373 item->cq_prev = head->cq_prev; 1365 item->cq_prev = head->cq_prev;
1374 head->cq_prev = item; 1366 head->cq_prev = item;
1375 item->cq_next = NULL; 1367 item->cq_next = NULL;
1376 if (item->cq_prev == NULL) 1368 if (item->cq_prev == NULL)
1636 /* 1628 /*
1637 * Invoke the "callback" on channel "channel". 1629 * Invoke the "callback" on channel "channel".
1638 * This does not redraw but sets channel_need_redraw; 1630 * This does not redraw but sets channel_need_redraw;
1639 */ 1631 */
1640 static void 1632 static void
1641 invoke_callback(channel_T *channel, char_u *callback, partial_T *partial, 1633 invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
1642 typval_T *argv)
1643 { 1634 {
1644 typval_T rettv; 1635 typval_T rettv;
1645 int dummy; 1636 int dummy;
1646 1637
1647 if (safe_to_invoke_callback == 0) 1638 if (safe_to_invoke_callback == 0)
1648 iemsg("INTERNAL: Invoking callback when it is not safe"); 1639 iemsg("INTERNAL: Invoking callback when it is not safe");
1649 1640
1650 argv[0].v_type = VAR_CHANNEL; 1641 argv[0].v_type = VAR_CHANNEL;
1651 argv[0].vval.v_channel = channel; 1642 argv[0].vval.v_channel = channel;
1652 1643
1653 call_func(callback, -1, &rettv, 2, argv, NULL, 1644 call_callback(callback, -1, &rettv, 2, argv, NULL,
1654 0L, 0L, &dummy, TRUE, partial, NULL); 1645 0L, 0L, &dummy, TRUE, NULL);
1655 clear_tv(&rettv); 1646 clear_tv(&rettv);
1656 channel_need_redraw = TRUE; 1647 channel_need_redraw = TRUE;
1657 } 1648 }
1658 1649
1659 /* 1650 /*
2412 cbq_T *cbhead, 2403 cbq_T *cbhead,
2413 cbq_T *item, 2404 cbq_T *item,
2414 typval_T *argv) 2405 typval_T *argv)
2415 { 2406 {
2416 ch_log(channel, "Invoking one-time callback %s", 2407 ch_log(channel, "Invoking one-time callback %s",
2417 (char *)item->cq_callback); 2408 (char *)item->cq_callback.cb_name);
2418 /* Remove the item from the list first, if the callback 2409 /* Remove the item from the list first, if the callback
2419 * invokes ch_close() the list will be cleared. */ 2410 * invokes ch_close() the list will be cleared. */
2420 remove_cb_node(cbhead, item); 2411 remove_cb_node(cbhead, item);
2421 invoke_callback(channel, item->cq_callback, item->cq_partial, argv); 2412 invoke_callback(channel, &item->cq_callback, argv);
2422 free_callback(item->cq_callback, item->cq_partial); 2413 free_callback(&item->cq_callback);
2423 vim_free(item); 2414 vim_free(item);
2424 } 2415 }
2425 2416
2426 static void 2417 static void
2427 append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part) 2418 append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
2551 int seq_nr = -1; 2542 int seq_nr = -1;
2552 chanpart_T *ch_part = &channel->ch_part[part]; 2543 chanpart_T *ch_part = &channel->ch_part[part];
2553 ch_mode_T ch_mode = ch_part->ch_mode; 2544 ch_mode_T ch_mode = ch_part->ch_mode;
2554 cbq_T *cbhead = &ch_part->ch_cb_head; 2545 cbq_T *cbhead = &ch_part->ch_cb_head;
2555 cbq_T *cbitem; 2546 cbq_T *cbitem;
2556 char_u *callback = NULL; 2547 callback_T *callback = NULL;
2557 partial_T *partial = NULL;
2558 buf_T *buffer = NULL; 2548 buf_T *buffer = NULL;
2559 char_u *p; 2549 char_u *p;
2560 2550
2561 if (channel->ch_nb_close_cb != NULL) 2551 if (channel->ch_nb_close_cb != NULL)
2562 /* this channel is handled elsewhere (netbeans) */ 2552 /* this channel is handled elsewhere (netbeans) */
2565 /* Use a message-specific callback, part callback or channel callback */ 2555 /* Use a message-specific callback, part callback or channel callback */
2566 for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next) 2556 for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next)
2567 if (cbitem->cq_seq_nr == 0) 2557 if (cbitem->cq_seq_nr == 0)
2568 break; 2558 break;
2569 if (cbitem != NULL) 2559 if (cbitem != NULL)
2570 { 2560 callback = &cbitem->cq_callback;
2571 callback = cbitem->cq_callback; 2561 else if (ch_part->ch_callback.cb_name != NULL)
2572 partial = cbitem->cq_partial; 2562 callback = &ch_part->ch_callback;
2573 } 2563 else if (channel->ch_callback.cb_name != NULL)
2574 else if (ch_part->ch_callback != NULL) 2564 callback = &channel->ch_callback;
2575 {
2576 callback = ch_part->ch_callback;
2577 partial = ch_part->ch_partial;
2578 }
2579 else
2580 {
2581 callback = channel->ch_callback;
2582 partial = channel->ch_partial;
2583 }
2584 2565
2585 buffer = ch_part->ch_bufref.br_buf; 2566 buffer = ch_part->ch_bufref.br_buf;
2586 if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref) 2567 if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref)
2587 || buffer->b_ml.ml_mfp == NULL)) 2568 || buffer->b_ml.ml_mfp == NULL))
2588 { 2569 {
2640 /* If there is no callback or buffer drop the message. */ 2621 /* If there is no callback or buffer drop the message. */
2641 if (callback == NULL && buffer == NULL) 2622 if (callback == NULL && buffer == NULL)
2642 { 2623 {
2643 /* If there is a close callback it may use ch_read() to get the 2624 /* If there is a close callback it may use ch_read() to get the
2644 * messages. */ 2625 * messages. */
2645 if (channel->ch_close_cb == NULL && !channel->ch_drop_never) 2626 if (channel->ch_close_cb.cb_name == NULL && !channel->ch_drop_never)
2646 drop_messages(channel, part); 2627 drop_messages(channel, part);
2647 return FALSE; 2628 return FALSE;
2648 } 2629 }
2649 2630
2650 if (ch_mode == MODE_NL) 2631 if (ch_mode == MODE_NL)
2759 invoke_one_time_callback(channel, cbhead, cbitem, argv); 2740 invoke_one_time_callback(channel, cbhead, cbitem, argv);
2760 else 2741 else
2761 { 2742 {
2762 /* invoke the channel callback */ 2743 /* invoke the channel callback */
2763 ch_log(channel, "Invoking channel callback %s", 2744 ch_log(channel, "Invoking channel callback %s",
2764 (char *)callback); 2745 (char *)callback->cb_name);
2765 invoke_callback(channel, callback, partial, argv); 2746 invoke_callback(channel, callback, argv);
2766 } 2747 }
2767 } 2748 }
2768 } 2749 }
2769 else 2750 else
2770 ch_log(channel, "Dropping message %d", seq_nr); 2751 ch_log(channel, "Dropping message %d", seq_nr);
2954 if (invoke_close_cb) 2935 if (invoke_close_cb)
2955 { 2936 {
2956 ch_part_T part; 2937 ch_part_T part;
2957 2938
2958 /* Invoke callbacks and flush buffers before the close callback. */ 2939 /* Invoke callbacks and flush buffers before the close callback. */
2959 if (channel->ch_close_cb != NULL) 2940 if (channel->ch_close_cb.cb_name != NULL)
2960 ch_log(channel, 2941 ch_log(channel,
2961 "Invoking callbacks and flushing buffers before closing"); 2942 "Invoking callbacks and flushing buffers before closing");
2962 for (part = PART_SOCK; part < PART_IN; ++part) 2943 for (part = PART_SOCK; part < PART_IN; ++part)
2963 { 2944 {
2964 if (channel->ch_close_cb != NULL 2945 if (channel->ch_close_cb.cb_name != NULL
2965 || channel->ch_part[part].ch_bufref.br_buf != NULL) 2946 || channel->ch_part[part].ch_bufref.br_buf != NULL)
2966 { 2947 {
2967 /* Increment the refcount to avoid the channel being freed 2948 /* Increment the refcount to avoid the channel being freed
2968 * halfway. */ 2949 * halfway. */
2969 ++channel->ch_refcount; 2950 ++channel->ch_refcount;
2970 if (channel->ch_close_cb == NULL) 2951 if (channel->ch_close_cb.cb_name == NULL)
2971 ch_log(channel, "flushing %s buffers before closing", 2952 ch_log(channel, "flushing %s buffers before closing",
2972 part_names[part]); 2953 part_names[part]);
2973 while (may_invoke_callback(channel, part)) 2954 while (may_invoke_callback(channel, part))
2974 ; 2955 ;
2975 --channel->ch_refcount; 2956 --channel->ch_refcount;
2976 } 2957 }
2977 } 2958 }
2978 2959
2979 if (channel->ch_close_cb != NULL) 2960 if (channel->ch_close_cb.cb_name != NULL)
2980 { 2961 {
2981 typval_T argv[1]; 2962 typval_T argv[1];
2982 typval_T rettv; 2963 typval_T rettv;
2983 int dummy; 2964 int dummy;
2984 2965
2985 /* Increment the refcount to avoid the channel being freed 2966 /* Increment the refcount to avoid the channel being freed
2986 * halfway. */ 2967 * halfway. */
2987 ++channel->ch_refcount; 2968 ++channel->ch_refcount;
2988 ch_log(channel, "Invoking close callback %s", 2969 ch_log(channel, "Invoking close callback %s",
2989 (char *)channel->ch_close_cb); 2970 (char *)channel->ch_close_cb.cb_name);
2990 argv[0].v_type = VAR_CHANNEL; 2971 argv[0].v_type = VAR_CHANNEL;
2991 argv[0].vval.v_channel = channel; 2972 argv[0].vval.v_channel = channel;
2992 call_func(channel->ch_close_cb, -1, 2973 call_callback(&channel->ch_close_cb, -1,
2993 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, 2974 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
2994 channel->ch_close_partial, NULL);
2995 clear_tv(&rettv); 2975 clear_tv(&rettv);
2996 channel_need_redraw = TRUE; 2976 channel_need_redraw = TRUE;
2997 2977
2998 /* the callback is only called once */ 2978 /* the callback is only called once */
2999 free_callback(channel->ch_close_cb, channel->ch_close_partial); 2979 free_callback(&channel->ch_close_cb);
3000 channel->ch_close_cb = NULL;
3001 channel->ch_close_partial = NULL;
3002 2980
3003 if (channel_need_redraw) 2981 if (channel_need_redraw)
3004 { 2982 {
3005 channel_need_redraw = FALSE; 2983 channel_need_redraw = FALSE;
3006 redraw_after_callback(TRUE); 2984 redraw_after_callback(TRUE);
3059 while (cb_head->cq_next != NULL) 3037 while (cb_head->cq_next != NULL)
3060 { 3038 {
3061 cbq_T *node = cb_head->cq_next; 3039 cbq_T *node = cb_head->cq_next;
3062 3040
3063 remove_cb_node(cb_head, node); 3041 remove_cb_node(cb_head, node);
3064 free_callback(node->cq_callback, node->cq_partial); 3042 free_callback(&node->cq_callback);
3065 vim_free(node); 3043 vim_free(node);
3066 } 3044 }
3067 3045
3068 while (json_head->jq_next != NULL) 3046 while (json_head->jq_next != NULL)
3069 { 3047 {
3070 free_tv(json_head->jq_next->jq_value); 3048 free_tv(json_head->jq_next->jq_value);
3071 remove_json_node(json_head, json_head->jq_next); 3049 remove_json_node(json_head, json_head->jq_next);
3072 } 3050 }
3073 3051
3074 free_callback(ch_part->ch_callback, ch_part->ch_partial); 3052 free_callback(&ch_part->ch_callback);
3075 ch_part->ch_callback = NULL;
3076 ch_part->ch_partial = NULL;
3077 3053
3078 while (ch_part->ch_writeque.wq_next != NULL) 3054 while (ch_part->ch_writeque.wq_next != NULL)
3079 remove_from_writeque(&ch_part->ch_writeque, 3055 remove_from_writeque(&ch_part->ch_writeque,
3080 ch_part->ch_writeque.wq_next); 3056 ch_part->ch_writeque.wq_next);
3081 } 3057 }
3090 VIM_CLEAR(channel->ch_hostname); 3066 VIM_CLEAR(channel->ch_hostname);
3091 channel_clear_one(channel, PART_SOCK); 3067 channel_clear_one(channel, PART_SOCK);
3092 channel_clear_one(channel, PART_OUT); 3068 channel_clear_one(channel, PART_OUT);
3093 channel_clear_one(channel, PART_ERR); 3069 channel_clear_one(channel, PART_ERR);
3094 channel_clear_one(channel, PART_IN); 3070 channel_clear_one(channel, PART_IN);
3095 free_callback(channel->ch_callback, channel->ch_partial); 3071 free_callback(&channel->ch_callback);
3096 channel->ch_callback = NULL; 3072 free_callback(&channel->ch_close_cb);
3097 channel->ch_partial = NULL;
3098 free_callback(channel->ch_close_cb, channel->ch_close_partial);
3099 channel->ch_close_cb = NULL;
3100 channel->ch_close_partial = NULL;
3101 } 3073 }
3102 3074
3103 #if defined(EXITFREE) || defined(PROTO) 3075 #if defined(EXITFREE) || defined(PROTO)
3104 void 3076 void
3105 channel_free_all(void) 3077 channel_free_all(void)
3989 return NULL; 3961 return NULL;
3990 3962
3991 /* Set the callback. An empty callback means no callback and not reading 3963 /* Set the callback. An empty callback means no callback and not reading
3992 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not 3964 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not
3993 * allowed. */ 3965 * allowed. */
3994 if (opt->jo_callback != NULL && *opt->jo_callback != NUL) 3966 if (opt->jo_callback.cb_name != NULL && *opt->jo_callback.cb_name != NUL)
3995 { 3967 {
3996 if (eval) 3968 if (eval)
3997 { 3969 {
3998 semsg(_("E917: Cannot use a callback with %s()"), fun); 3970 semsg(_("E917: Cannot use a callback with %s()"), fun);
3999 return NULL; 3971 return NULL;
4000 } 3972 }
4001 channel_set_req_callback(channel, *part_read, 3973 channel_set_req_callback(channel, *part_read, &opt->jo_callback, id);
4002 opt->jo_callback, opt->jo_partial, id);
4003 } 3974 }
4004 3975
4005 if (channel_send(channel, part_send, text, len, fun) == OK 3976 if (channel_send(channel, part_send, text, len, fun) == OK
4006 && opt->jo_callback == NULL) 3977 && opt->jo_callback.cb_name == NULL)
4007 return channel; 3978 return channel;
4008 return NULL; 3979 return NULL;
4009 } 3980 }
4010 3981
4011 /* 3982 /*
4557 * Free any members of a jobopt_T. 4528 * Free any members of a jobopt_T.
4558 */ 4529 */
4559 void 4530 void
4560 free_job_options(jobopt_T *opt) 4531 free_job_options(jobopt_T *opt)
4561 { 4532 {
4562 if (opt->jo_partial != NULL) 4533 if (opt->jo_callback.cb_partial != NULL)
4563 partial_unref(opt->jo_partial); 4534 partial_unref(opt->jo_callback.cb_partial);
4564 else if (opt->jo_callback != NULL) 4535 else if (opt->jo_callback.cb_name != NULL)
4565 func_unref(opt->jo_callback); 4536 func_unref(opt->jo_callback.cb_name);
4566 if (opt->jo_out_partial != NULL) 4537 if (opt->jo_out_cb.cb_partial != NULL)
4567 partial_unref(opt->jo_out_partial); 4538 partial_unref(opt->jo_out_cb.cb_partial);
4568 else if (opt->jo_out_cb != NULL) 4539 else if (opt->jo_out_cb.cb_name != NULL)
4569 func_unref(opt->jo_out_cb); 4540 func_unref(opt->jo_out_cb.cb_name);
4570 if (opt->jo_err_partial != NULL) 4541 if (opt->jo_err_cb.cb_partial != NULL)
4571 partial_unref(opt->jo_err_partial); 4542 partial_unref(opt->jo_err_cb.cb_partial);
4572 else if (opt->jo_err_cb != NULL) 4543 else if (opt->jo_err_cb.cb_name != NULL)
4573 func_unref(opt->jo_err_cb); 4544 func_unref(opt->jo_err_cb.cb_name);
4574 if (opt->jo_close_partial != NULL) 4545 if (opt->jo_close_cb.cb_partial != NULL)
4575 partial_unref(opt->jo_close_partial); 4546 partial_unref(opt->jo_close_cb.cb_partial);
4576 else if (opt->jo_close_cb != NULL) 4547 else if (opt->jo_close_cb.cb_name != NULL)
4577 func_unref(opt->jo_close_cb); 4548 func_unref(opt->jo_close_cb.cb_name);
4578 if (opt->jo_exit_partial != NULL) 4549 if (opt->jo_exit_cb.cb_partial != NULL)
4579 partial_unref(opt->jo_exit_partial); 4550 partial_unref(opt->jo_exit_cb.cb_partial);
4580 else if (opt->jo_exit_cb != NULL) 4551 else if (opt->jo_exit_cb.cb_name != NULL)
4581 func_unref(opt->jo_exit_cb); 4552 func_unref(opt->jo_exit_cb.cb_name);
4582 if (opt->jo_env != NULL) 4553 if (opt->jo_env != NULL)
4583 dict_unref(opt->jo_env); 4554 dict_unref(opt->jo_env);
4584 } 4555 }
4585 4556
4586 /* 4557 /*
4769 else if (STRCMP(hi->hi_key, "callback") == 0) 4740 else if (STRCMP(hi->hi_key, "callback") == 0)
4770 { 4741 {
4771 if (!(supported & JO_CALLBACK)) 4742 if (!(supported & JO_CALLBACK))
4772 break; 4743 break;
4773 opt->jo_set |= JO_CALLBACK; 4744 opt->jo_set |= JO_CALLBACK;
4774 opt->jo_callback = get_callback(item, &opt->jo_partial); 4745 opt->jo_callback = get_callback(item);
4775 if (opt->jo_callback == NULL) 4746 if (opt->jo_callback.cb_name == NULL)
4776 { 4747 {
4777 semsg(_(e_invargval), "callback"); 4748 semsg(_(e_invargval), "callback");
4778 return FAIL; 4749 return FAIL;
4779 } 4750 }
4780 } 4751 }
4781 else if (STRCMP(hi->hi_key, "out_cb") == 0) 4752 else if (STRCMP(hi->hi_key, "out_cb") == 0)
4782 { 4753 {
4783 if (!(supported & JO_OUT_CALLBACK)) 4754 if (!(supported & JO_OUT_CALLBACK))
4784 break; 4755 break;
4785 opt->jo_set |= JO_OUT_CALLBACK; 4756 opt->jo_set |= JO_OUT_CALLBACK;
4786 opt->jo_out_cb = get_callback(item, &opt->jo_out_partial); 4757 opt->jo_out_cb = get_callback(item);
4787 if (opt->jo_out_cb == NULL) 4758 if (opt->jo_out_cb.cb_name == NULL)
4788 { 4759 {
4789 semsg(_(e_invargval), "out_cb"); 4760 semsg(_(e_invargval), "out_cb");
4790 return FAIL; 4761 return FAIL;
4791 } 4762 }
4792 } 4763 }
4793 else if (STRCMP(hi->hi_key, "err_cb") == 0) 4764 else if (STRCMP(hi->hi_key, "err_cb") == 0)
4794 { 4765 {
4795 if (!(supported & JO_ERR_CALLBACK)) 4766 if (!(supported & JO_ERR_CALLBACK))
4796 break; 4767 break;
4797 opt->jo_set |= JO_ERR_CALLBACK; 4768 opt->jo_set |= JO_ERR_CALLBACK;
4798 opt->jo_err_cb = get_callback(item, &opt->jo_err_partial); 4769 opt->jo_err_cb = get_callback(item);
4799 if (opt->jo_err_cb == NULL) 4770 if (opt->jo_err_cb.cb_name == NULL)
4800 { 4771 {
4801 semsg(_(e_invargval), "err_cb"); 4772 semsg(_(e_invargval), "err_cb");
4802 return FAIL; 4773 return FAIL;
4803 } 4774 }
4804 } 4775 }
4805 else if (STRCMP(hi->hi_key, "close_cb") == 0) 4776 else if (STRCMP(hi->hi_key, "close_cb") == 0)
4806 { 4777 {
4807 if (!(supported & JO_CLOSE_CALLBACK)) 4778 if (!(supported & JO_CLOSE_CALLBACK))
4808 break; 4779 break;
4809 opt->jo_set |= JO_CLOSE_CALLBACK; 4780 opt->jo_set |= JO_CLOSE_CALLBACK;
4810 opt->jo_close_cb = get_callback(item, &opt->jo_close_partial); 4781 opt->jo_close_cb = get_callback(item);
4811 if (opt->jo_close_cb == NULL) 4782 if (opt->jo_close_cb.cb_name == NULL)
4812 { 4783 {
4813 semsg(_(e_invargval), "close_cb"); 4784 semsg(_(e_invargval), "close_cb");
4814 return FAIL; 4785 return FAIL;
4815 } 4786 }
4816 } 4787 }
4831 else if (STRCMP(hi->hi_key, "exit_cb") == 0) 4802 else if (STRCMP(hi->hi_key, "exit_cb") == 0)
4832 { 4803 {
4833 if (!(supported & JO_EXIT_CB)) 4804 if (!(supported & JO_EXIT_CB))
4834 break; 4805 break;
4835 opt->jo_set |= JO_EXIT_CB; 4806 opt->jo_set |= JO_EXIT_CB;
4836 opt->jo_exit_cb = get_callback(item, &opt->jo_exit_partial); 4807 opt->jo_exit_cb = get_callback(item);
4837 if (opt->jo_exit_cb == NULL) 4808 if (opt->jo_exit_cb.cb_name == NULL)
4838 { 4809 {
4839 semsg(_(e_invargval), "exit_cb"); 4810 semsg(_(e_invargval), "exit_cb");
4840 return FAIL; 4811 return FAIL;
4841 } 4812 }
4842 } 4813 }
5199 vim_free(job->jv_termsig); 5170 vim_free(job->jv_termsig);
5200 #endif 5171 #endif
5201 #ifdef MSWIN 5172 #ifdef MSWIN
5202 vim_free(job->jv_tty_type); 5173 vim_free(job->jv_tty_type);
5203 #endif 5174 #endif
5204 free_callback(job->jv_exit_cb, job->jv_exit_partial); 5175 free_callback(&job->jv_exit_cb);
5205 if (job->jv_argv != NULL) 5176 if (job->jv_argv != NULL)
5206 { 5177 {
5207 for (i = 0; job->jv_argv[i] != NULL; i++) 5178 for (i = 0; job->jv_argv[i] != NULL; i++)
5208 vim_free(job->jv_argv[i]); 5179 vim_free(job->jv_argv[i]);
5209 vim_free(job->jv_argv); 5180 vim_free(job->jv_argv);
5287 */ 5258 */
5288 static int 5259 static int
5289 job_need_end_check(job_T *job) 5260 job_need_end_check(job_T *job)
5290 { 5261 {
5291 return job->jv_status == JOB_STARTED 5262 return job->jv_status == JOB_STARTED
5292 && (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL); 5263 && (job->jv_stoponexit != NULL || job->jv_exit_cb.cb_name != NULL);
5293 } 5264 }
5294 5265
5295 /* 5266 /*
5296 * Return TRUE if the channel of "job" is still useful. 5267 * Return TRUE if the channel of "job" is still useful.
5297 */ 5268 */
5463 5434
5464 /* When only channel-in is kept open, close explicitly. */ 5435 /* When only channel-in is kept open, close explicitly. */
5465 if (job->jv_channel != NULL) 5436 if (job->jv_channel != NULL)
5466 ch_close_part(job->jv_channel, PART_IN); 5437 ch_close_part(job->jv_channel, PART_IN);
5467 5438
5468 if (job->jv_exit_cb != NULL) 5439 if (job->jv_exit_cb.cb_name != NULL)
5469 { 5440 {
5470 typval_T argv[3]; 5441 typval_T argv[3];
5471 typval_T rettv; 5442 typval_T rettv;
5472 int dummy; 5443 int dummy;
5473 5444
5474 /* Invoke the exit callback. Make sure the refcount is > 0. */ 5445 /* Invoke the exit callback. Make sure the refcount is > 0. */
5475 ch_log(job->jv_channel, "Invoking exit callback %s", job->jv_exit_cb); 5446 ch_log(job->jv_channel, "Invoking exit callback %s",
5447 job->jv_exit_cb.cb_name);
5476 ++job->jv_refcount; 5448 ++job->jv_refcount;
5477 argv[0].v_type = VAR_JOB; 5449 argv[0].v_type = VAR_JOB;
5478 argv[0].vval.v_job = job; 5450 argv[0].vval.v_job = job;
5479 argv[1].v_type = VAR_NUMBER; 5451 argv[1].v_type = VAR_NUMBER;
5480 argv[1].vval.v_number = job->jv_exitval; 5452 argv[1].vval.v_number = job->jv_exitval;
5481 call_func(job->jv_exit_cb, -1, 5453 call_callback(&job->jv_exit_cb, -1,
5482 &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, 5454 &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
5483 job->jv_exit_partial, NULL);
5484 clear_tv(&rettv); 5455 clear_tv(&rettv);
5485 --job->jv_refcount; 5456 --job->jv_refcount;
5486 channel_need_redraw = TRUE; 5457 channel_need_redraw = TRUE;
5487 } 5458 }
5488 5459
5620 else 5591 else
5621 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit); 5592 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit);
5622 } 5593 }
5623 if (opt->jo_set & JO_EXIT_CB) 5594 if (opt->jo_set & JO_EXIT_CB)
5624 { 5595 {
5625 free_callback(job->jv_exit_cb, job->jv_exit_partial); 5596 free_callback(&job->jv_exit_cb);
5626 if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL) 5597 if (opt->jo_exit_cb.cb_name == NULL || *opt->jo_exit_cb.cb_name == NUL)
5627 { 5598 {
5628 job->jv_exit_cb = NULL; 5599 job->jv_exit_cb.cb_name = NULL;
5629 job->jv_exit_partial = NULL; 5600 job->jv_exit_cb.cb_partial = NULL;
5630 } 5601 }
5631 else 5602 else
5632 { 5603 copy_callback(&job->jv_exit_cb, &opt->jo_exit_cb);
5633 job->jv_exit_partial = opt->jo_exit_partial;
5634 if (job->jv_exit_partial != NULL)
5635 {
5636 job->jv_exit_cb = opt->jo_exit_cb;
5637 ++job->jv_exit_partial->pt_refcount;
5638 }
5639 else
5640 {
5641 job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
5642 func_ref(job->jv_exit_cb);
5643 }
5644 }
5645 } 5604 }
5646 } 5605 }
5647 5606
5648 /* 5607 /*
5649 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag. 5608 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag.
5957 dict_add_number(dict, "process", nr); 5916 dict_add_number(dict, "process", nr);
5958 dict_add_string(dict, "tty_in", job->jv_tty_in); 5917 dict_add_string(dict, "tty_in", job->jv_tty_in);
5959 dict_add_string(dict, "tty_out", job->jv_tty_out); 5918 dict_add_string(dict, "tty_out", job->jv_tty_out);
5960 5919
5961 dict_add_number(dict, "exitval", job->jv_exitval); 5920 dict_add_number(dict, "exitval", job->jv_exitval);
5962 dict_add_string(dict, "exit_cb", job->jv_exit_cb); 5921 dict_add_string(dict, "exit_cb", job->jv_exit_cb.cb_name);
5963 dict_add_string(dict, "stoponexit", job->jv_stoponexit); 5922 dict_add_string(dict, "stoponexit", job->jv_stoponexit);
5964 #ifdef UNIX 5923 #ifdef UNIX
5965 dict_add_string(dict, "termsig", job->jv_termsig); 5924 dict_add_string(dict, "termsig", job->jv_termsig);
5966 #endif 5925 #endif
5967 #ifdef MSWIN 5926 #ifdef MSWIN
6057 // text can always be inserted above the last line. 6016 // text can always be inserted above the last line.
6058 ml_append(lnum, (char_u *)"", 0, FALSE); 6017 ml_append(lnum, (char_u *)"", 0, FALSE);
6059 curwin->w_cursor.lnum = lnum + 1; 6018 curwin->w_cursor.lnum = lnum + 1;
6060 curwin->w_cursor.col = 0; 6019 curwin->w_cursor.col = 0;
6061 6020
6062 if (curbuf->b_prompt_callback == NULL || *curbuf->b_prompt_callback == NUL) 6021 if (curbuf->b_prompt_callback.cb_name == NULL
6022 || *curbuf->b_prompt_callback.cb_name == NUL)
6063 return; 6023 return;
6064 text = ml_get(lnum); 6024 text = ml_get(lnum);
6065 prompt = prompt_text(); 6025 prompt = prompt_text();
6066 if (STRLEN(text) >= STRLEN(prompt)) 6026 if (STRLEN(text) >= STRLEN(prompt))
6067 text += STRLEN(prompt); 6027 text += STRLEN(prompt);
6068 argv[0].v_type = VAR_STRING; 6028 argv[0].v_type = VAR_STRING;
6069 argv[0].vval.v_string = vim_strsave(text); 6029 argv[0].vval.v_string = vim_strsave(text);
6070 argv[1].v_type = VAR_UNKNOWN; 6030 argv[1].v_type = VAR_UNKNOWN;
6071 6031
6072 call_func(curbuf->b_prompt_callback, -1, 6032 call_callback(&curbuf->b_prompt_callback, -1,
6073 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, 6033 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
6074 curbuf->b_prompt_partial, NULL);
6075 clear_tv(&argv[0]); 6034 clear_tv(&argv[0]);
6076 clear_tv(&rettv); 6035 clear_tv(&rettv);
6077 } 6036 }
6078 6037
6079 /* 6038 /*
6084 { 6043 {
6085 typval_T rettv; 6044 typval_T rettv;
6086 int dummy; 6045 int dummy;
6087 typval_T argv[1]; 6046 typval_T argv[1];
6088 6047
6089 if (curbuf->b_prompt_interrupt == NULL 6048 if (curbuf->b_prompt_interrupt.cb_name == NULL
6090 || *curbuf->b_prompt_interrupt == NUL) 6049 || *curbuf->b_prompt_interrupt.cb_name == NUL)
6091 return FALSE; 6050 return FALSE;
6092 argv[0].v_type = VAR_UNKNOWN; 6051 argv[0].v_type = VAR_UNKNOWN;
6093 6052
6094 got_int = FALSE; // don't skip executing commands 6053 got_int = FALSE; // don't skip executing commands
6095 call_func(curbuf->b_prompt_interrupt, -1, 6054 call_callback(&curbuf->b_prompt_interrupt, -1,
6096 &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, 6055 &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
6097 curbuf->b_prompt_int_partial, NULL);
6098 clear_tv(&rettv); 6056 clear_tv(&rettv);
6099 return TRUE; 6057 return TRUE;
6100 } 6058 }
6101 6059
6102 #endif /* FEAT_JOB_CHANNEL */ 6060 #endif /* FEAT_JOB_CHANNEL */