mirror of
https://github.com/neovim/neovim.git
synced 2025-10-01 07:28:34 +00:00
eval: Add id() function and make printf("%p") return something useful (#6095)
This commit is contained in:

committed by
Justin M. Keyes

parent
b1cf50c684
commit
abdbfd26bc
@@ -498,6 +498,14 @@ static PMap(uint64_t) *jobs = NULL;
|
||||
static uint64_t last_timer_id = 0;
|
||||
static PMap(uint64_t) *timers = NULL;
|
||||
|
||||
/// Dummy va_list for passing to vim_snprintf
|
||||
///
|
||||
/// Used because:
|
||||
/// - passing a NULL pointer doesn't work when va_list isn't a pointer
|
||||
/// - locally in the function results in a "used before set" warning
|
||||
/// - using va_start() to initialize it gives "function with fixed args" error
|
||||
static va_list dummy_ap;
|
||||
|
||||
static const char *const msgpack_type_names[] = {
|
||||
[kMPNil] = "nil",
|
||||
[kMPBoolean] = "boolean",
|
||||
@@ -12122,6 +12130,16 @@ static void dict_list(typval_T *argvars, typval_T *rettv, int what)
|
||||
}
|
||||
}
|
||||
|
||||
/// "id()" function
|
||||
static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const int len = vim_vsnprintf(NULL, 0, "%p", dummy_ap, argvars);
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = xmalloc(len + 1);
|
||||
vim_vsnprintf((char *)rettv->vval.v_string, len + 1, "%p", dummy_ap, argvars);
|
||||
}
|
||||
|
||||
/*
|
||||
* "items(dict)" function
|
||||
*/
|
||||
@@ -13628,12 +13646,6 @@ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
rettv->vval.v_number = lnum;
|
||||
}
|
||||
|
||||
/* This dummy va_list is here because:
|
||||
* - passing a NULL pointer doesn't work when va_list isn't a pointer
|
||||
* - locally in the function results in a "used before set" warning
|
||||
* - using va_start() to initialize it gives "function with fixed args" error */
|
||||
static va_list ap;
|
||||
|
||||
/*
|
||||
* "printf()" function
|
||||
*/
|
||||
@@ -13650,11 +13662,11 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
/* Get the required length, allocate the buffer and do it for real. */
|
||||
did_emsg = FALSE;
|
||||
fmt = (char *)get_tv_string_buf(&argvars[0], buf);
|
||||
len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
|
||||
len = vim_vsnprintf(NULL, 0, fmt, dummy_ap, argvars + 1);
|
||||
if (!did_emsg) {
|
||||
char *s = xmalloc(len + 1);
|
||||
rettv->vval.v_string = (char_u *)s;
|
||||
(void)vim_vsnprintf(s, len + 1, fmt, ap, argvars + 1);
|
||||
(void)vim_vsnprintf(s, len + 1, fmt, dummy_ap, argvars + 1);
|
||||
}
|
||||
did_emsg |= saved_did_emsg;
|
||||
}
|
||||
|
@@ -168,6 +168,7 @@ return {
|
||||
invert={args=1},
|
||||
isdirectory={args=1},
|
||||
islocked={args=1},
|
||||
id={args=1},
|
||||
items={args=1},
|
||||
jobclose={args={1, 2}},
|
||||
jobpid={args=1},
|
||||
|
@@ -49,7 +49,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union {
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/assert.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/eval.h"
|
||||
@@ -3043,6 +3044,38 @@ static char *tv_str(typval_T *tvs, int *idxp)
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Get pointer argument from the next entry in tvs
|
||||
///
|
||||
/// First entry is 1. Returns NULL for an error.
|
||||
///
|
||||
/// @param[in] tvs List of typval_T values.
|
||||
/// @param[in,out] idxp Pointer to the index of the current value.
|
||||
///
|
||||
/// @return Pointer stored in typval_T or NULL.
|
||||
static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
#define OFF(attr) offsetof(union typval_vval_union, attr)
|
||||
STATIC_ASSERT(
|
||||
OFF(v_string) == OFF(v_list)
|
||||
&& OFF(v_string) == OFF(v_dict)
|
||||
&& OFF(v_string) == OFF(v_partial)
|
||||
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
|
||||
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
|
||||
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
|
||||
"Strings, dictionaries, lists and partials are expected to be pointers, "
|
||||
"so that all three of them can be accessed via v_string");
|
||||
#undef OFF
|
||||
const int idx = *idxp - 1;
|
||||
if (tvs[idx].v_type == VAR_UNKNOWN) {
|
||||
EMSG(_(e_printf));
|
||||
return NULL;
|
||||
} else {
|
||||
(*idxp)++;
|
||||
return tvs[idx].vval.v_string;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get float argument from "idxp" entry in "tvs". First entry is 1.
|
||||
*/
|
||||
@@ -3369,11 +3402,11 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
|
||||
size_t size_t_arg = 0;
|
||||
|
||||
// only defined for p conversion
|
||||
void *ptr_arg = NULL;
|
||||
const void *ptr_arg = NULL;
|
||||
|
||||
if (fmt_spec == 'p') {
|
||||
length_modifier = '\0';
|
||||
ptr_arg = tvs ? (void *)tv_str(tvs, &arg_idx) : va_arg(ap, void *);
|
||||
ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
|
||||
if (ptr_arg) {
|
||||
arg_sign = 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user