diff options
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r-- | src/evalfunc.c | 245 |
1 files changed, 186 insertions, 59 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 9720691..173b544 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -28,6 +28,7 @@ static void f_balloon_show(typval_T *argvars, typval_T *rettv); static void f_balloon_split(typval_T *argvars, typval_T *rettv); # endif #endif +static void f_bindtextdomain(typval_T *argvars, typval_T *rettv); static void f_byte2line(typval_T *argvars, typval_T *rettv); static void f_call(typval_T *argvars, typval_T *rettv); static void f_changenr(typval_T *argvars, typval_T *rettv); @@ -81,6 +82,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv); static void f_hlID(typval_T *argvars, typval_T *rettv); static void f_hlexists(typval_T *argvars, typval_T *rettv); static void f_hostname(typval_T *argvars, typval_T *rettv); +static void f_id(typval_T *argvars, typval_T *rettv); static void f_index(typval_T *argvars, typval_T *rettv); static void f_indexof(typval_T *argvars, typval_T *rettv); static void f_input(typval_T *argvars, typval_T *rettv); @@ -1133,6 +1135,7 @@ static argcheck_T arg2_number_bool[] = {arg_number, arg_bool}; static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any}; static argcheck_T arg2_number_list[] = {arg_number, arg_list_any}; static argcheck_T arg2_number_string[] = {arg_number, arg_string}; +static argcheck_T arg2_number_buffer[] = {arg_number, arg_buffer}; static argcheck_T arg2_number_string_or_list[] = {arg_number, arg_string_or_list_any}; static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; static argcheck_T arg2_string[] = {arg_string, arg_string}; @@ -1323,7 +1326,6 @@ ret_list_items(int argcount UNUSED, *decl_type = &t_list_any; return &t_list_list_any; } - static type_T * ret_list_string_items(int argcount UNUSED, type2_T *argtypes UNUSED, @@ -1333,6 +1335,14 @@ ret_list_string_items(int argcount UNUSED, return &t_list_list_string; } static type_T * +ret_list_regionpos(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type) +{ + *decl_type = &t_list_any; + return &t_list_list_list_number; +} + static type_T * ret_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED, type_T **decl_type UNUSED) @@ -1823,6 +1833,8 @@ static funcentry_T global_functions[] = NULL #endif }, + {"bindtextdomain", 2, 2, 0, arg2_string, + ret_bool, f_bindtextdomain}, {"blob2list", 1, 1, FEARG_1, arg1_blob, ret_list_number, f_blob2list}, {"browse", 4, 4, 0, arg4_browse, @@ -1963,11 +1975,11 @@ static funcentry_T global_functions[] = ret_number, f_diff_hlID}, {"digraph_get", 1, 1, FEARG_1, arg1_string, ret_string, f_digraph_get}, - {"digraph_getlist",0, 1, FEARG_1, arg1_bool, + {"digraph_getlist", 0, 1, FEARG_1, arg1_bool, ret_list_string_items, f_digraph_getlist}, {"digraph_set", 2, 2, FEARG_1, arg2_string, ret_bool, f_digraph_set}, - {"digraph_setlist",1, 1, FEARG_1, arg1_list_string, + {"digraph_setlist", 1, 1, FEARG_1, arg1_list_string, ret_bool, f_digraph_setlist}, {"echoraw", 1, 1, FEARG_1, arg1_string, ret_void, f_echoraw}, @@ -2139,8 +2151,8 @@ static funcentry_T global_functions[] = ret_dict_any, f_getreginfo}, {"getregion", 2, 3, FEARG_1, arg3_list_list_dict, ret_list_string, f_getregion}, - {"getregionpos", 2, 3, FEARG_1, arg3_list_list_dict, - ret_list_string, f_getregionpos}, + {"getregionpos", 2, 3, FEARG_1, arg3_list_list_dict, + ret_list_regionpos, f_getregionpos}, {"getregtype", 0, 1, FEARG_1, arg1_string, ret_string, f_getregtype}, {"getscriptinfo", 0, 1, 0, arg1_dict_any, @@ -2153,7 +2165,7 @@ static funcentry_T global_functions[] = ret_any, f_gettabwinvar}, {"gettagstack", 0, 1, FEARG_1, arg1_number, ret_dict_any, f_gettagstack}, - {"gettext", 1, 1, FEARG_1, arg1_string, + {"gettext", 1, 2, FEARG_1, arg2_string, ret_string, f_gettext}, {"getwininfo", 0, 1, FEARG_1, arg1_number, ret_list_dict_any, f_getwininfo}, @@ -2203,6 +2215,8 @@ static funcentry_T global_functions[] = ret_string, f_hostname}, {"iconv", 3, 3, FEARG_1, arg3_string, ret_string, f_iconv}, + {"id", 1, 1, FEARG_1, NULL, + ret_string, f_id}, {"indent", 1, 1, FEARG_1, arg1_lnum, ret_number, f_indent}, {"index", 2, 4, FEARG_1, arg24_index, @@ -2421,6 +2435,8 @@ static funcentry_T global_functions[] = ret_void, PROP_FUNC(f_popup_move)}, {"popup_notification", 2, 2, FEARG_1, arg2_str_or_nr_or_list_dict, ret_number, PROP_FUNC(f_popup_notification)}, + {"popup_setbuf", 2, 2, FEARG_1, arg2_number_buffer, + ret_number_bool, PROP_FUNC(f_popup_setbuf)}, {"popup_setoptions", 2, 2, FEARG_1, arg2_number_dict_any, ret_void, PROP_FUNC(f_popup_setoptions)}, {"popup_settext", 2, 2, FEARG_1, arg2_number_string_or_list, @@ -3118,8 +3134,8 @@ internal_func_check_arg_types( // functions, check the arguments are not types. if (!(func_allows_type(idx))) { - for (int i = 0; i < argcount; ++i) - if (check_type_is_value(types[i].type_curr) == FAIL) + for (int i = 0; i < argcount; ++i) + if (check_type_is_value(types[i].type_curr) == FAIL) return FAIL; } @@ -3474,6 +3490,33 @@ get_buf_arg(typval_T *arg) } /* + * "bindtextdomain(package, path)" function + */ + static void +f_bindtextdomain(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_BOOL; + rettv->vval.v_number = VVAL_TRUE; + + if (check_for_nonempty_string_arg(argvars, 0) == FAIL + || check_for_nonempty_string_arg(argvars, 1) == FAIL) + return; + + if (strcmp((const char *)argvars[0].vval.v_string, VIMPACKAGE) == 0) + semsg(_(e_invalid_argument_str), tv_get_string(&argvars[0])); + else + { + if (bindtextdomain((const char *)argvars[0].vval.v_string, (const char *)argvars[1].vval.v_string) == NULL) + { + do_outofmem_msg((long)0); + rettv->vval.v_number = VVAL_FALSE; + } + } + + return; +} + +/* * "byte2line(byte)" function */ static void @@ -5110,6 +5153,36 @@ f_get(typval_T *argvars, typval_T *rettv) list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); } } + else if (STRCMP(what, "arity") == 0) + { + int required = 0, optional = 0, varargs = FALSE; + char_u *name = partial_name(pt); + + get_func_arity(name, &required, &optional, &varargs); + + rettv->v_type = VAR_DICT; + if (rettv_dict_alloc(rettv) == OK) + { + dict_T *dict = rettv->vval.v_dict; + + // Take into account the arguments of the partial, if any. + // Note that it is possible to supply more arguments than the function + // accepts. + if (pt->pt_argc >= required + optional) + required = optional = 0; + else if (pt->pt_argc > required) + { + optional -= pt->pt_argc - required; + required = 0; + } + else + required -= pt->pt_argc; + + dict_add_number(dict, "required", required); + dict_add_number(dict, "optional", optional); + dict_add_bool(dict, "varargs", varargs); + } + } else semsg(_(e_invalid_argument_str), what); @@ -6030,11 +6103,39 @@ f_gettagstack(typval_T *argvars, typval_T *rettv) static void f_gettext(typval_T *argvars, typval_T *rettv) { - if (check_for_nonempty_string_arg(argvars, 0) == FAIL) +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + char *prev = NULL; +#endif + + if (check_for_nonempty_string_arg(argvars, 0) == FAIL + || check_for_opt_string_arg(argvars, 1) == FAIL) return; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); + + if (argvars[1].v_type == VAR_STRING && + argvars[1].vval.v_string != NULL && + *(argvars[1].vval.v_string) != NUL) + { +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + prev = bind_textdomain_codeset((const char *)argvars[1].vval.v_string, (char *)p_enc); +#endif + +#if defined(HAVE_DGETTEXT) + rettv->vval.v_string = vim_strsave((char_u *)dgettext((const char *)argvars[1].vval.v_string, (const char *)argvars[0].vval.v_string)); +#else + textdomain((const char *)argvars[1].vval.v_string); + rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); + textdomain(VIMPACKAGE); +#endif + +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + if (prev != NULL) + bind_textdomain_codeset((const char *)argvars[1].vval.v_string, prev); +#endif + } + else + rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); } // for VIM_VERSION_ defines @@ -7435,6 +7536,54 @@ f_hostname(typval_T *argvars UNUSED, typval_T *rettv) } /* + * "id()" function + * Identity. Return address of item as a hex string, %p format. + * Currently only valid for object/container types. + * Return empty string if not an object. + */ +#ifdef VMS // VMS does not have defined uintptr_t +# if defined(HAVE_NO_LONG_LONG) +typedef unsigned int uintptr_t; +# else +typedef unsigned long long uintptr_t; +# endif +#endif // VMS + + static void +f_id(typval_T *argvars, typval_T *rettv) +{ + char numbuf[NUMBUFLEN]; + char *p = numbuf; + + switch (argvars[0].v_type) + { + case VAR_LIST: + case VAR_DICT: + case VAR_OBJECT: + case VAR_JOB: + case VAR_CHANNEL: + case VAR_BLOB: + // Assume pointer value in typval_T vval union at common location. + if (argvars[0].vval.v_object != NULL) + { + // "v" gets the address as an integer + uintptr_t v = (uintptr_t)(void *)argvars[0].vval.v_object; + // Build a hex string from the item's address; it is in + // reverse order. Ignore trailing zeros. + for (; p < numbuf + sizeof(uintptr_t) * 2 && v != 0; + ++p, v >>= 4) + *p = "0123456789abcdef"[v & 0xf]; + } + default: + break; + } + *p = NUL; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strsave((char_u *)numbuf); +} + +/* * "index()" function */ static void @@ -7483,7 +7632,7 @@ f_index(typval_T *argvars, typval_T *rettv) { tv.v_type = VAR_NUMBER; tv.vval.v_number = blob_get(b, idx); - if (tv_equal(&tv, &argvars[1], ic, FALSE)) + if (tv_equal(&tv, &argvars[1], ic)) { rettv->vval.v_number = idx; return; @@ -7516,7 +7665,7 @@ f_index(typval_T *argvars, typval_T *rettv) } for ( ; item != NULL; item = item->li_next, ++idx) - if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE)) + if (tv_equal(&item->li_tv, &argvars[1], ic)) { rettv->vval.v_number = idx; break; @@ -9215,69 +9364,47 @@ f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED) static void init_srand(UINT32_T *x) { -#ifndef MSWIN - static int dev_urandom_state = NOTDONE; // FAIL or OK once tried -#endif + struct { + union { + UINT32_T number; + char_u bytes[sizeof(UINT32_T)]; + } contents; + } buf; if (srand_seed_for_testing_is_used) { *x = srand_seed_for_testing; return; } -#ifndef MSWIN - if (dev_urandom_state != FAIL) - { - int fd = open("/dev/urandom", O_RDONLY); - struct { - union { - UINT32_T number; - char bytes[sizeof(UINT32_T)]; - } contents; - } buf; - // Attempt reading /dev/urandom. - if (fd == -1) - dev_urandom_state = FAIL; - else - { - buf.contents.number = 0; - if (read(fd, buf.contents.bytes, sizeof(UINT32_T)) - != sizeof(UINT32_T)) - dev_urandom_state = FAIL; - else - { - dev_urandom_state = OK; - *x = buf.contents.number; - } - close(fd); - } - } - if (dev_urandom_state != OK) -#endif + if (mch_get_random(buf.contents.bytes, sizeof(buf.contents.bytes)) == OK) { - // Reading /dev/urandom doesn't work, fall back to: - // - randombytes_random() - // - reltime() or time() - // - XOR with process ID + *x = buf.contents.number; + return; + } + + // The system's random number generator doesn't work, fall back to: + // - randombytes_random() + // - reltime() or time() + // - XOR with process ID #if defined(FEAT_SODIUM) - if (crypt_sodium_init() >= 0) - *x = crypt_sodium_randombytes_random(); - else + if (crypt_sodium_init() >= 0) + *x = crypt_sodium_randombytes_random(); + else #endif - { + { #if defined(FEAT_RELTIME) - proftime_T res; - profile_start(&res); + proftime_T res; + profile_start(&res); # if defined(MSWIN) - *x = (UINT32_T)res.LowPart; + *x = (UINT32_T)res.LowPart; # else - *x = (UINT32_T)res.tv_fsec; + *x = (UINT32_T)res.tv_fsec; # endif #else - *x = vim_time(); + *x = vim_time(); #endif - *x ^= mch_get_pid(); - } + *x ^= mch_get_pid(); } } |