1 #ifndef NVIM_EVAL_TYPVAL_H
2 #define NVIM_EVAL_TYPVAL_H
3 
4 #include <assert.h>
5 #include <inttypes.h>
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <string.h>
9 
10 #include "nvim/func_attr.h"
11 #include "nvim/garray.h"
12 #include "nvim/gettext.h"
13 #include "nvim/hashtab.h"
14 #include "nvim/lib/queue.h"
15 #include "nvim/macros.h"
16 #include "nvim/mbyte.h"
17 #include "nvim/message.h"
18 #include "nvim/pos.h"      // for linenr_T
19 #include "nvim/profile.h"  // for proftime_T
20 #include "nvim/types.h"
21 #ifdef LOG_LIST_ACTIONS
22 # include "nvim/memory.h"
23 #endif
24 
25 /// Type used for VimL VAR_NUMBER values
26 typedef int64_t varnumber_T;
27 typedef uint64_t uvarnumber_T;
28 
29 /// Type used for VimL VAR_FLOAT values
30 typedef double float_T;
31 
32 /// Refcount for dict or list that should not be freed
33 enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };
34 
35 /// Additional values for tv_list_alloc() len argument
36 enum ListLenSpecials {
37   /// List length is not known in advance
38   ///
39   /// To be used when there is neither a way to know how many elements will be
40   /// needed nor are any educated guesses.
41   kListLenUnknown = -1,
42   /// List length *should* be known, but is actually not
43   ///
44   /// All occurrences of this value should be eventually removed. This is for
45   /// the case when the only reason why list length is not known is that it
46   /// would be hard to code without refactoring, but refactoring is needed.
47   kListLenShouldKnow = -2,
48   /// List length may be known in advance, but it requires too much effort
49   ///
50   /// To be used when it looks impractical to determine list length.
51   kListLenMayKnow = -3,
52 };
53 
54 /// Maximal possible value of varnumber_T variable
55 #define VARNUMBER_MAX INT64_MAX
56 #define UVARNUMBER_MAX UINT64_MAX
57 
58 /// Minimal possible value of varnumber_T variable
59 #define VARNUMBER_MIN INT64_MIN
60 
61 /// %d printf format specifier for varnumber_T
62 #define PRIdVARNUMBER PRId64
63 
64 typedef struct listvar_S list_T;
65 typedef struct dictvar_S dict_T;
66 typedef struct partial_S partial_T;
67 typedef struct blobvar_S blob_T;
68 
69 typedef struct ufunc ufunc_T;
70 
71 typedef enum {
72   kCallbackNone = 0,
73   kCallbackFuncref,
74   kCallbackPartial,
75 } CallbackType;
76 
77 typedef struct {
78   union {
79     char_u *funcref;
80     partial_T *partial;
81   } data;
82   CallbackType type;
83 } Callback;
84 #define CALLBACK_NONE ((Callback){ .type = kCallbackNone })
85 
86 /// Structure holding dictionary watcher
87 typedef struct dict_watcher {
88   Callback callback;
89   char *key_pattern;
90   size_t key_pattern_len;
91   QUEUE node;
92   bool busy;  // prevent recursion if the dict is changed in the callback
93   bool needs_free;
94 } DictWatcher;
95 
96 /// Bool variable values
97 typedef enum {
98   kBoolVarFalse,         ///< v:false
99   kBoolVarTrue,          ///< v:true
100 } BoolVarValue;
101 
102 /// Special variable values
103 typedef enum {
104   kSpecialVarNull,   ///< v:null
105 } SpecialVarValue;
106 
107 /// Variable lock status for typval_T.v_lock
108 typedef enum {
109   VAR_UNLOCKED = 0,  ///< Not locked.
110   VAR_LOCKED = 1,    ///< User lock, can be unlocked.
111   VAR_FIXED = 2,     ///< Locked forever.
112 } VarLockStatus;
113 
114 /// VimL variable types, for use in typval_T.v_type
115 typedef enum {
116   VAR_UNKNOWN = 0,  ///< Unknown (unspecified) value.
117   VAR_NUMBER,       ///< Number, .v_number is used.
118   VAR_STRING,       ///< String, .v_string is used.
119   VAR_FUNC,         ///< Function reference, .v_string is used as function name.
120   VAR_LIST,         ///< List, .v_list is used.
121   VAR_DICT,         ///< Dictionary, .v_dict is used.
122   VAR_FLOAT,        ///< Floating-point value, .v_float is used.
123   VAR_BOOL,         ///< true, false
124   VAR_SPECIAL,      ///< Special value (null), .v_special
125                     ///< is used.
126   VAR_PARTIAL,      ///< Partial, .v_partial is used.
127   VAR_BLOB,         ///< Blob, .v_blob is used.
128 } VarType;
129 
130 /// Structure that holds an internal variable value
131 typedef struct {
132   VarType v_type;  ///< Variable type.
133   VarLockStatus v_lock;  ///< Variable lock status.
134   union typval_vval_union {
135     varnumber_T v_number;  ///< Number, for VAR_NUMBER.
136     BoolVarValue v_bool;        ///< Bool value, for VAR_BOOL
137     SpecialVarValue v_special;  ///< Special value, for VAR_SPECIAL.
138     float_T v_float;  ///< Floating-point number, for VAR_FLOAT.
139     char_u *v_string;  ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
140     list_T *v_list;  ///< List for VAR_LIST, can be NULL.
141     dict_T *v_dict;  ///< Dictionary for VAR_DICT, can be NULL.
142     partial_T *v_partial;  ///< Closure: function with args.
143     blob_T *v_blob;  ///< Blob for VAR_BLOB, can be NULL.
144   } vval;  ///< Actual value.
145 } typval_T;
146 
147 /// Values for (struct dictvar_S).dv_scope
148 typedef enum {
149   VAR_NO_SCOPE = 0,  ///< Not a scope dictionary.
150   VAR_SCOPE = 1,  ///< Scope dictionary which requires prefix (a:, v:, …).
151   VAR_DEF_SCOPE = 2,  ///< Scope dictionary which may be accessed without prefix
152                       ///< (l:, g:).
153 } ScopeType;
154 
155 /// Structure to hold an item of a list
156 typedef struct listitem_S listitem_T;
157 
158 struct listitem_S {
159   listitem_T *li_next;  ///< Next item in list.
160   listitem_T *li_prev;  ///< Previous item in list.
161   typval_T li_tv;  ///< Item value.
162 };
163 
164 /// Structure used by those that are using an item in a list
165 typedef struct listwatch_S listwatch_T;
166 
167 struct listwatch_S {
168   listitem_T *lw_item;  ///< Item being watched.
169   listwatch_T *lw_next;  ///< Next watcher.
170 };
171 
172 /// Structure to hold info about a list
173 /// Order of members is optimized to reduce padding.
174 struct listvar_S {
175   listitem_T *lv_first;  ///< First item, NULL if none.
176   listitem_T *lv_last;  ///< Last item, NULL if none.
177   listwatch_T *lv_watch;  ///< First watcher, NULL if none.
178   listitem_T *lv_idx_item;  ///< When not NULL item at index "lv_idx".
179   list_T *lv_copylist;  ///< Copied list used by deepcopy().
180   list_T *lv_used_next;  ///< next list in used lists list.
181   list_T *lv_used_prev;  ///< Previous list in used lists list.
182   int lv_refcount;  ///< Reference count.
183   int lv_len;  ///< Number of items.
184   int lv_idx;  ///< Index of a cached item, used for optimising repeated l[idx].
185   int lv_copyID;  ///< ID used by deepcopy().
186   VarLockStatus lv_lock;  ///< Zero, VAR_LOCKED, VAR_FIXED.
187 
188   LuaRef lua_table_ref;
189 };
190 
191 // Static list with 10 items. Use tv_list_init_static10() to initialize.
192 typedef struct {
193   list_T sl_list;  // must be first
194   listitem_T sl_items[10];
195 } staticList10_T;
196 
197 #define TV_LIST_STATIC10_INIT { \
198   .sl_list = { \
199   .lv_first = NULL, \
200   .lv_last = NULL, \
201   .lv_refcount = 0, \
202   .lv_len = 0, \
203   .lv_watch = NULL, \
204   .lv_idx_item = NULL, \
205   .lv_lock = VAR_FIXED, \
206   .lv_used_next = NULL, \
207   .lv_used_prev = NULL, \
208   }, \
209 }
210 
211 #define TV_DICTITEM_STRUCT(...) \
212   struct { \
213     typval_T di_tv;  /* Structure that holds scope dictionary itself. */ \
214     uint8_t di_flags;  /* Flags. */ \
215     char_u di_key[__VA_ARGS__];  /* Key value. */ \
216   }
217 
218 /// Structure to hold a scope dictionary
219 ///
220 /// @warning Must be compatible with dictitem_T.
221 ///
222 /// For use in find_var_in_ht to pretend that it found dictionary item when it
223 /// finds scope dictionary.
224 typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
225 
226 /// Structure to hold an item of a Dictionary
227 ///
228 /// @warning Must be compatible with ScopeDictDictItem.
229 ///
230 /// Also used for a variable.
231 typedef TV_DICTITEM_STRUCT() dictitem_T;
232 
233 /// Flags for dictitem_T.di_flags
234 typedef enum {
235   DI_FLAGS_RO = 1,  ///< Read-only value
236   DI_FLAGS_RO_SBX = 2,  ///< Value, read-only in the sandbox
237   DI_FLAGS_FIX = 4,  ///< Fixed value: cannot be :unlet or remove()d.
238   DI_FLAGS_LOCK = 8,  ///< Locked value.
239   DI_FLAGS_ALLOC = 16,  ///< Separately allocated.
240 } DictItemFlags;
241 
242 /// Structure representing a Dictionary
243 struct dictvar_S {
244   VarLockStatus dv_lock;  ///< Whole dictionary lock status.
245   ScopeType dv_scope;     ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
246                           ///< dictionary represents a scope (i.e. g:, l: …).
247   int dv_refcount;        ///< Reference count.
248   int dv_copyID;          ///< ID used when recursivery traversing a value.
249   hashtab_T dv_hashtab;   ///< Hashtab containing all items.
250   dict_T *dv_copydict;    ///< Copied dict used by deepcopy().
251   dict_T *dv_used_next;   ///< Next dictionary in used dictionaries list.
252   dict_T *dv_used_prev;   ///< Previous dictionary in used dictionaries list.
253   QUEUE watchers;         ///< Dictionary key watchers set by user code.
254 
255   LuaRef lua_table_ref;
256 };
257 
258 /// Structure to hold info about a Blob
259 struct blobvar_S {
260   garray_T bv_ga;         ///< Growarray with the data.
261   int bv_refcount;        ///< Reference count.
262   VarLockStatus bv_lock;  ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED.
263 };
264 
265 /// Type used for script ID
266 typedef int scid_T;
267 /// Format argument for scid_T
268 #define PRIdSCID "d"
269 
270 // SCript ConteXt (SCTX): identifies a script line.
271 // When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current
272 // line number. When executing a user function "sc_lnum" is the line where the
273 // function was defined, "sourcing_lnum" is the line number inside the
274 // function.  When stored with a function, mapping, option, etc. "sc_lnum" is
275 // the line number in the script "sc_sid".
276 typedef struct {
277   scid_T sc_sid;     // script ID
278   int sc_seq;        // sourcing sequence number
279   linenr_T sc_lnum;  // line number
280 } sctx_T;
281 
282 /// Maximum number of function arguments
283 #define MAX_FUNC_ARGS   20
284 /// Short variable name length
285 #define VAR_SHORT_LEN 20
286 /// Number of fixed variables used for arguments
287 #define FIXVAR_CNT 12
288 
289 /// Callback interface for C function reference>
290 ///     Used for managing functions that were registered with |register_cfunc|
291 typedef int (*cfunc_T)(int argcount, typval_T *argvars, typval_T *rettv, void *state);  // NOLINT
292 /// Callback to clear cfunc_T and any associated state.
293 typedef void (*cfunc_free_T)(void *state);
294 
295 // Structure to hold info for a function that is currently being executed.
296 typedef struct funccall_S funccall_T;
297 
298 struct funccall_S {
299   ufunc_T *func;  ///< Function being called.
300   int linenr;  ///< Next line to be executed.
301   int returned;  ///< ":return" used.
302   /// Fixed variables for arguments.
303   TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT];
304   dict_T l_vars;  ///< l: local function variables.
305   ScopeDictDictItem l_vars_var;  ///< Variable for l: scope.
306   dict_T l_avars;  ///< a: argument variables.
307   ScopeDictDictItem l_avars_var;  ///< Variable for a: scope.
308   list_T l_varlist;  ///< List for a:000.
309   listitem_T l_listitems[MAX_FUNC_ARGS];  ///< List items for a:000.
310   typval_T *rettv;  ///< Return value.
311   linenr_T breakpoint;  ///< Next line with breakpoint or zero.
312   int dbg_tick;  ///< Debug_tick when breakpoint was set.
313   int level;  ///< Top nesting level of executed function.
314   proftime_T prof_child;  ///< Time spent in a child.
315   funccall_T *caller;  ///< Calling function or NULL; or next funccal in
316                        ///< list pointed to by previous_funccal.
317   int fc_refcount;  ///< Number of user functions that reference this funccall.
318   int fc_copyID;  ///< CopyID used for garbage collection.
319   garray_T fc_funcs;  ///< List of ufunc_T* which keep a reference to "func".
320 };
321 
322 /// Structure to hold info for a user function.
323 struct ufunc {
324   int uf_varargs;       ///< variable nr of arguments
325   int uf_flags;
326   int uf_calls;         ///< nr of active calls
327   bool uf_cleared;       ///< func_clear() was already called
328   garray_T uf_args;          ///< arguments
329   garray_T uf_def_args;      ///< default argument expressions
330   garray_T uf_lines;         ///< function lines
331   int uf_profiling;     ///< true when func is being profiled
332   int uf_prof_initialized;
333   // Managing cfuncs
334   cfunc_T uf_cb;            ///< C function extension callback
335   cfunc_free_T uf_cb_free;       ///< C function extension free callback
336   void *uf_cb_state;      ///< State of C function extension.
337   // Profiling the function as a whole.
338   int uf_tm_count;      ///< nr of calls
339   proftime_T uf_tm_total;      ///< time spent in function + children
340   proftime_T uf_tm_self;       ///< time spent in function itself
341   proftime_T uf_tm_children;   ///< time spent in children this call
342   // Profiling the function per line.
343   int *uf_tml_count;     ///< nr of times line was executed
344   proftime_T *uf_tml_total;     ///< time spent in a line + children
345   proftime_T *uf_tml_self;      ///< time spent in a line itself
346   proftime_T uf_tml_start;     ///< start time for current line
347   proftime_T uf_tml_children;  ///< time spent in children for this line
348   proftime_T uf_tml_wait;      ///< start wait time for current line
349   int uf_tml_idx;       ///< index of line being timed; -1 if none
350   int uf_tml_execed;    ///< line being timed was executed
351   sctx_T uf_script_ctx;    ///< SCTX where function was defined,
352                            ///< used for s: variables
353   int uf_refcount;      ///< reference count, see func_name_refcount()
354   funccall_T *uf_scoped;       ///< l: local variables for closure
355   char_u uf_name[];  ///< Name of function (actual size equals name);
356                      ///< can start with <SNR>123_
357                      ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR)
358 };
359 
360 struct partial_S {
361   int pt_refcount;  ///< Reference count.
362   char_u *pt_name;  ///< Function name; when NULL use pt_func->name.
363   ufunc_T *pt_func;  ///< Function pointer; when NULL lookup function with
364                      ///< pt_name.
365   bool pt_auto;  ///< When true the partial was created by using dict.member
366                  ///< in handle_subscript().
367   int pt_argc;  ///< Number of arguments.
368   typval_T *pt_argv;  ///< Arguments in allocated array.
369   dict_T *pt_dict;  ///< Dict for "self".
370 };
371 
372 /// Structure used for explicit stack while garbage collecting hash tables
373 typedef struct ht_stack_S {
374   hashtab_T *ht;
375   struct ht_stack_S *prev;
376 } ht_stack_T;
377 
378 /// Structure used for explicit stack while garbage collecting lists
379 typedef struct list_stack_S {
380   list_T *list;
381   struct list_stack_S *prev;
382 } list_stack_T;
383 
384 /// Structure representing one list item, used for sort array.
385 typedef struct {
386   listitem_T *item;  ///< Sorted list item.
387   int idx;  ///< Sorted list item index.
388 } ListSortItem;
389 
390 typedef int (*ListSorter)(const void *, const void *);
391 
392 #ifdef LOG_LIST_ACTIONS
393 
394 /// List actions log entry
395 typedef struct {
396   uintptr_t l;  ///< List log entry belongs to.
397   uintptr_t li1;  ///< First list item log entry belongs to, if applicable.
398   uintptr_t li2;  ///< Second list item log entry belongs to, if applicable.
399   int len;  ///< List length when log entry was created.
400   const char *action;  ///< Logged action.
401 } ListLogEntry;
402 
403 typedef struct list_log ListLog;
404 
405 /// List actions log
406 struct list_log {
407   ListLog *next;  ///< Next chunk or NULL.
408   size_t capacity;  ///< Number of entries in current chunk.
409   size_t size;  ///< Current chunk size.
410   ListLogEntry entries[];  ///< Actual log entries.
411 };
412 
413 extern ListLog *list_log_first;  ///< First list log chunk, NULL if missing
414 extern ListLog *list_log_last;  ///< Last list log chunk
415 
416 static inline ListLog *list_log_alloc(const size_t size)
417   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT;
418 
419 /// Allocate a new log chunk and update globals
420 ///
421 /// @param[in]  size  Number of entries in a new chunk.
422 ///
423 /// @return [allocated] Newly allocated chunk.
list_log_new(const size_t size)424 static inline ListLog *list_log_new(const size_t size)
425 {
426   ListLog *ret = xmalloc(offsetof(ListLog, entries)
427                          + size * sizeof(ret->entries[0]));
428   ret->size = 0;
429   ret->capacity = size;
430   ret->next = NULL;
431   if (list_log_first == NULL) {
432     list_log_first = ret;
433   } else {
434     list_log_last->next = ret;
435   }
436   list_log_last = ret;
437   return ret;
438 }
439 
440 static inline void list_log(const list_T *const l,
441                             const listitem_T *const li1,
442                             const listitem_T *const li2,
443                             const char *const action)
444   REAL_FATTR_ALWAYS_INLINE;
445 
446 /// Add new entry to log
447 ///
448 /// If last chunk was filled it uses twice as much memory to allocate the next
449 /// chunk.
450 ///
451 /// @param[in]  l  List to which entry belongs.
452 /// @param[in]  li1  List item 1.
453 /// @param[in]  li2  List item 2, often used for integers and not list items.
454 /// @param[in]  action  Logged action.
list_log(const list_T * const l,const listitem_T * const li1,const listitem_T * const li2,const char * const action)455 static inline void list_log(const list_T *const l, const listitem_T *const li1,
456                             const listitem_T *const li2, const char *const action)
457 {
458   ListLog *tgt;
459   if (list_log_first == NULL) {
460     tgt = list_log_new(128);
461   } else if (list_log_last->size == list_log_last->capacity) {
462     tgt = list_log_new(list_log_last->capacity * 2);
463   } else {
464     tgt = list_log_last;
465   }
466   tgt->entries[tgt->size++] = (ListLogEntry) {
467     .l = (uintptr_t)l,
468     .li1 = (uintptr_t)li1,
469     .li2 = (uintptr_t)li2,
470     .len = (l == NULL ? 0 : l->lv_len),
471     .action = action,
472   };
473 }
474 #else
475 # define list_log(...)
476 # define list_write_log(...)
477 # define list_free_log()
478 #endif
479 
480 // In a hashtab item "hi_key" points to "di_key" in a dictitem.
481 // This avoids adding a pointer to the hashtab item.
482 
483 /// Convert a hashitem pointer to a dictitem pointer
484 #define TV_DICT_HI2DI(hi) \
485   ((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
486 
487 static inline void tv_list_ref(list_T *const l)
488   REAL_FATTR_ALWAYS_INLINE;
489 
490 /// Increase reference count for a given list
491 ///
492 /// Does nothing for NULL lists.
493 ///
494 /// @param[in,out]  l  List to modify.
tv_list_ref(list_T * const l)495 static inline void tv_list_ref(list_T *const l)
496 {
497   if (l == NULL) {
498     return;
499   }
500   l->lv_refcount++;
501 }
502 
503 static inline void tv_list_set_ret(typval_T *const tv, list_T *const l)
504   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1);
505 
506 /// Set a list as the return value.  Increments the reference count.
507 ///
508 /// @param[out]  tv  Object to receive the list
509 /// @param[in,out]  l  List to pass to the object
tv_list_set_ret(typval_T * const tv,list_T * const l)510 static inline void tv_list_set_ret(typval_T *const tv, list_T *const l)
511 {
512   tv->v_type = VAR_LIST;
513   tv->vval.v_list = l;
514   tv_list_ref(l);
515 }
516 
517 static inline VarLockStatus tv_list_locked(const list_T *const l)
518   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
519 
520 /// Get list lock status
521 ///
522 /// Returns VAR_FIXED for NULL lists.
523 ///
524 /// @param[in]  l  List to check.
tv_list_locked(const list_T * const l)525 static inline VarLockStatus tv_list_locked(const list_T *const l)
526 {
527   if (l == NULL) {
528     return VAR_FIXED;
529   }
530   return l->lv_lock;
531 }
532 
533 /// Set list lock status
534 ///
535 /// May only “set” VAR_FIXED for NULL lists.
536 ///
537 /// @param[out]  l  List to modify.
538 /// @param[in]  lock  New lock status.
tv_list_set_lock(list_T * const l,const VarLockStatus lock)539 static inline void tv_list_set_lock(list_T *const l, const VarLockStatus lock)
540 {
541   if (l == NULL) {
542     assert(lock == VAR_FIXED);
543     return;
544   }
545   l->lv_lock = lock;
546 }
547 
548 /// Set list copyID
549 ///
550 /// Does not expect NULL list, be careful.
551 ///
552 /// @param[out]  l  List to modify.
553 /// @param[in]  copyid  New copyID.
tv_list_set_copyid(list_T * const l,const int copyid)554 static inline void tv_list_set_copyid(list_T *const l, const int copyid)
555   FUNC_ATTR_NONNULL_ALL
556 {
557   l->lv_copyID = copyid;
558 }
559 
560 static inline int tv_list_len(const list_T *const l)
561   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
562 
563 /// Get the number of items in a list
564 ///
565 /// @param[in]  l  List to check.
tv_list_len(const list_T * const l)566 static inline int tv_list_len(const list_T *const l)
567 {
568   list_log(l, NULL, NULL, "len");
569   if (l == NULL) {
570     return 0;
571   }
572   return l->lv_len;
573 }
574 
575 static inline int tv_list_copyid(const list_T *const l)
576   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
577 
578 /// Get list copyID
579 ///
580 /// Does not expect NULL list, be careful.
581 ///
582 /// @param[in]  l  List to check.
tv_list_copyid(const list_T * const l)583 static inline int tv_list_copyid(const list_T *const l)
584 {
585   return l->lv_copyID;
586 }
587 
588 static inline list_T *tv_list_latest_copy(const list_T *const l)
589   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
590 
591 /// Get latest list copy
592 ///
593 /// Gets lv_copylist field assigned by tv_list_copy() earlier.
594 ///
595 /// Does not expect NULL list, be careful.
596 ///
597 /// @param[in]  l  List to check.
tv_list_latest_copy(const list_T * const l)598 static inline list_T *tv_list_latest_copy(const list_T *const l)
599 {
600   return l->lv_copylist;
601 }
602 
603 static inline int tv_list_uidx(const list_T *const l, int n)
604   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
605 
606 /// Normalize index: that is, return either -1 or non-negative index
607 ///
608 /// @param[in]  l  List to index. Used to get length.
609 /// @param[in]  n  List index, possibly negative.
610 ///
611 /// @return -1 or list index in range [0, tv_list_len(l)).
tv_list_uidx(const list_T * const l,int n)612 static inline int tv_list_uidx(const list_T *const l, int n)
613 {
614   // Negative index is relative to the end.
615   if (n < 0) {
616     n += tv_list_len(l);
617   }
618 
619   // Check for index out of range.
620   if (n < 0 || n >= tv_list_len(l)) {
621     return -1;
622   }
623   return n;
624 }
625 
626 static inline bool tv_list_has_watchers(const list_T *const l)
627   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
628 
629 /// Check whether list has watchers
630 ///
631 /// E.g. is referenced by a :for loop.
632 ///
633 /// @param[in]  l  List to check.
634 ///
635 /// @return true if there are watchers, false otherwise.
tv_list_has_watchers(const list_T * const l)636 static inline bool tv_list_has_watchers(const list_T *const l)
637 {
638   return l && l->lv_watch;
639 }
640 
641 static inline listitem_T *tv_list_first(const list_T *const l)
642   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
643 
644 /// Get first list item
645 ///
646 /// @param[in]  l  List to get item from.
647 ///
648 /// @return List item or NULL in case of an empty list.
tv_list_first(const list_T * const l)649 static inline listitem_T *tv_list_first(const list_T *const l)
650 {
651   if (l == NULL) {
652     list_log(l, NULL, NULL, "first");
653     return NULL;
654   }
655   list_log(l, l->lv_first, NULL, "first");
656   return l->lv_first;
657 }
658 
659 static inline listitem_T *tv_list_last(const list_T *const l)
660   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
661 
662 /// Get last list item
663 ///
664 /// @param[in]  l  List to get item from.
665 ///
666 /// @return List item or NULL in case of an empty list.
tv_list_last(const list_T * const l)667 static inline listitem_T *tv_list_last(const list_T *const l)
668 {
669   if (l == NULL) {
670     list_log(l, NULL, NULL, "last");
671     return NULL;
672   }
673   list_log(l, l->lv_last, NULL, "last");
674   return l->lv_last;
675 }
676 
677 static inline void tv_dict_set_ret(typval_T *const tv, dict_T *const d)
678   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1);
679 
680 /// Set a dictionary as the return value
681 ///
682 /// @param[out]  tv  Object to receive the dictionary
683 /// @param[in,out]  d  Dictionary to pass to the object
tv_dict_set_ret(typval_T * const tv,dict_T * const d)684 static inline void tv_dict_set_ret(typval_T *const tv, dict_T *const d)
685 {
686   tv->v_type = VAR_DICT;
687   tv->vval.v_dict = d;
688   if (d != NULL) {
689     d->dv_refcount++;
690   }
691 }
692 
693 static inline long tv_dict_len(const dict_T *const d)
694   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
695 
696 /// Get the number of items in a Dictionary
697 ///
698 /// @param[in]  d  Dictionary to check.
tv_dict_len(const dict_T * const d)699 static inline long tv_dict_len(const dict_T *const d)
700 {
701   if (d == NULL) {
702     return 0L;
703   }
704   return (long)d->dv_hashtab.ht_used;
705 }
706 
707 static inline bool tv_dict_is_watched(const dict_T *const d)
708   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
709 
710 /// Check if dictionary is watched
711 ///
712 /// @param[in]  d  Dictionary to check.
713 ///
714 /// @return true if there is at least one watcher.
tv_dict_is_watched(const dict_T * const d)715 static inline bool tv_dict_is_watched(const dict_T *const d)
716 {
717   return d && !QUEUE_EMPTY(&d->watchers);
718 }
719 
720 static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b)
721   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1);
722 
723 /// Set a blob as the return value.
724 ///
725 /// Increments the reference count.
726 ///
727 /// @param[out]  tv  Object to receive the blob.
728 /// @param[in,out]  b  Blob to pass to the object.
tv_blob_set_ret(typval_T * const tv,blob_T * const b)729 static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b)
730 {
731   tv->v_type = VAR_BLOB;
732   tv->vval.v_blob = b;
733   if (b != NULL) {
734     b->bv_refcount++;
735   }
736 }
737 
738 static inline int tv_blob_len(const blob_T *const b)
739   REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
740 
741 /// Get the length of the data in the blob, in bytes.
742 ///
743 /// @param[in]  b  Blob to check.
tv_blob_len(const blob_T * const b)744 static inline int tv_blob_len(const blob_T *const b)
745 {
746   if (b == NULL) {
747     return 0;
748   }
749   return b->bv_ga.ga_len;
750 }
751 
752 static inline char_u tv_blob_get(const blob_T *const b, int idx)
753   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
754 
755 /// Get the byte at index `idx` in the blob.
756 ///
757 /// @param[in]  b  Blob to index. Cannot be NULL.
758 /// @param[in]  idx  Index in a blob. Must be valid.
759 ///
760 /// @return Byte value at the given index.
tv_blob_get(const blob_T * const b,int idx)761 static inline char_u tv_blob_get(const blob_T *const b, int idx)
762 {
763   return ((char_u *)b->bv_ga.ga_data)[idx];
764 }
765 
766 static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
767   REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
768 
769 /// Store the byte `c` at index `idx` in the blob.
770 ///
771 /// @param[in]  b  Blob to index. Cannot be NULL.
772 /// @param[in]  idx  Index in a blob. Must be valid.
773 /// @param[in]  c  Value to store.
tv_blob_set(blob_T * const b,int idx,char_u c)774 static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
775 {
776   ((char_u *)b->bv_ga.ga_data)[idx] = c;
777 }
778 
779 /// Initialize VimL object
780 ///
781 /// Initializes to unlocked VAR_UNKNOWN object.
782 ///
783 /// @param[out]  tv  Object to initialize.
tv_init(typval_T * const tv)784 static inline void tv_init(typval_T *const tv)
785 {
786   if (tv != NULL) {
787     memset(tv, 0, sizeof(*tv));
788   }
789 }
790 
791 #define TV_INITIAL_VALUE \
792   ((typval_T) { \
793     .v_type = VAR_UNKNOWN, \
794     .v_lock = VAR_UNLOCKED, \
795   })
796 
797 /// Empty string
798 ///
799 /// Needed for hack which allows not allocating empty string and still not
800 /// crashing when freeing it.
801 extern const char *const tv_empty_string;
802 
803 /// Specifies that free_unref_items() function has (not) been entered
804 extern bool tv_in_free_unref_items;
805 
806 /// Iterate over a list
807 ///
808 /// @param  modifier  Modifier: expected to be const or nothing, volatile should
809 ///                   also work if you have any uses for the volatile list.
810 /// @param[in]  l  List to iterate over.
811 /// @param  li  Name of the variable with current listitem_T entry.
812 /// @param  code  Cycle body.
813 #define _TV_LIST_ITER_MOD(modifier, l, li, code) \
814   do { \
815     modifier list_T *const l_ = (l); \
816     list_log(l_, NULL, NULL, "iter" #modifier); \
817     if (l_ != NULL) { \
818       for (modifier listitem_T *li = l_->lv_first; \
819            li != NULL; li = li->li_next) { \
820         code \
821       } \
822     } \
823   } while (0)
824 
825 /// Iterate over a list
826 ///
827 /// To be used when you need to modify list or values you iterate over, use
828 /// #TV_LIST_ITER_CONST if you don’t.
829 ///
830 /// @param[in]  l  List to iterate over.
831 /// @param  li  Name of the variable with current listitem_T entry.
832 /// @param  code  Cycle body.
833 #define TV_LIST_ITER(l, li, code) \
834   _TV_LIST_ITER_MOD( , l, li, code)
835 
836 /// Iterate over a list
837 ///
838 /// To be used when you don’t need to modify list or values you iterate over,
839 /// use #TV_LIST_ITER if you do.
840 ///
841 /// @param[in]  l  List to iterate over.
842 /// @param  li  Name of the variable with current listitem_T entry.
843 /// @param  code  Cycle body.
844 #define TV_LIST_ITER_CONST(l, li, code) \
845   _TV_LIST_ITER_MOD(const, l, li, code)
846 
847 // Below macros are macros to avoid duplicating code for functionally identical
848 // const and non-const function variants.
849 
850 /// Get typval_T out of list item
851 ///
852 /// @param[in]  li  List item to get typval_T from, must not be NULL.
853 ///
854 /// @return Pointer to typval_T.
855 #define TV_LIST_ITEM_TV(li) (&(li)->li_tv)
856 
857 /// Get next list item given the current one
858 ///
859 /// @param[in]  l  List to get item from.
860 /// @param[in]  li  List item to get typval_T from.
861 ///
862 /// @return Pointer to the next item or NULL.
863 #define TV_LIST_ITEM_NEXT(l, li) ((li)->li_next)
864 
865 /// Get previous list item given the current one
866 ///
867 /// @param[in]  l  List to get item from.
868 /// @param[in]  li  List item to get typval_T from.
869 ///
870 /// @return Pointer to the previous item or NULL.
871 #define TV_LIST_ITEM_PREV(l, li) ((li)->li_prev)
872 // List argument is not used currently, but it is a must for lists implemented
873 // as a pair (size(in list), array) without terminator - basically for lists on
874 // top of kvec.
875 
876 /// Iterate over a dictionary
877 ///
878 /// @param[in]  d  Dictionary to iterate over.
879 /// @param  di  Name of the variable with current dictitem_T entry.
880 /// @param  code  Cycle body.
881 #define TV_DICT_ITER(d, di, code) \
882   HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \
883     { \
884       dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \
885       { \
886         code \
887       } \
888     } \
889   })
890 
891 static inline bool tv_get_float_chk(const typval_T *const tv,
892                                     float_T *const ret_f)
893   REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
894 
895 // FIXME circular dependency, cannot import message.h.
896 bool semsg(const char *const fmt, ...);
897 
898 /// Get the float value
899 ///
900 /// Raises an error if object is not number or floating-point.
901 ///
902 /// @param[in]  tv  VimL object to get value from.
903 /// @param[out]  ret_f  Location where resulting float is stored.
904 ///
905 /// @return true in case of success, false if tv is not a number or float.
tv_get_float_chk(const typval_T * const tv,float_T * const ret_f)906 static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret_f)
907 {
908   if (tv->v_type == VAR_FLOAT) {
909     *ret_f = tv->vval.v_float;
910     return true;
911   }
912   if (tv->v_type == VAR_NUMBER) {
913     *ret_f = (float_T)tv->vval.v_number;
914     return true;
915   }
916   semsg("%s", _("E808: Number or Float required"));
917   return false;
918 }
919 
920 static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
921   REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
922   REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
923 
924 /// Compute the `DictWatcher` address from a QUEUE node.
925 ///
926 /// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
927 /// arithmetic).
tv_dict_watcher_node_data(QUEUE * q)928 static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
929 {
930   return QUEUE_DATA(q, DictWatcher, node);
931 }
932 
933 static inline bool tv_is_func(const typval_T tv)
934   FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST;
935 
936 /// Check whether given typval_T contains a function
937 ///
938 /// That is, whether it contains VAR_FUNC or VAR_PARTIAL.
939 ///
940 /// @param[in]  tv  Typval to check.
941 ///
942 /// @return True if it is a function or a partial, false otherwise.
tv_is_func(const typval_T tv)943 static inline bool tv_is_func(const typval_T tv)
944 {
945   return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL;
946 }
947 
948 /// Specify that argument needs to be translated
949 ///
950 /// Used for size_t length arguments to avoid calling gettext() and strlen()
951 /// unless needed.
952 #define TV_TRANSLATE (SIZE_MAX)
953 
954 /// Specify that argument is a NUL-terminated C string
955 ///
956 /// Used for size_t length arguments to avoid calling strlen() unless needed.
957 #define TV_CSTRING (SIZE_MAX - 1)
958 
959 #ifdef UNIT_TESTING
960 // Do not use enum constants, see commit message.
961 EXTERN const size_t kTVCstring INIT(= TV_CSTRING);
962 EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE);
963 #endif
964 
965 #ifdef INCLUDE_GENERATED_DECLARATIONS
966 # include "eval/typval.h.generated.h"
967 #endif
968 #endif  // NVIM_EVAL_TYPVAL_H
969