aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2024-02-19 21:21:05 +0100
committerGitHub <noreply@github.com>2024-02-19 21:21:05 +0100
commit8952a89db588db10a9dba16356f9bbd35ca5fabb (patch)
treeac34d55b77303deadef6a7ed3f4202259324a249
parent8fdc84d0aaec63d57203bdef4b88047479ad4fc1 (diff)
parent404707c7606389ccb6c6062bfe9e2ff30a2552af (diff)
downloadrneovim-8952a89db588db10a9dba16356f9bbd35ca5fabb.tar.gz
rneovim-8952a89db588db10a9dba16356f9bbd35ca5fabb.tar.bz2
rneovim-8952a89db588db10a9dba16356f9bbd35ca5fabb.zip
Merge pull request #27534 from bfredl/userarena
refactor(api): next PR to make use of the arena
-rw-r--r--src/nvim/api/command.c10
-rw-r--r--src/nvim/api/private/helpers.c16
-rw-r--r--src/nvim/api/tabpage.c10
-rw-r--r--src/nvim/api/vim.c110
-rw-r--r--src/nvim/ops.c3
-rw-r--r--src/nvim/runtime.c12
-rw-r--r--src/nvim/usercmd.c55
7 files changed, 107 insertions, 109 deletions
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index a21c9e70a7..f2d5342a5f 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -1166,10 +1166,10 @@ err:
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_get_commands(Dict(get_commands) *opts, Error *err)
+Dictionary nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
- return nvim_buf_get_commands(-1, opts, err);
+ return nvim_buf_get_commands(-1, opts, arena, err);
}
/// Gets a map of buffer-local |user-commands|.
@@ -1179,7 +1179,7 @@ Dictionary nvim_get_commands(Dict(get_commands) *opts, Error *err)
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error *err)
+Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
bool global = (buffer == -1);
@@ -1192,12 +1192,12 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
api_set_error(err, kErrorTypeValidation, "builtin=true not implemented");
return (Dictionary)ARRAY_DICT_INIT;
}
- return commands_array(NULL);
+ return commands_array(NULL, arena);
}
buf_T *buf = find_buffer_by_handle(buffer, err);
if (opts->builtin || !buf) {
return (Dictionary)ARRAY_DICT_INIT;
}
- return commands_array(buf);
+ return commands_array(buf, arena);
}
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 63c5689109..14f4046a56 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -456,9 +456,10 @@ String ga_take_string(garray_T *ga)
/// @param input Binary string
/// @param crlf Also break lines at CR and CRLF.
/// @return [allocated] String array
-Array string_to_array(const String input, bool crlf)
+Array string_to_array(const String input, bool crlf, Arena *arena)
{
- Array ret = ARRAY_DICT_INIT;
+ ArrayBuilder ret = ARRAY_DICT_INIT;
+ kvi_init(ret);
for (size_t i = 0; i < input.size; i++) {
const char *start = input.data + i;
const char *end = start;
@@ -473,20 +474,17 @@ Array string_to_array(const String input, bool crlf)
if (crlf && *end == CAR && i + 1 < input.size && *(end + 1) == NL) {
i += 1; // Advance past CRLF.
}
- String s = {
- .size = line_len,
- .data = xmemdupz(start, line_len),
- };
+ String s = CBUF_TO_ARENA_STR(arena, start, line_len);
memchrsub(s.data, NUL, NL, line_len);
- ADD(ret, STRING_OBJ(s));
+ kvi_push(ret, STRING_OBJ(s));
// If line ends at end-of-buffer, add empty final item.
// This is "readfile()-style", see also ":help channel-lines".
if (i + 1 == input.size && (*end == NL || (crlf && *end == CAR))) {
- ADD(ret, STRING_OBJ(STRING_INIT));
+ kvi_push(ret, STRING_OBJ(STRING_INIT));
}
}
- return ret;
+ return arena_take_arraybuilder(arena, &ret);
}
/// Normalizes 0-based indexes to buffer line numbers.
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index 109075df8e..040abb1e3f 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -19,7 +19,7 @@
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param[out] err Error details, if any
/// @return List of windows in `tabpage`
-ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
+ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -29,15 +29,15 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
return rv;
}
+ size_t n = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ rv = arena_array(arena, n);
FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- rv.items[i++] = WINDOW_OBJ(wp->handle);
+ ADD_C(rv, WINDOW_OBJ(wp->handle));
}
return rv;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index d161dca050..e472f5d160 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -543,17 +543,22 @@ Integer nvim_strwidth(String text, Error *err)
/// Gets the paths contained in |runtime-search-path|.
///
/// @return List of paths
-ArrayOf(String) nvim_list_runtime_paths(Error *err)
+ArrayOf(String) nvim_list_runtime_paths(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return nvim_get_runtime_file(NULL_STRING, true, err);
+ return nvim_get_runtime_file(NULL_STRING, true, arena, err);
}
-Array nvim__runtime_inspect(void)
+Array nvim__runtime_inspect(Arena *arena)
{
- return runtime_inspect();
+ return runtime_inspect(arena);
}
+typedef struct {
+ ArrayBuilder rv;
+ Arena *arena;
+} RuntimeCookie;
+
/// Find files in runtime directories
///
/// "name" can contain wildcards. For example
@@ -566,25 +571,27 @@ Array nvim__runtime_inspect(void)
/// @param name pattern of files to search for
/// @param all whether to return all matches or only the first
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
+ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_FAST
{
- Array rv = ARRAY_DICT_INIT;
+ RuntimeCookie cookie = { .rv = ARRAY_DICT_INIT, .arena = arena, };
+ kvi_init(cookie.rv);
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
TRY_WRAP(err, {
- do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &rv);
+ do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &cookie);
});
- return rv;
+ return arena_take_arraybuilder(arena, &cookie.rv);
}
-static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cookie)
+static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *c)
{
- Array *rv = (Array *)cookie;
+ RuntimeCookie *cookie = (RuntimeCookie *)c;
for (int i = 0; i < num_fnames; i++) {
- ADD(*rv, CSTR_TO_OBJ(fnames[i]));
+ // TODO(bfredl): consider memory management of gen_expand_wildcards() itself
+ kvi_push(cookie->rv, CSTR_TO_ARENA_OBJ(cookie->arena, fnames[i]));
if (!all) {
return true;
}
@@ -825,20 +832,19 @@ void nvim_err_writeln(String str)
/// Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
///
/// @return List of buffer handles
-ArrayOf(Buffer) nvim_list_bufs(void)
+ArrayOf(Buffer) nvim_list_bufs(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_BUFFERS(b) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_BUFFERS(b) {
- rv.items[i++] = BUFFER_OBJ(b->handle);
+ ADD_C(rv, BUFFER_OBJ(b->handle));
}
return rv;
@@ -880,20 +886,19 @@ void nvim_set_current_buf(Buffer buffer, Error *err)
/// Gets the current list of window handles.
///
/// @return List of window handles
-ArrayOf(Window) nvim_list_wins(void)
+ArrayOf(Window) nvim_list_wins(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.items[i++] = WINDOW_OBJ(wp->handle);
+ ADD_C(rv, WINDOW_OBJ(wp->handle));
}
return rv;
@@ -1117,20 +1122,19 @@ void nvim_chan_send(Integer chan, String data, Error *err)
/// Gets the current list of tabpage handles.
///
/// @return List of tabpage handles
-ArrayOf(Tabpage) nvim_list_tabpages(void)
+ArrayOf(Tabpage) nvim_list_tabpages(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TABS(tp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TABS(tp) {
- rv.items[i++] = TABPAGE_OBJ(tp->handle);
+ ADD_C(rv, TABPAGE_OBJ(tp->handle));
}
return rv;
@@ -1201,14 +1205,13 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error
VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, {
return false;
});
- Array lines = ARRAY_DICT_INIT;
if (phase == -1 || phase == 1) { // Start of paste-stream.
draining = false;
} else if (draining) {
// Skip remaining chunks. Report error only once per "stream".
goto theend;
}
- lines = string_to_array(data, crlf);
+ Array lines = string_to_array(data, crlf, arena);
MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, ARRAY_OBJ(lines));
ADD_C(args, INTEGER_OBJ(phase));
@@ -1239,7 +1242,6 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:
- api_free_array(lines);
if (cancel || phase == -1 || phase == 3) { // End of paste-stream.
draining = false;
}
@@ -1260,24 +1262,27 @@ theend:
/// @param after If true insert after cursor (like |p|), or before (like |P|).
/// @param follow If true place cursor at end of inserted text.
/// @param[out] err Error details, if any
-void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err)
+void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Arena *arena,
+ Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- yankreg_T *reg = xcalloc(1, sizeof(yankreg_T));
+ yankreg_T reg[1] = { 0 };
VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, {
- goto cleanup;
+ return;
});
if (lines.size == 0) {
- goto cleanup; // Nothing to do.
+ return; // Nothing to do.
}
+ reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
+ reg->y_size = lines.size;
for (size_t i = 0; i < lines.size; i++) {
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
- goto cleanup;
+ return;
});
String line = lines.items[i].data.string;
- reg->y_array[i] = xmemdupz(line.data, line.size);
+ reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
memchrsub(reg->y_array[i], NUL, NL, line.size);
}
@@ -1290,10 +1295,6 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
msg_silent--;
VIsual_active = VIsual_was_active;
});
-
-cleanup:
- free_register(reg);
- xfree(reg);
}
/// Subscribes to event broadcasts.
@@ -1583,13 +1584,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
///
/// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type,
- Dictionary methods, Dictionary attributes, Error *err)
+ Dictionary methods, Dictionary attributes, Arena *arena, Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{
- Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "name", copy_object(STRING_OBJ(name), NULL));
+ MAXSIZE_TEMP_DICT(info, 5);
+ PUT_C(info, "name", STRING_OBJ(name));
- version = copy_dictionary(version, NULL);
bool has_major = false;
for (size_t i = 0; i < version.size; i++) {
if (strequal(version.items[i].key.data, "major")) {
@@ -1598,15 +1598,21 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
}
}
if (!has_major) {
- PUT(version, "major", INTEGER_OBJ(0));
+ Dictionary v = arena_dict(arena, version.size + 1);
+ if (version.size) {
+ memcpy(v.items, version.items, version.size * sizeof(v.items[0]));
+ v.size = version.size;
+ }
+ PUT_C(v, "major", INTEGER_OBJ(0));
+ version = v;
}
- PUT(info, "version", DICTIONARY_OBJ(version));
+ PUT_C(info, "version", DICTIONARY_OBJ(version));
- PUT(info, "type", copy_object(STRING_OBJ(type), NULL));
- PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL)));
- PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL)));
+ PUT_C(info, "type", STRING_OBJ(type));
+ PUT_C(info, "methods", DICTIONARY_OBJ(methods));
+ PUT_C(info, "attributes", DICTIONARY_OBJ(attributes));
- rpc_set_client_info(channel_id, info);
+ rpc_set_client_info(channel_id, copy_dictionary(info, NULL));
}
/// Gets information about a channel.
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index f91df49e4f..e7a3aa29aa 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -6499,8 +6499,6 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
}
}
- reg->y_array = xcalloc(lines, sizeof(uint8_t *));
- reg->y_size = lines;
reg->additional_data = NULL;
reg->timestamp = 0;
return true;
@@ -6513,7 +6511,6 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
if (reg->y_type == kMTUnknown || clipboard_adjust) {
- xfree(reg->y_array[reg->y_size - 1]);
reg->y_size--;
}
if (reg->y_type == kMTUnknown) {
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 44fcc29ad1..fb6397f9eb 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -574,20 +574,20 @@ static int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback,
return did_one ? OK : FAIL;
}
-Array runtime_inspect(void)
+Array runtime_inspect(Arena *arena)
{
RuntimeSearchPath path = runtime_search_path;
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, kv_size(path));
for (size_t i = 0; i < kv_size(path); i++) {
SearchPathItem *item = &kv_A(path, i);
Array entry = ARRAY_DICT_INIT;
- ADD(entry, CSTR_TO_OBJ(item->path));
- ADD(entry, BOOLEAN_OBJ(item->after));
+ ADD_C(entry, CSTR_AS_OBJ(item->path));
+ ADD_C(entry, BOOLEAN_OBJ(item->after));
if (item->has_lua != kNone) {
- ADD(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
+ ADD_C(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
}
- ADD(rv, ARRAY_OBJ(entry));
+ ADD_C(rv, ARRAY_OBJ(entry));
}
return rv;
}
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index c4e04159ef..8d41edec8a 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -1744,25 +1744,24 @@ int do_ucmd(exarg_T *eap, bool preview)
/// @param buf Buffer to inspect, or NULL to get global commands.
///
/// @return Map of maps describing commands
-Dictionary commands_array(buf_T *buf)
+Dictionary commands_array(buf_T *buf, Arena *arena)
{
- Dictionary rv = ARRAY_DICT_INIT;
- char str[20];
garray_T *gap = (buf == NULL) ? &ucmds : &buf->b_ucmds;
+ Dictionary rv = arena_dict(arena, (size_t)gap->ga_len);
for (int i = 0; i < gap->ga_len; i++) {
char arg[2] = { 0, 0 };
- Dictionary d = ARRAY_DICT_INIT;
+ Dictionary d = arena_dict(arena, 14);
ucmd_T *cmd = USER_CMD_GA(gap, i);
- PUT(d, "name", CSTR_TO_OBJ(cmd->uc_name));
- PUT(d, "definition", CSTR_TO_OBJ(cmd->uc_rep));
- PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
- PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
- PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
- PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
- PUT(d, "keepscript", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_KEEPSCRIPT)));
- PUT(d, "preview", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_PREVIEW)));
+ PUT_C(d, "name", CSTR_AS_OBJ(cmd->uc_name));
+ PUT_C(d, "definition", CSTR_AS_OBJ(cmd->uc_rep));
+ PUT_C(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
+ PUT_C(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
+ PUT_C(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+ PUT_C(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
+ PUT_C(d, "keepscript", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_KEEPSCRIPT)));
+ PUT_C(d, "preview", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_PREVIEW)));
switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case 0:
@@ -1776,49 +1775,47 @@ Dictionary commands_array(buf_T *buf)
case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
arg[0] = '1'; break;
}
- PUT(d, "nargs", CSTR_TO_OBJ(arg));
+ PUT_C(d, "nargs", CSTR_TO_ARENA_OBJ(arena, arg));
char *cmd_compl = get_command_complete(cmd->uc_compl);
- PUT(d, "complete", (cmd_compl == NULL
- ? NIL : CSTR_TO_OBJ(cmd_compl)));
- PUT(d, "complete_arg", cmd->uc_compl_arg == NULL
- ? NIL : CSTR_TO_OBJ(cmd->uc_compl_arg));
+ PUT_C(d, "complete", (cmd_compl == NULL
+ ? NIL : CSTR_AS_OBJ(cmd_compl)));
+ PUT_C(d, "complete_arg", cmd->uc_compl_arg == NULL
+ ? NIL : CSTR_AS_OBJ(cmd->uc_compl_arg));
Object obj = NIL;
if (cmd->uc_argt & EX_COUNT) {
if (cmd->uc_def >= 0) {
- snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def);
- obj = CSTR_TO_OBJ(str); // -count=N
+ obj = STRING_OBJ(arena_printf(arena, "%" PRId64, cmd->uc_def)); // -count=N
} else {
- obj = CSTR_TO_OBJ("0"); // -count
+ obj = CSTR_AS_OBJ("0"); // -count
}
}
- PUT(d, "count", obj);
+ PUT_C(d, "count", obj);
obj = NIL;
if (cmd->uc_argt & EX_RANGE) {
if (cmd->uc_argt & EX_DFLALL) {
- obj = CSTR_TO_OBJ("%"); // -range=%
+ obj = STATIC_CSTR_AS_OBJ("%"); // -range=%
} else if (cmd->uc_def >= 0) {
- snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def);
- obj = CSTR_TO_OBJ(str); // -range=N
+ obj = STRING_OBJ(arena_printf(arena, "%" PRId64, cmd->uc_def)); // -range=N
} else {
- obj = CSTR_TO_OBJ("."); // -range
+ obj = STATIC_CSTR_AS_OBJ("."); // -range
}
}
- PUT(d, "range", obj);
+ PUT_C(d, "range", obj);
obj = NIL;
for (int j = 0; addr_type_complete[j].expand != ADDR_NONE; j++) {
if (addr_type_complete[j].expand != ADDR_LINES
&& addr_type_complete[j].expand == cmd->uc_addr_type) {
- obj = CSTR_TO_OBJ(addr_type_complete[j].name);
+ obj = CSTR_AS_OBJ(addr_type_complete[j].name);
break;
}
}
- PUT(d, "addr", obj);
+ PUT_C(d, "addr", obj);
- PUT(rv, cmd->uc_name, DICTIONARY_OBJ(d));
+ PUT_C(rv, cmd->uc_name, DICTIONARY_OBJ(d));
}
return rv;
}