Mercurial > vim
comparison src/eval.c @ 8498:42277980a76d v7.4.1539
commit https://github.com/vim/vim/commit/8e2c942ce49f2555d7dc2088cf3aa856820c5e32
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Mar 12 13:43:33 2016 +0100
patch 7.4.1539
Problem: Too much code in eval.c.
Solution: Move job and channel code to channel.c.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 12 Mar 2016 13:45:04 +0100 |
parents | caed4b2d305f |
children | ee5cb2e9ed5a |
comparison
equal
deleted
inserted
replaced
8497:da01d5da2cfa | 8498:42277980a76d |
---|---|
834 static int eval_isnamec1(int c); | 834 static int eval_isnamec1(int c); |
835 static int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload); | 835 static int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload); |
836 static int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose); | 836 static int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose); |
837 static typval_T *alloc_string_tv(char_u *string); | 837 static typval_T *alloc_string_tv(char_u *string); |
838 static void init_tv(typval_T *varp); | 838 static void init_tv(typval_T *varp); |
839 static long get_tv_number(typval_T *varp); | |
840 #ifdef FEAT_FLOAT | 839 #ifdef FEAT_FLOAT |
841 static float_T get_tv_float(typval_T *varp); | 840 static float_T get_tv_float(typval_T *varp); |
842 #endif | 841 #endif |
843 static linenr_T get_tv_lnum(typval_T *argvars); | 842 static linenr_T get_tv_lnum(typval_T *argvars); |
844 static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf); | 843 static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf); |
845 static char_u *get_tv_string(typval_T *varp); | |
846 static char_u *get_tv_string_buf(typval_T *varp, char_u *buf); | |
847 static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); | 844 static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); |
848 static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); | 845 static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); |
849 static hashtab_T *find_var_ht(char_u *name, char_u **varname); | 846 static hashtab_T *find_var_ht(char_u *name, char_u **varname); |
850 static funccall_T *get_funccal(void); | 847 static funccall_T *get_funccal(void); |
851 static void vars_clear_ext(hashtab_T *ht, int free_val); | 848 static void vars_clear_ext(hashtab_T *ht, int free_val); |
7733 | 7730 |
7734 return OK; | 7731 return OK; |
7735 } | 7732 } |
7736 | 7733 |
7737 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) | 7734 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) |
7738 /* | |
7739 * Decrement the reference count on "channel" and maybe free it when it goes | |
7740 * down to zero. Don't free it if there is a pending action. | |
7741 * Returns TRUE when the channel is no longer referenced. | |
7742 */ | |
7743 int | |
7744 channel_unref(channel_T *channel) | |
7745 { | |
7746 if (channel != NULL && --channel->ch_refcount <= 0) | |
7747 return channel_may_free(channel); | |
7748 return FALSE; | |
7749 } | |
7750 | |
7751 static job_T *first_job = NULL; | |
7752 | |
7753 static void | |
7754 job_free(job_T *job) | |
7755 { | |
7756 ch_log(job->jv_channel, "Freeing job"); | |
7757 if (job->jv_channel != NULL) | |
7758 { | |
7759 /* The link from the channel to the job doesn't count as a reference, | |
7760 * thus don't decrement the refcount of the job. The reference from | |
7761 * the job to the channel does count the refrence, decrement it and | |
7762 * NULL the reference. We don't set ch_job_killed, unreferencing the | |
7763 * job doesn't mean it stops running. */ | |
7764 job->jv_channel->ch_job = NULL; | |
7765 channel_unref(job->jv_channel); | |
7766 } | |
7767 mch_clear_job(job); | |
7768 | |
7769 if (job->jv_next != NULL) | |
7770 job->jv_next->jv_prev = job->jv_prev; | |
7771 if (job->jv_prev == NULL) | |
7772 first_job = job->jv_next; | |
7773 else | |
7774 job->jv_prev->jv_next = job->jv_next; | |
7775 | |
7776 vim_free(job->jv_stoponexit); | |
7777 vim_free(job->jv_exit_cb); | |
7778 vim_free(job); | |
7779 } | |
7780 | |
7781 static void | |
7782 job_unref(job_T *job) | |
7783 { | |
7784 if (job != NULL && --job->jv_refcount <= 0) | |
7785 { | |
7786 /* Do not free the job when it has not ended yet and there is a | |
7787 * "stoponexit" flag or an exit callback. */ | |
7788 if (job->jv_status != JOB_STARTED | |
7789 || (job->jv_stoponexit == NULL && job->jv_exit_cb == NULL)) | |
7790 { | |
7791 job_free(job); | |
7792 } | |
7793 else if (job->jv_channel != NULL) | |
7794 { | |
7795 /* Do remove the link to the channel, otherwise it hangs | |
7796 * around until Vim exits. See job_free() for refcount. */ | |
7797 job->jv_channel->ch_job = NULL; | |
7798 channel_unref(job->jv_channel); | |
7799 job->jv_channel = NULL; | |
7800 } | |
7801 } | |
7802 } | |
7803 | |
7804 /* | |
7805 * Allocate a job. Sets the refcount to one and sets options default. | |
7806 */ | |
7807 static job_T * | |
7808 job_alloc(void) | |
7809 { | |
7810 job_T *job; | |
7811 | |
7812 job = (job_T *)alloc_clear(sizeof(job_T)); | |
7813 if (job != NULL) | |
7814 { | |
7815 job->jv_refcount = 1; | |
7816 job->jv_stoponexit = vim_strsave((char_u *)"term"); | |
7817 | |
7818 if (first_job != NULL) | |
7819 { | |
7820 first_job->jv_prev = job; | |
7821 job->jv_next = first_job; | |
7822 } | |
7823 first_job = job; | |
7824 } | |
7825 return job; | |
7826 } | |
7827 | |
7828 static void | |
7829 job_set_options(job_T *job, jobopt_T *opt) | |
7830 { | |
7831 if (opt->jo_set & JO_STOPONEXIT) | |
7832 { | |
7833 vim_free(job->jv_stoponexit); | |
7834 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL) | |
7835 job->jv_stoponexit = NULL; | |
7836 else | |
7837 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit); | |
7838 } | |
7839 if (opt->jo_set & JO_EXIT_CB) | |
7840 { | |
7841 vim_free(job->jv_exit_cb); | |
7842 if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL) | |
7843 job->jv_exit_cb = NULL; | |
7844 else | |
7845 job->jv_exit_cb = vim_strsave(opt->jo_exit_cb); | |
7846 } | |
7847 } | |
7848 | |
7849 /* | |
7850 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag. | |
7851 */ | |
7852 void | |
7853 job_stop_on_exit() | |
7854 { | |
7855 job_T *job; | |
7856 | |
7857 for (job = first_job; job != NULL; job = job->jv_next) | |
7858 if (job->jv_status == JOB_STARTED && job->jv_stoponexit != NULL) | |
7859 mch_stop_job(job, job->jv_stoponexit); | |
7860 } | |
7861 #endif | 7735 #endif |
7862 | 7736 |
7863 static char * | 7737 static char * |
7864 get_var_special_name(int nr) | 7738 get_var_special_name(int nr) |
7865 { | 7739 { |
9648 | 9522 |
9649 buf = find_buffer(&argvars[0]); | 9523 buf = find_buffer(&argvars[0]); |
9650 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); | 9524 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); |
9651 } | 9525 } |
9652 | 9526 |
9653 static buf_T * | 9527 buf_T * |
9654 buflist_find_by_name(char_u *name, int curtab_only) | 9528 buflist_find_by_name(char_u *name, int curtab_only) |
9655 { | 9529 { |
9656 int save_magic; | 9530 int save_magic; |
9657 char_u *save_cpo; | 9531 char_u *save_cpo; |
9658 buf_T *buf; | 9532 buf_T *buf; |
9939 else | 9813 else |
9940 rettv->vval.v_float = 0.0; | 9814 rettv->vval.v_float = 0.0; |
9941 } | 9815 } |
9942 #endif | 9816 #endif |
9943 | 9817 |
9944 #if defined(FEAT_JOB_CHANNEL) | |
9945 /* | |
9946 * Get a callback from "arg". It can be a Funcref or a function name. | |
9947 * When "arg" is zero return an empty string. | |
9948 * Return NULL for an invalid argument. | |
9949 */ | |
9950 static char_u * | |
9951 get_callback(typval_T *arg) | |
9952 { | |
9953 if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING) | |
9954 return arg->vval.v_string; | |
9955 if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0) | |
9956 return (char_u *)""; | |
9957 EMSG(_("E999: Invalid callback argument")); | |
9958 return NULL; | |
9959 } | |
9960 | |
9961 static int | |
9962 handle_mode(typval_T *item, jobopt_T *opt, ch_mode_T *modep, int jo) | |
9963 { | |
9964 char_u *val = get_tv_string(item); | |
9965 | |
9966 opt->jo_set |= jo; | |
9967 if (STRCMP(val, "nl") == 0) | |
9968 *modep = MODE_NL; | |
9969 else if (STRCMP(val, "raw") == 0) | |
9970 *modep = MODE_RAW; | |
9971 else if (STRCMP(val, "js") == 0) | |
9972 *modep = MODE_JS; | |
9973 else if (STRCMP(val, "json") == 0) | |
9974 *modep = MODE_JSON; | |
9975 else | |
9976 { | |
9977 EMSG2(_(e_invarg2), val); | |
9978 return FAIL; | |
9979 } | |
9980 return OK; | |
9981 } | |
9982 | |
9983 static int | |
9984 handle_io(typval_T *item, int part, jobopt_T *opt) | |
9985 { | |
9986 char_u *val = get_tv_string(item); | |
9987 | |
9988 opt->jo_set |= JO_OUT_IO << (part - PART_OUT); | |
9989 if (STRCMP(val, "null") == 0) | |
9990 opt->jo_io[part] = JIO_NULL; | |
9991 else if (STRCMP(val, "pipe") == 0) | |
9992 opt->jo_io[part] = JIO_PIPE; | |
9993 else if (STRCMP(val, "file") == 0) | |
9994 opt->jo_io[part] = JIO_FILE; | |
9995 else if (STRCMP(val, "buffer") == 0) | |
9996 opt->jo_io[part] = JIO_BUFFER; | |
9997 else if (STRCMP(val, "out") == 0 && part == PART_ERR) | |
9998 opt->jo_io[part] = JIO_OUT; | |
9999 else | |
10000 { | |
10001 EMSG2(_(e_invarg2), val); | |
10002 return FAIL; | |
10003 } | |
10004 return OK; | |
10005 } | |
10006 | |
10007 static void | |
10008 clear_job_options(jobopt_T *opt) | |
10009 { | |
10010 vim_memset(opt, 0, sizeof(jobopt_T)); | |
10011 } | |
10012 | |
10013 /* | |
10014 * Get the PART_ number from the first character of an option name. | |
10015 */ | |
10016 static int | |
10017 part_from_char(int c) | |
10018 { | |
10019 return c == 'i' ? PART_IN : c == 'o' ? PART_OUT: PART_ERR; | |
10020 } | |
10021 | |
10022 /* | |
10023 * Get the option entries from the dict in "tv", parse them and put the result | |
10024 * in "opt". | |
10025 * Only accept options in "supported". | |
10026 * If an option value is invalid return FAIL. | |
10027 */ | |
10028 static int | |
10029 get_job_options(typval_T *tv, jobopt_T *opt, int supported) | |
10030 { | |
10031 typval_T *item; | |
10032 char_u *val; | |
10033 dict_T *dict; | |
10034 int todo; | |
10035 hashitem_T *hi; | |
10036 int part; | |
10037 | |
10038 opt->jo_set = 0; | |
10039 if (tv->v_type == VAR_UNKNOWN) | |
10040 return OK; | |
10041 if (tv->v_type != VAR_DICT) | |
10042 { | |
10043 EMSG(_(e_invarg)); | |
10044 return FAIL; | |
10045 } | |
10046 dict = tv->vval.v_dict; | |
10047 if (dict == NULL) | |
10048 return OK; | |
10049 | |
10050 todo = (int)dict->dv_hashtab.ht_used; | |
10051 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi) | |
10052 if (!HASHITEM_EMPTY(hi)) | |
10053 { | |
10054 item = &HI2DI(hi)->di_tv; | |
10055 | |
10056 if (STRCMP(hi->hi_key, "mode") == 0) | |
10057 { | |
10058 if (!(supported & JO_MODE)) | |
10059 break; | |
10060 if (handle_mode(item, opt, &opt->jo_mode, JO_MODE) == FAIL) | |
10061 return FAIL; | |
10062 } | |
10063 else if (STRCMP(hi->hi_key, "in-mode") == 0) | |
10064 { | |
10065 if (!(supported & JO_IN_MODE)) | |
10066 break; | |
10067 if (handle_mode(item, opt, &opt->jo_in_mode, JO_IN_MODE) | |
10068 == FAIL) | |
10069 return FAIL; | |
10070 } | |
10071 else if (STRCMP(hi->hi_key, "out-mode") == 0) | |
10072 { | |
10073 if (!(supported & JO_OUT_MODE)) | |
10074 break; | |
10075 if (handle_mode(item, opt, &opt->jo_out_mode, JO_OUT_MODE) | |
10076 == FAIL) | |
10077 return FAIL; | |
10078 } | |
10079 else if (STRCMP(hi->hi_key, "err-mode") == 0) | |
10080 { | |
10081 if (!(supported & JO_ERR_MODE)) | |
10082 break; | |
10083 if (handle_mode(item, opt, &opt->jo_err_mode, JO_ERR_MODE) | |
10084 == FAIL) | |
10085 return FAIL; | |
10086 } | |
10087 else if (STRCMP(hi->hi_key, "in-io") == 0 | |
10088 || STRCMP(hi->hi_key, "out-io") == 0 | |
10089 || STRCMP(hi->hi_key, "err-io") == 0) | |
10090 { | |
10091 if (!(supported & JO_OUT_IO)) | |
10092 break; | |
10093 if (handle_io(item, part_from_char(*hi->hi_key), opt) == FAIL) | |
10094 return FAIL; | |
10095 } | |
10096 else if (STRCMP(hi->hi_key, "in-name") == 0 | |
10097 || STRCMP(hi->hi_key, "out-name") == 0 | |
10098 || STRCMP(hi->hi_key, "err-name") == 0) | |
10099 { | |
10100 part = part_from_char(*hi->hi_key); | |
10101 | |
10102 if (!(supported & JO_OUT_IO)) | |
10103 break; | |
10104 opt->jo_set |= JO_OUT_NAME << (part - PART_OUT); | |
10105 opt->jo_io_name[part] = | |
10106 get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]); | |
10107 } | |
10108 else if (STRCMP(hi->hi_key, "in-buf") == 0 | |
10109 || STRCMP(hi->hi_key, "out-buf") == 0 | |
10110 || STRCMP(hi->hi_key, "err-buf") == 0) | |
10111 { | |
10112 part = part_from_char(*hi->hi_key); | |
10113 | |
10114 if (!(supported & JO_OUT_IO)) | |
10115 break; | |
10116 opt->jo_set |= JO_OUT_BUF << (part - PART_OUT); | |
10117 opt->jo_io_buf[part] = get_tv_number(item); | |
10118 if (opt->jo_io_buf[part] <= 0) | |
10119 { | |
10120 EMSG2(_(e_invarg2), get_tv_string(item)); | |
10121 return FAIL; | |
10122 } | |
10123 if (buflist_findnr(opt->jo_io_buf[part]) == NULL) | |
10124 { | |
10125 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[part]); | |
10126 return FAIL; | |
10127 } | |
10128 } | |
10129 else if (STRCMP(hi->hi_key, "in-top") == 0 | |
10130 || STRCMP(hi->hi_key, "in-bot") == 0) | |
10131 { | |
10132 linenr_T *lp; | |
10133 | |
10134 if (!(supported & JO_OUT_IO)) | |
10135 break; | |
10136 if (hi->hi_key[3] == 't') | |
10137 { | |
10138 lp = &opt->jo_in_top; | |
10139 opt->jo_set |= JO_IN_TOP; | |
10140 } | |
10141 else | |
10142 { | |
10143 lp = &opt->jo_in_bot; | |
10144 opt->jo_set |= JO_IN_BOT; | |
10145 } | |
10146 *lp = get_tv_number(item); | |
10147 if (*lp < 0) | |
10148 { | |
10149 EMSG2(_(e_invarg2), get_tv_string(item)); | |
10150 return FAIL; | |
10151 } | |
10152 } | |
10153 else if (STRCMP(hi->hi_key, "channel") == 0) | |
10154 { | |
10155 if (!(supported & JO_OUT_IO)) | |
10156 break; | |
10157 opt->jo_set |= JO_CHANNEL; | |
10158 if (item->v_type != VAR_CHANNEL) | |
10159 { | |
10160 EMSG2(_(e_invarg2), "channel"); | |
10161 return FAIL; | |
10162 } | |
10163 opt->jo_channel = item->vval.v_channel; | |
10164 } | |
10165 else if (STRCMP(hi->hi_key, "callback") == 0) | |
10166 { | |
10167 if (!(supported & JO_CALLBACK)) | |
10168 break; | |
10169 opt->jo_set |= JO_CALLBACK; | |
10170 opt->jo_callback = get_callback(item); | |
10171 if (opt->jo_callback == NULL) | |
10172 { | |
10173 EMSG2(_(e_invarg2), "callback"); | |
10174 return FAIL; | |
10175 } | |
10176 } | |
10177 else if (STRCMP(hi->hi_key, "out-cb") == 0) | |
10178 { | |
10179 if (!(supported & JO_OUT_CALLBACK)) | |
10180 break; | |
10181 opt->jo_set |= JO_OUT_CALLBACK; | |
10182 opt->jo_out_cb = get_callback(item); | |
10183 if (opt->jo_out_cb == NULL) | |
10184 { | |
10185 EMSG2(_(e_invarg2), "out-cb"); | |
10186 return FAIL; | |
10187 } | |
10188 } | |
10189 else if (STRCMP(hi->hi_key, "err-cb") == 0) | |
10190 { | |
10191 if (!(supported & JO_ERR_CALLBACK)) | |
10192 break; | |
10193 opt->jo_set |= JO_ERR_CALLBACK; | |
10194 opt->jo_err_cb = get_callback(item); | |
10195 if (opt->jo_err_cb == NULL) | |
10196 { | |
10197 EMSG2(_(e_invarg2), "err-cb"); | |
10198 return FAIL; | |
10199 } | |
10200 } | |
10201 else if (STRCMP(hi->hi_key, "close-cb") == 0) | |
10202 { | |
10203 if (!(supported & JO_CLOSE_CALLBACK)) | |
10204 break; | |
10205 opt->jo_set |= JO_CLOSE_CALLBACK; | |
10206 opt->jo_close_cb = get_callback(item); | |
10207 if (opt->jo_close_cb == NULL) | |
10208 { | |
10209 EMSG2(_(e_invarg2), "close-cb"); | |
10210 return FAIL; | |
10211 } | |
10212 } | |
10213 else if (STRCMP(hi->hi_key, "waittime") == 0) | |
10214 { | |
10215 if (!(supported & JO_WAITTIME)) | |
10216 break; | |
10217 opt->jo_set |= JO_WAITTIME; | |
10218 opt->jo_waittime = get_tv_number(item); | |
10219 } | |
10220 else if (STRCMP(hi->hi_key, "timeout") == 0) | |
10221 { | |
10222 if (!(supported & JO_TIMEOUT)) | |
10223 break; | |
10224 opt->jo_set |= JO_TIMEOUT; | |
10225 opt->jo_timeout = get_tv_number(item); | |
10226 } | |
10227 else if (STRCMP(hi->hi_key, "out-timeout") == 0) | |
10228 { | |
10229 if (!(supported & JO_OUT_TIMEOUT)) | |
10230 break; | |
10231 opt->jo_set |= JO_OUT_TIMEOUT; | |
10232 opt->jo_out_timeout = get_tv_number(item); | |
10233 } | |
10234 else if (STRCMP(hi->hi_key, "err-timeout") == 0) | |
10235 { | |
10236 if (!(supported & JO_ERR_TIMEOUT)) | |
10237 break; | |
10238 opt->jo_set |= JO_ERR_TIMEOUT; | |
10239 opt->jo_err_timeout = get_tv_number(item); | |
10240 } | |
10241 else if (STRCMP(hi->hi_key, "part") == 0) | |
10242 { | |
10243 if (!(supported & JO_PART)) | |
10244 break; | |
10245 opt->jo_set |= JO_PART; | |
10246 val = get_tv_string(item); | |
10247 if (STRCMP(val, "err") == 0) | |
10248 opt->jo_part = PART_ERR; | |
10249 else | |
10250 { | |
10251 EMSG2(_(e_invarg2), val); | |
10252 return FAIL; | |
10253 } | |
10254 } | |
10255 else if (STRCMP(hi->hi_key, "id") == 0) | |
10256 { | |
10257 if (!(supported & JO_ID)) | |
10258 break; | |
10259 opt->jo_set |= JO_ID; | |
10260 opt->jo_id = get_tv_number(item); | |
10261 } | |
10262 else if (STRCMP(hi->hi_key, "stoponexit") == 0) | |
10263 { | |
10264 if (!(supported & JO_STOPONEXIT)) | |
10265 break; | |
10266 opt->jo_set |= JO_STOPONEXIT; | |
10267 opt->jo_stoponexit = get_tv_string_buf_chk(item, | |
10268 opt->jo_soe_buf); | |
10269 if (opt->jo_stoponexit == NULL) | |
10270 { | |
10271 EMSG2(_(e_invarg2), "stoponexit"); | |
10272 return FAIL; | |
10273 } | |
10274 } | |
10275 else if (STRCMP(hi->hi_key, "exit-cb") == 0) | |
10276 { | |
10277 if (!(supported & JO_EXIT_CB)) | |
10278 break; | |
10279 opt->jo_set |= JO_EXIT_CB; | |
10280 opt->jo_exit_cb = get_tv_string_buf_chk(item, opt->jo_ecb_buf); | |
10281 if (opt->jo_exit_cb == NULL) | |
10282 { | |
10283 EMSG2(_(e_invarg2), "exit-cb"); | |
10284 return FAIL; | |
10285 } | |
10286 } | |
10287 else | |
10288 break; | |
10289 --todo; | |
10290 } | |
10291 if (todo > 0) | |
10292 { | |
10293 EMSG2(_(e_invarg2), hi->hi_key); | |
10294 return FAIL; | |
10295 } | |
10296 | |
10297 return OK; | |
10298 } | |
10299 #endif | |
10300 | |
10301 #ifdef FEAT_JOB_CHANNEL | 9818 #ifdef FEAT_JOB_CHANNEL |
10302 /* | |
10303 * Get the channel from the argument. | |
10304 * Returns NULL if the handle is invalid. | |
10305 */ | |
10306 static channel_T * | |
10307 get_channel_arg(typval_T *tv, int check_open) | |
10308 { | |
10309 channel_T *channel = NULL; | |
10310 | |
10311 if (tv->v_type == VAR_JOB) | |
10312 { | |
10313 if (tv->vval.v_job != NULL) | |
10314 channel = tv->vval.v_job->jv_channel; | |
10315 } | |
10316 else if (tv->v_type == VAR_CHANNEL) | |
10317 { | |
10318 channel = tv->vval.v_channel; | |
10319 } | |
10320 else | |
10321 { | |
10322 EMSG2(_(e_invarg2), get_tv_string(tv)); | |
10323 return NULL; | |
10324 } | |
10325 | |
10326 if (check_open && (channel == NULL || !channel_is_open(channel))) | |
10327 { | |
10328 EMSG(_("E906: not an open channel")); | |
10329 return NULL; | |
10330 } | |
10331 return channel; | |
10332 } | |
10333 | |
10334 /* | 9819 /* |
10335 * "ch_close()" function | 9820 * "ch_close()" function |
10336 */ | 9821 */ |
10337 static void | 9822 static void |
10338 f_ch_close(typval_T *argvars, typval_T *rettv UNUSED) | 9823 f_ch_close(typval_T *argvars, typval_T *rettv UNUSED) |
10412 f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED) | 9897 f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED) |
10413 { | 9898 { |
10414 char_u *fname; | 9899 char_u *fname; |
10415 char_u *opt = (char_u *)""; | 9900 char_u *opt = (char_u *)""; |
10416 char_u buf[NUMBUFLEN]; | 9901 char_u buf[NUMBUFLEN]; |
10417 FILE *file = NULL; | |
10418 | 9902 |
10419 fname = get_tv_string(&argvars[0]); | 9903 fname = get_tv_string(&argvars[0]); |
10420 if (argvars[1].v_type == VAR_STRING) | 9904 if (argvars[1].v_type == VAR_STRING) |
10421 opt = get_tv_string_buf(&argvars[1], buf); | 9905 opt = get_tv_string_buf(&argvars[1], buf); |
10422 if (*fname != NUL) | 9906 ch_logfile(fname, opt); |
10423 { | |
10424 file = fopen((char *)fname, *opt == 'w' ? "w" : "a"); | |
10425 if (file == NULL) | |
10426 { | |
10427 EMSG2(_(e_notopen), fname); | |
10428 return; | |
10429 } | |
10430 } | |
10431 ch_logfile(file); | |
10432 } | 9907 } |
10433 | 9908 |
10434 /* | 9909 /* |
10435 * "ch_open()" function | 9910 * "ch_open()" function |
10436 */ | 9911 */ |
10437 static void | 9912 static void |
10438 f_ch_open(typval_T *argvars, typval_T *rettv) | 9913 f_ch_open(typval_T *argvars, typval_T *rettv) |
10439 { | 9914 { |
10440 char_u *address; | |
10441 char_u *p; | |
10442 char *rest; | |
10443 int port; | |
10444 jobopt_T opt; | |
10445 channel_T *channel; | |
10446 | |
10447 /* default: fail */ | |
10448 rettv->v_type = VAR_CHANNEL; | 9915 rettv->v_type = VAR_CHANNEL; |
10449 rettv->vval.v_channel = NULL; | 9916 rettv->vval.v_channel = channel_open_func(argvars); |
10450 | |
10451 address = get_tv_string(&argvars[0]); | |
10452 if (argvars[1].v_type != VAR_UNKNOWN | |
10453 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)) | |
10454 { | |
10455 EMSG(_(e_invarg)); | |
10456 return; | |
10457 } | |
10458 | |
10459 /* parse address */ | |
10460 p = vim_strchr(address, ':'); | |
10461 if (p == NULL) | |
10462 { | |
10463 EMSG2(_(e_invarg2), address); | |
10464 return; | |
10465 } | |
10466 *p++ = NUL; | |
10467 port = strtol((char *)p, &rest, 10); | |
10468 if (*address == NUL || port <= 0 || *rest != NUL) | |
10469 { | |
10470 p[-1] = ':'; | |
10471 EMSG2(_(e_invarg2), address); | |
10472 return; | |
10473 } | |
10474 | |
10475 /* parse options */ | |
10476 clear_job_options(&opt); | |
10477 opt.jo_mode = MODE_JSON; | |
10478 opt.jo_timeout = 2000; | |
10479 if (get_job_options(&argvars[1], &opt, | |
10480 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL) == FAIL) | |
10481 return; | |
10482 if (opt.jo_timeout < 0) | |
10483 { | |
10484 EMSG(_(e_invarg)); | |
10485 return; | |
10486 } | |
10487 | |
10488 channel = channel_open((char *)address, port, opt.jo_waittime, NULL); | |
10489 if (channel != NULL) | |
10490 { | |
10491 rettv->vval.v_channel = channel; | |
10492 opt.jo_set = JO_ALL; | |
10493 channel_set_options(channel, &opt); | |
10494 } | |
10495 } | |
10496 | |
10497 /* | |
10498 * Common for ch_read() and ch_readraw(). | |
10499 */ | |
10500 static void | |
10501 common_channel_read(typval_T *argvars, typval_T *rettv, int raw) | |
10502 { | |
10503 channel_T *channel; | |
10504 int part; | |
10505 jobopt_T opt; | |
10506 int mode; | |
10507 int timeout; | |
10508 int id = -1; | |
10509 typval_T *listtv = NULL; | |
10510 | |
10511 /* return an empty string by default */ | |
10512 rettv->v_type = VAR_STRING; | |
10513 rettv->vval.v_string = NULL; | |
10514 | |
10515 clear_job_options(&opt); | |
10516 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID) | |
10517 == FAIL) | |
10518 return; | |
10519 | |
10520 channel = get_channel_arg(&argvars[0], TRUE); | |
10521 if (channel != NULL) | |
10522 { | |
10523 if (opt.jo_set & JO_PART) | |
10524 part = opt.jo_part; | |
10525 else | |
10526 part = channel_part_read(channel); | |
10527 mode = channel_get_mode(channel, part); | |
10528 timeout = channel_get_timeout(channel, part); | |
10529 if (opt.jo_set & JO_TIMEOUT) | |
10530 timeout = opt.jo_timeout; | |
10531 | |
10532 if (raw || mode == MODE_RAW || mode == MODE_NL) | |
10533 rettv->vval.v_string = channel_read_block(channel, part, timeout); | |
10534 else | |
10535 { | |
10536 if (opt.jo_set & JO_ID) | |
10537 id = opt.jo_id; | |
10538 channel_read_json_block(channel, part, timeout, id, &listtv); | |
10539 if (listtv != NULL) | |
10540 { | |
10541 *rettv = *listtv; | |
10542 vim_free(listtv); | |
10543 } | |
10544 else | |
10545 { | |
10546 rettv->v_type = VAR_SPECIAL; | |
10547 rettv->vval.v_number = VVAL_NONE; | |
10548 } | |
10549 } | |
10550 } | |
10551 } | 9917 } |
10552 | 9918 |
10553 /* | 9919 /* |
10554 * "ch_read()" function | 9920 * "ch_read()" function |
10555 */ | 9921 */ |
10567 { | 9933 { |
10568 common_channel_read(argvars, rettv, TRUE); | 9934 common_channel_read(argvars, rettv, TRUE); |
10569 } | 9935 } |
10570 | 9936 |
10571 /* | 9937 /* |
10572 * common for "sendexpr()" and "sendraw()" | |
10573 * Returns the channel if the caller should read the response. | |
10574 * Sets "part_read" to the the read fd. | |
10575 * Otherwise returns NULL. | |
10576 */ | |
10577 static channel_T * | |
10578 send_common( | |
10579 typval_T *argvars, | |
10580 char_u *text, | |
10581 int id, | |
10582 int eval, | |
10583 jobopt_T *opt, | |
10584 char *fun, | |
10585 int *part_read) | |
10586 { | |
10587 channel_T *channel; | |
10588 int part_send; | |
10589 | |
10590 channel = get_channel_arg(&argvars[0], TRUE); | |
10591 if (channel == NULL) | |
10592 return NULL; | |
10593 part_send = channel_part_send(channel); | |
10594 *part_read = channel_part_read(channel); | |
10595 | |
10596 clear_job_options(opt); | |
10597 if (get_job_options(&argvars[2], opt, JO_CALLBACK + JO_TIMEOUT) == FAIL) | |
10598 return NULL; | |
10599 | |
10600 /* Set the callback. An empty callback means no callback and not reading | |
10601 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not | |
10602 * allowed. */ | |
10603 if (opt->jo_callback != NULL && *opt->jo_callback != NUL) | |
10604 { | |
10605 if (eval) | |
10606 { | |
10607 EMSG2(_("E917: Cannot use a callback with %s()"), fun); | |
10608 return NULL; | |
10609 } | |
10610 channel_set_req_callback(channel, part_send, opt->jo_callback, id); | |
10611 } | |
10612 | |
10613 if (channel_send(channel, part_send, text, fun) == OK | |
10614 && opt->jo_callback == NULL) | |
10615 return channel; | |
10616 return NULL; | |
10617 } | |
10618 | |
10619 /* | |
10620 * common for "ch_evalexpr()" and "ch_sendexpr()" | |
10621 */ | |
10622 static void | |
10623 ch_expr_common(typval_T *argvars, typval_T *rettv, int eval) | |
10624 { | |
10625 char_u *text; | |
10626 typval_T *listtv; | |
10627 channel_T *channel; | |
10628 int id; | |
10629 ch_mode_T ch_mode; | |
10630 int part_send; | |
10631 int part_read; | |
10632 jobopt_T opt; | |
10633 int timeout; | |
10634 | |
10635 /* return an empty string by default */ | |
10636 rettv->v_type = VAR_STRING; | |
10637 rettv->vval.v_string = NULL; | |
10638 | |
10639 channel = get_channel_arg(&argvars[0], TRUE); | |
10640 if (channel == NULL) | |
10641 return; | |
10642 part_send = channel_part_send(channel); | |
10643 | |
10644 ch_mode = channel_get_mode(channel, part_send); | |
10645 if (ch_mode == MODE_RAW || ch_mode == MODE_NL) | |
10646 { | |
10647 EMSG(_("E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel")); | |
10648 return; | |
10649 } | |
10650 | |
10651 id = channel_get_id(); | |
10652 text = json_encode_nr_expr(id, &argvars[1], | |
10653 ch_mode == MODE_JS ? JSON_JS : 0); | |
10654 if (text == NULL) | |
10655 return; | |
10656 | |
10657 channel = send_common(argvars, text, id, eval, &opt, | |
10658 eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); | |
10659 vim_free(text); | |
10660 if (channel != NULL && eval) | |
10661 { | |
10662 if (opt.jo_set & JO_TIMEOUT) | |
10663 timeout = opt.jo_timeout; | |
10664 else | |
10665 timeout = channel_get_timeout(channel, part_read); | |
10666 timeout = channel_get_timeout(channel, part_read); | |
10667 if (channel_read_json_block(channel, part_read, timeout, id, &listtv) | |
10668 == OK) | |
10669 { | |
10670 list_T *list = listtv->vval.v_list; | |
10671 | |
10672 /* Move the item from the list and then change the type to | |
10673 * avoid the value being freed. */ | |
10674 *rettv = list->lv_last->li_tv; | |
10675 list->lv_last->li_tv.v_type = VAR_NUMBER; | |
10676 free_tv(listtv); | |
10677 } | |
10678 } | |
10679 } | |
10680 | |
10681 /* | |
10682 * "ch_evalexpr()" function | 9938 * "ch_evalexpr()" function |
10683 */ | 9939 */ |
10684 static void | 9940 static void |
10685 f_ch_evalexpr(typval_T *argvars, typval_T *rettv) | 9941 f_ch_evalexpr(typval_T *argvars, typval_T *rettv) |
10686 { | 9942 { |
10692 */ | 9948 */ |
10693 static void | 9949 static void |
10694 f_ch_sendexpr(typval_T *argvars, typval_T *rettv) | 9950 f_ch_sendexpr(typval_T *argvars, typval_T *rettv) |
10695 { | 9951 { |
10696 ch_expr_common(argvars, rettv, FALSE); | 9952 ch_expr_common(argvars, rettv, FALSE); |
10697 } | |
10698 | |
10699 /* | |
10700 * common for "ch_evalraw()" and "ch_sendraw()" | |
10701 */ | |
10702 static void | |
10703 ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) | |
10704 { | |
10705 char_u buf[NUMBUFLEN]; | |
10706 char_u *text; | |
10707 channel_T *channel; | |
10708 int part_read; | |
10709 jobopt_T opt; | |
10710 int timeout; | |
10711 | |
10712 /* return an empty string by default */ | |
10713 rettv->v_type = VAR_STRING; | |
10714 rettv->vval.v_string = NULL; | |
10715 | |
10716 text = get_tv_string_buf(&argvars[1], buf); | |
10717 channel = send_common(argvars, text, 0, eval, &opt, | |
10718 eval ? "ch_evalraw" : "ch_sendraw", &part_read); | |
10719 if (channel != NULL && eval) | |
10720 { | |
10721 if (opt.jo_set & JO_TIMEOUT) | |
10722 timeout = opt.jo_timeout; | |
10723 else | |
10724 timeout = channel_get_timeout(channel, part_read); | |
10725 rettv->vval.v_string = channel_read_block(channel, part_read, timeout); | |
10726 } | |
10727 } | 9953 } |
10728 | 9954 |
10729 /* | 9955 /* |
10730 * "ch_evalraw()" function | 9956 * "ch_evalraw()" function |
10731 */ | 9957 */ |
15136 * "job_start()" function | 14362 * "job_start()" function |
15137 */ | 14363 */ |
15138 static void | 14364 static void |
15139 f_job_start(typval_T *argvars, typval_T *rettv) | 14365 f_job_start(typval_T *argvars, typval_T *rettv) |
15140 { | 14366 { |
15141 job_T *job; | |
15142 char_u *cmd = NULL; | |
15143 #if defined(UNIX) | |
15144 # define USE_ARGV | |
15145 char **argv = NULL; | |
15146 int argc = 0; | |
15147 #else | |
15148 garray_T ga; | |
15149 #endif | |
15150 jobopt_T opt; | |
15151 int part; | |
15152 | |
15153 rettv->v_type = VAR_JOB; | 14367 rettv->v_type = VAR_JOB; |
15154 job = job_alloc(); | 14368 rettv->vval.v_job = job_start(argvars); |
15155 rettv->vval.v_job = job; | |
15156 if (job == NULL) | |
15157 return; | |
15158 | |
15159 rettv->vval.v_job->jv_status = JOB_FAILED; | |
15160 | |
15161 /* Default mode is NL. */ | |
15162 clear_job_options(&opt); | |
15163 opt.jo_mode = MODE_NL; | |
15164 if (get_job_options(&argvars[1], &opt, | |
15165 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL | |
15166 + JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL) | |
15167 return; | |
15168 | |
15169 /* Check that when io is "file" that there is a file name. */ | |
15170 for (part = PART_OUT; part <= PART_IN; ++part) | |
15171 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT))) | |
15172 && opt.jo_io[part] == JIO_FILE | |
15173 && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT))) | |
15174 || *opt.jo_io_name[part] == NUL)) | |
15175 { | |
15176 EMSG(_("E920: -io file requires -name to be set")); | |
15177 return; | |
15178 } | |
15179 | |
15180 if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER) | |
15181 { | |
15182 buf_T *buf = NULL; | |
15183 | |
15184 /* check that we can find the buffer before starting the job */ | |
15185 if (opt.jo_set & JO_IN_BUF) | |
15186 { | |
15187 buf = buflist_findnr(opt.jo_io_buf[PART_IN]); | |
15188 if (buf == NULL) | |
15189 EMSGN(_(e_nobufnr), (long)opt.jo_io_buf[PART_IN]); | |
15190 } | |
15191 else if (!(opt.jo_set & JO_IN_NAME)) | |
15192 { | |
15193 EMSG(_("E915: in-io buffer requires in-buf or in-name to be set")); | |
15194 } | |
15195 else | |
15196 buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE); | |
15197 if (buf == NULL) | |
15198 return; | |
15199 if (buf->b_ml.ml_mfp == NULL) | |
15200 { | |
15201 char_u numbuf[NUMBUFLEN]; | |
15202 char_u *s; | |
15203 | |
15204 if (opt.jo_set & JO_IN_BUF) | |
15205 { | |
15206 sprintf((char *)numbuf, "%d", opt.jo_io_buf[PART_IN]); | |
15207 s = numbuf; | |
15208 } | |
15209 else | |
15210 s = opt.jo_io_name[PART_IN]; | |
15211 EMSG2(_("E918: buffer must be loaded: %s"), s); | |
15212 return; | |
15213 } | |
15214 job->jv_in_buf = buf; | |
15215 } | |
15216 | |
15217 job_set_options(job, &opt); | |
15218 | |
15219 #ifndef USE_ARGV | |
15220 ga_init2(&ga, (int)sizeof(char*), 20); | |
15221 #endif | |
15222 | |
15223 if (argvars[0].v_type == VAR_STRING) | |
15224 { | |
15225 /* Command is a string. */ | |
15226 cmd = argvars[0].vval.v_string; | |
15227 #ifdef USE_ARGV | |
15228 if (mch_parse_cmd(cmd, FALSE, &argv, &argc) == FAIL) | |
15229 return; | |
15230 argv[argc] = NULL; | |
15231 #endif | |
15232 } | |
15233 else if (argvars[0].v_type != VAR_LIST | |
15234 || argvars[0].vval.v_list == NULL | |
15235 || argvars[0].vval.v_list->lv_len < 1) | |
15236 { | |
15237 EMSG(_(e_invarg)); | |
15238 return; | |
15239 } | |
15240 else | |
15241 { | |
15242 list_T *l = argvars[0].vval.v_list; | |
15243 listitem_T *li; | |
15244 char_u *s; | |
15245 | |
15246 #ifdef USE_ARGV | |
15247 /* Pass argv[] to mch_call_shell(). */ | |
15248 argv = (char **)alloc(sizeof(char *) * (l->lv_len + 1)); | |
15249 if (argv == NULL) | |
15250 return; | |
15251 #endif | |
15252 for (li = l->lv_first; li != NULL; li = li->li_next) | |
15253 { | |
15254 s = get_tv_string_chk(&li->li_tv); | |
15255 if (s == NULL) | |
15256 goto theend; | |
15257 #ifdef USE_ARGV | |
15258 argv[argc++] = (char *)s; | |
15259 #else | |
15260 /* Only escape when needed, double quotes are not always allowed. */ | |
15261 if (li != l->lv_first && vim_strpbrk(s, (char_u *)" \t\"") != NULL) | |
15262 { | |
15263 s = vim_strsave_shellescape(s, FALSE, TRUE); | |
15264 if (s == NULL) | |
15265 goto theend; | |
15266 ga_concat(&ga, s); | |
15267 vim_free(s); | |
15268 } | |
15269 else | |
15270 ga_concat(&ga, s); | |
15271 if (li->li_next != NULL) | |
15272 ga_append(&ga, ' '); | |
15273 #endif | |
15274 } | |
15275 #ifdef USE_ARGV | |
15276 argv[argc] = NULL; | |
15277 #else | |
15278 cmd = ga.ga_data; | |
15279 #endif | |
15280 } | |
15281 | |
15282 #ifdef USE_ARGV | |
15283 if (ch_log_active()) | |
15284 { | |
15285 garray_T ga; | |
15286 int i; | |
15287 | |
15288 ga_init2(&ga, (int)sizeof(char), 200); | |
15289 for (i = 0; i < argc; ++i) | |
15290 { | |
15291 if (i > 0) | |
15292 ga_concat(&ga, (char_u *)" "); | |
15293 ga_concat(&ga, (char_u *)argv[i]); | |
15294 } | |
15295 ch_logs(NULL, "Starting job: %s", (char *)ga.ga_data); | |
15296 ga_clear(&ga); | |
15297 } | |
15298 mch_start_job(argv, job, &opt); | |
15299 #else | |
15300 ch_logs(NULL, "Starting job: %s", (char *)cmd); | |
15301 mch_start_job((char *)cmd, job, &opt); | |
15302 #endif | |
15303 | |
15304 /* If the channel is reading from a buffer, write lines now. */ | |
15305 if (job->jv_channel != NULL) | |
15306 channel_write_in(job->jv_channel); | |
15307 | |
15308 theend: | |
15309 #ifdef USE_ARGV | |
15310 vim_free(argv); | |
15311 #else | |
15312 vim_free(ga.ga_data); | |
15313 #endif | |
15314 } | |
15315 | |
15316 /* | |
15317 * Get the status of "job" and invoke the exit callback when needed. | |
15318 * The returned string is not allocated. | |
15319 */ | |
15320 static char * | |
15321 job_status(job_T *job) | |
15322 { | |
15323 char *result; | |
15324 | |
15325 if (job->jv_status == JOB_ENDED) | |
15326 /* No need to check, dead is dead. */ | |
15327 result = "dead"; | |
15328 else if (job->jv_status == JOB_FAILED) | |
15329 result = "fail"; | |
15330 else | |
15331 { | |
15332 result = mch_job_status(job); | |
15333 if (job->jv_status == JOB_ENDED) | |
15334 ch_log(job->jv_channel, "Job ended"); | |
15335 if (job->jv_status == JOB_ENDED && job->jv_exit_cb != NULL) | |
15336 { | |
15337 typval_T argv[3]; | |
15338 typval_T rettv; | |
15339 int dummy; | |
15340 | |
15341 /* invoke the exit callback; make sure the refcount is > 0 */ | |
15342 ++job->jv_refcount; | |
15343 argv[0].v_type = VAR_JOB; | |
15344 argv[0].vval.v_job = job; | |
15345 argv[1].v_type = VAR_NUMBER; | |
15346 argv[1].vval.v_number = job->jv_exitval; | |
15347 call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb), | |
15348 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL); | |
15349 clear_tv(&rettv); | |
15350 --job->jv_refcount; | |
15351 } | |
15352 if (job->jv_status == JOB_ENDED && job->jv_refcount == 0) | |
15353 { | |
15354 /* The job was already unreferenced, now that it ended it can be | |
15355 * freed. Careful: caller must not use "job" after this! */ | |
15356 job_free(job); | |
15357 } | |
15358 } | |
15359 return result; | |
15360 } | |
15361 | |
15362 /* | |
15363 * Called once in a while: check if any jobs with an "exit-cb" have ended. | |
15364 */ | |
15365 void | |
15366 job_check_ended(void) | |
15367 { | |
15368 static time_t last_check = 0; | |
15369 time_t now; | |
15370 job_T *job; | |
15371 job_T *next; | |
15372 | |
15373 /* Only do this once in 10 seconds. */ | |
15374 now = time(NULL); | |
15375 if (last_check + 10 < now) | |
15376 { | |
15377 last_check = now; | |
15378 for (job = first_job; job != NULL; job = next) | |
15379 { | |
15380 next = job->jv_next; | |
15381 if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL) | |
15382 job_status(job); /* may free "job" */ | |
15383 } | |
15384 } | |
15385 } | 14369 } |
15386 | 14370 |
15387 /* | 14371 /* |
15388 * "job_status()" function | 14372 * "job_status()" function |
15389 */ | 14373 */ |
15403 | 14387 |
15404 /* | 14388 /* |
15405 * "job_stop()" function | 14389 * "job_stop()" function |
15406 */ | 14390 */ |
15407 static void | 14391 static void |
15408 f_job_stop(typval_T *argvars UNUSED, typval_T *rettv UNUSED) | 14392 f_job_stop(typval_T *argvars, typval_T *rettv) |
15409 { | 14393 { |
15410 job_T *job = get_job_arg(&argvars[0]); | 14394 job_T *job = get_job_arg(&argvars[0]); |
15411 | 14395 |
15412 if (job != NULL) | 14396 if (job != NULL) |
15413 { | 14397 rettv->vval.v_number = job_stop(job, argvars); |
15414 char_u *arg; | |
15415 | |
15416 if (argvars[1].v_type == VAR_UNKNOWN) | |
15417 arg = (char_u *)""; | |
15418 else | |
15419 { | |
15420 arg = get_tv_string_chk(&argvars[1]); | |
15421 if (arg == NULL) | |
15422 { | |
15423 EMSG(_(e_invarg)); | |
15424 return; | |
15425 } | |
15426 } | |
15427 ch_logs(job->jv_channel, "Stopping job with '%s'", (char *)arg); | |
15428 if (mch_stop_job(job, arg) == FAIL) | |
15429 rettv->vval.v_number = 0; | |
15430 else | |
15431 { | |
15432 rettv->vval.v_number = 1; | |
15433 /* Assume that "hup" does not kill the job. */ | |
15434 if (job->jv_channel != NULL && STRCMP(arg, "hup") != 0) | |
15435 job->jv_channel->ch_job_killed = TRUE; | |
15436 } | |
15437 /* We don't try freeing the job, obviously the caller still has a | |
15438 * reference to it. */ | |
15439 } | |
15440 } | 14398 } |
15441 #endif | 14399 #endif |
15442 | 14400 |
15443 /* | 14401 /* |
15444 * "join()" function | 14402 * "join()" function |
22473 * For incompatible types, return 0. | 21431 * For incompatible types, return 0. |
22474 * get_tv_number_chk() is similar to get_tv_number(), but informs the | 21432 * get_tv_number_chk() is similar to get_tv_number(), but informs the |
22475 * caller of incompatible types: it sets *denote to TRUE if "denote" | 21433 * caller of incompatible types: it sets *denote to TRUE if "denote" |
22476 * is not NULL or returns -1 otherwise. | 21434 * is not NULL or returns -1 otherwise. |
22477 */ | 21435 */ |
22478 static long | 21436 long |
22479 get_tv_number(typval_T *varp) | 21437 get_tv_number(typval_T *varp) |
22480 { | 21438 { |
22481 int error = FALSE; | 21439 int error = FALSE; |
22482 | 21440 |
22483 return get_tv_number_chk(varp, &error); /* return 0L on error */ | 21441 return get_tv_number_chk(varp, &error); /* return 0L on error */ |
22624 * If the String variable has never been set, return an empty string. | 21582 * If the String variable has never been set, return an empty string. |
22625 * Never returns NULL; | 21583 * Never returns NULL; |
22626 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return | 21584 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return |
22627 * NULL on error. | 21585 * NULL on error. |
22628 */ | 21586 */ |
22629 static char_u * | 21587 char_u * |
22630 get_tv_string(typval_T *varp) | 21588 get_tv_string(typval_T *varp) |
22631 { | 21589 { |
22632 static char_u mybuf[NUMBUFLEN]; | 21590 static char_u mybuf[NUMBUFLEN]; |
22633 | 21591 |
22634 return get_tv_string_buf(varp, mybuf); | 21592 return get_tv_string_buf(varp, mybuf); |
22635 } | 21593 } |
22636 | 21594 |
22637 static char_u * | 21595 char_u * |
22638 get_tv_string_buf(typval_T *varp, char_u *buf) | 21596 get_tv_string_buf(typval_T *varp, char_u *buf) |
22639 { | 21597 { |
22640 char_u *res = get_tv_string_buf_chk(varp, buf); | 21598 char_u *res = get_tv_string_buf_chk(varp, buf); |
22641 | 21599 |
22642 return res != NULL ? res : (char_u *)""; | 21600 return res != NULL ? res : (char_u *)""; |