Patch 9.0.1175

8 views
Skip to first unread message

Bram Moolenaar

unread,
Jan 11, 2023, 6:47:02 AM1/11/23
to vim...@googlegroups.com

Patch 9.0.1175
Problem: The set_ref_in_item() function is too long.
Solution: Use a separate function for more complicated types. (Yegappan
Lakshmanan, closes #11802)
Files: src/eval.c


*** ../vim-9.0.1174/src/eval.c 2023-01-06 18:42:16.434674109 +0000
--- src/eval.c 2023-01-11 11:44:37.922251835 +0000
***************
*** 5484,5489 ****
--- 5484,5738 ----
}

/*
+ * Mark the dict "dd" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_dict(
+ dict_T *dd,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ if (dd == NULL || dd->dv_copyID == copyID)
+ return FALSE;
+
+ // Didn't see this dict yet.
+ dd->dv_copyID = copyID;
+ if (ht_stack == NULL)
+ return set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
+
+ ht_stack_T *newitem = ALLOC_ONE(ht_stack_T);
+ if (newitem == NULL)
+ return TRUE;
+
+ newitem->ht = &dd->dv_hashtab;
+ newitem->prev = *ht_stack;
+ *ht_stack = newitem;
+
+ return FALSE;
+ }
+
+ /*
+ * Mark the list "ll" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_list(
+ list_T *ll,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ if (ll == NULL || ll->lv_copyID == copyID)
+ return FALSE;
+
+ // Didn't see this list yet.
+ ll->lv_copyID = copyID;
+ if (list_stack == NULL)
+ return set_ref_in_list_items(ll, copyID, ht_stack);
+
+ list_stack_T *newitem = ALLOC_ONE(list_stack_T);
+ if (newitem == NULL)
+ return TRUE;
+
+ newitem->list = ll;
+ newitem->prev = *list_stack;
+ *list_stack = newitem;
+
+ return FALSE;
+ }
+
+ /*
+ * Mark the partial "pt" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_partial(
+ partial_T *pt,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ if (pt == NULL || pt->pt_copyID == copyID)
+ return FALSE;
+
+ // Didn't see this partial yet.
+ pt->pt_copyID = copyID;
+
+ int abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
+
+ if (pt->pt_dict != NULL)
+ {
+ typval_T dtv;
+
+ dtv.v_type = VAR_DICT;
+ dtv.vval.v_dict = pt->pt_dict;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+
+ for (int i = 0; i < pt->pt_argc; ++i)
+ abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
+ ht_stack, list_stack);
+ // pt_funcstack is handled in set_ref_in_funcstacks()
+ // pt_loopvars is handled in set_ref_in_loopvars()
+
+ return abort;
+ }
+
+ /*
+ * Mark the job "pt" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_job(
+ job_T *job,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ #ifdef FEAT_JOB_CHANNEL
+ typval_T dtv;
+
+ if (job == NULL || job->jv_copyID == copyID)
+ return FALSE;
+
+ job->jv_copyID = copyID;
+ if (job->jv_channel != NULL)
+ {
+ dtv.v_type = VAR_CHANNEL;
+ dtv.vval.v_channel = job->jv_channel;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ if (job->jv_exit_cb.cb_partial != NULL)
+ {
+ dtv.v_type = VAR_PARTIAL;
+ dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ #endif
+
+ return FALSE;
+ }
+
+ /*
+ * Mark the channel "ch" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_channel(
+ channel_T *ch,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ #ifdef FEAT_JOB_CHANNEL
+ typval_T dtv;
+
+ if (ch == NULL || ch->ch_copyID == copyID)
+ return FALSE;
+
+ ch->ch_copyID = copyID;
+ for (ch_part_T part = PART_SOCK; part < PART_COUNT; ++part)
+ {
+ for (jsonq_T *jq = ch->ch_part[part].ch_json_head.jq_next;
+ jq != NULL; jq = jq->jq_next)
+ set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
+ for (cbq_T *cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
+ cq = cq->cq_next)
+ if (cq->cq_callback.cb_partial != NULL)
+ {
+ dtv.v_type = VAR_PARTIAL;
+ dtv.vval.v_partial = cq->cq_callback.cb_partial;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ if (ch->ch_part[part].ch_callback.cb_partial != NULL)
+ {
+ dtv.v_type = VAR_PARTIAL;
+ dtv.vval.v_partial = ch->ch_part[part].ch_callback.cb_partial;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ }
+ if (ch->ch_callback.cb_partial != NULL)
+ {
+ dtv.v_type = VAR_PARTIAL;
+ dtv.vval.v_partial = ch->ch_callback.cb_partial;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ if (ch->ch_close_cb.cb_partial != NULL)
+ {
+ dtv.v_type = VAR_PARTIAL;
+ dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
+ set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
+ }
+ #endif
+
+ return FALSE;
+ }
+
+ /*
+ * Mark the class "cl" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_class(
+ class_T *cl,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ int abort = FALSE;
+
+ if (cl == NULL || cl->class_copyID == copyID
+ || (cl->class_flags & CLASS_INTERFACE) != 0)
+ return FALSE;
+
+ cl->class_copyID = copyID;
+ for (int i = 0; !abort && i < cl->class_class_member_count; ++i)
+ abort = abort || set_ref_in_item(
+ &cl->class_members_tv[i],
+ copyID, ht_stack, list_stack);
+
+ for (int i = 0; !abort && i < cl->class_class_function_count; ++i)
+ abort = abort || set_ref_in_func(NULL,
+ cl->class_class_functions[i], copyID);
+
+ for (int i = 0; !abort && i < cl->class_obj_method_count; ++i)
+ abort = abort || set_ref_in_func(NULL,
+ cl->class_obj_methods[i], copyID);
+
+ return abort;
+ }
+
+ /*
+ * Mark the object "cl" with "copyID".
+ * Also see set_ref_in_item().
+ */
+ static int
+ set_ref_in_item_object(
+ object_T *obj,
+ int copyID,
+ ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
+ {
+ int abort = FALSE;
+
+ if (obj == NULL || obj->obj_copyID == copyID)
+ return FALSE;
+
+ obj->obj_copyID = copyID;
+
+ // The typval_T array is right after the object_T.
+ typval_T *mtv = (typval_T *)(obj + 1);
+ for (int i = 0; !abort
+ && i < obj->obj_class->class_obj_member_count; ++i)
+ abort = abort || set_ref_in_item(mtv + i, copyID,
+ ht_stack, list_stack);
+
+ return abort;
+ }
+
+ /*
* Mark all lists, dicts and other container types referenced through typval
* "tv" with "copyID".
* "list_stack" is used to add lists to be marked. Can be NULL.
***************
*** 5503,5564 ****
switch (tv->v_type)
{
case VAR_DICT:
! {
! dict_T *dd = tv->vval.v_dict;
!
! if (dd != NULL && dd->dv_copyID != copyID)
! {
! // Didn't see this dict yet.
! dd->dv_copyID = copyID;
! if (ht_stack == NULL)
! {
! abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
! }
! else
! {
! ht_stack_T *newitem = ALLOC_ONE(ht_stack_T);
!
! if (newitem == NULL)
! abort = TRUE;
! else
! {
! newitem->ht = &dd->dv_hashtab;
! newitem->prev = *ht_stack;
! *ht_stack = newitem;
! }
! }
! }
! break;
! }

case VAR_LIST:
! {
! list_T *ll = tv->vval.v_list;
!
! if (ll != NULL && ll->lv_copyID != copyID)
! {
! // Didn't see this list yet.
! ll->lv_copyID = copyID;
! if (list_stack == NULL)
! {
! abort = set_ref_in_list_items(ll, copyID, ht_stack);
! }
! else
! {
! list_stack_T *newitem = ALLOC_ONE(list_stack_T);
!
! if (newitem == NULL)
! abort = TRUE;
! else
! {
! newitem->list = ll;
! newitem->prev = *list_stack;
! *list_stack = newitem;
! }
! }
! }
! break;
! }

case VAR_FUNC:
{
--- 5752,5763 ----
switch (tv->v_type)
{
case VAR_DICT:
! return set_ref_in_item_dict(tv->vval.v_dict, copyID,
! ht_stack, list_stack);

case VAR_LIST:
! return set_ref_in_item_list(tv->vval.v_list, copyID,
! ht_stack, list_stack);

case VAR_FUNC:
{
***************
*** 5567,5723 ****
}

case VAR_PARTIAL:
! {
! partial_T *pt = tv->vval.v_partial;
! int i;
!
! if (pt != NULL && pt->pt_copyID != copyID)
! {
! // Didn't see this partial yet.
! pt->pt_copyID = copyID;
!
! abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
!
! if (pt->pt_dict != NULL)
! {
! typval_T dtv;
!
! dtv.v_type = VAR_DICT;
! dtv.vval.v_dict = pt->pt_dict;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
!
! for (i = 0; i < pt->pt_argc; ++i)
! abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
! ht_stack, list_stack);
! // pt_funcstack is handled in set_ref_in_funcstacks()
! // pt_loopvars is handled in set_ref_in_loopvars()
! }
! break;
! }

case VAR_JOB:
! {
! #ifdef FEAT_JOB_CHANNEL
! job_T *job = tv->vval.v_job;
! typval_T dtv;
!
! if (job != NULL && job->jv_copyID != copyID)
! {
! job->jv_copyID = copyID;
! if (job->jv_channel != NULL)
! {
! dtv.v_type = VAR_CHANNEL;
! dtv.vval.v_channel = job->jv_channel;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! if (job->jv_exit_cb.cb_partial != NULL)
! {
! dtv.v_type = VAR_PARTIAL;
! dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! }
! #endif
! break;
! }

case VAR_CHANNEL:
! {
! #ifdef FEAT_JOB_CHANNEL
! channel_T *ch = tv->vval.v_channel;
! ch_part_T part;
! typval_T dtv;
! jsonq_T *jq;
! cbq_T *cq;
!
! if (ch != NULL && ch->ch_copyID != copyID)
! {
! ch->ch_copyID = copyID;
! for (part = PART_SOCK; part < PART_COUNT; ++part)
! {
! for (jq = ch->ch_part[part].ch_json_head.jq_next;
! jq != NULL; jq = jq->jq_next)
! set_ref_in_item(jq->jq_value, copyID,
! ht_stack, list_stack);
! for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
! cq = cq->cq_next)
! if (cq->cq_callback.cb_partial != NULL)
! {
! dtv.v_type = VAR_PARTIAL;
! dtv.vval.v_partial = cq->cq_callback.cb_partial;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! if (ch->ch_part[part].ch_callback.cb_partial != NULL)
! {
! dtv.v_type = VAR_PARTIAL;
! dtv.vval.v_partial =
! ch->ch_part[part].ch_callback.cb_partial;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! }
! if (ch->ch_callback.cb_partial != NULL)
! {
! dtv.v_type = VAR_PARTIAL;
! dtv.vval.v_partial = ch->ch_callback.cb_partial;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! if (ch->ch_close_cb.cb_partial != NULL)
! {
! dtv.v_type = VAR_PARTIAL;
! dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
! set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
! }
! }
! #endif
! break;
! }

case VAR_CLASS:
! {
! class_T *cl = tv->vval.v_class;
! if (cl != NULL && cl->class_copyID != copyID
! && (cl->class_flags && CLASS_INTERFACE) == 0)
! {
! cl->class_copyID = copyID;
! for (int i = 0; !abort
! && i < cl->class_class_member_count; ++i)
! abort = abort || set_ref_in_item(
! &cl->class_members_tv[i],
! copyID, ht_stack, list_stack);
!
!
! for (int i = 0; !abort
! && i < cl->class_class_function_count; ++i)
! abort = abort || set_ref_in_func(NULL,
! cl->class_class_functions[i], copyID);
!
! for (int i = 0; !abort
! && i < cl->class_obj_method_count; ++i)
! abort = abort || set_ref_in_func(NULL,
! cl->class_obj_methods[i], copyID);
!
! // Mark initializer expressions?
! }
! break;
! }

case VAR_OBJECT:
! {
! object_T *obj = tv->vval.v_object;
! if (obj != NULL && obj->obj_copyID != copyID)
! {
! obj->obj_copyID = copyID;
!
! // The typval_T array is right after the object_T.
! typval_T *mtv = (typval_T *)(obj + 1);
! for (int i = 0; !abort
! && i < obj->obj_class->class_obj_member_count; ++i)
! abort = abort || set_ref_in_item(mtv + i, copyID,
ht_stack, list_stack);
- }
- break;
- }

case VAR_UNKNOWN:
case VAR_ANY:
--- 5766,5789 ----
}

case VAR_PARTIAL:
! return set_ref_in_item_partial(tv->vval.v_partial, copyID,
! ht_stack, list_stack);

case VAR_JOB:
! return set_ref_in_item_job(tv->vval.v_job, copyID,
! ht_stack, list_stack);

case VAR_CHANNEL:
! return set_ref_in_item_channel(tv->vval.v_channel, copyID,
! ht_stack, list_stack);

case VAR_CLASS:
! return set_ref_in_item_class(tv->vval.v_class, copyID,
! ht_stack, list_stack);

case VAR_OBJECT:
! return set_ref_in_item_object(tv->vval.v_object, copyID,
ht_stack, list_stack);

case VAR_UNKNOWN:
case VAR_ANY:
*** ../vim-9.0.1174/src/version.c 2023-01-10 19:58:31.030209252 +0000
--- src/version.c 2023-01-11 11:39:24.130750955 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1175,
/**/

--
Git catch 22: "merge is not possible because you have unmerged files."

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

John Marriott

unread,
Jan 11, 2023, 2:02:52 PM1/11/23
to vim...@googlegroups.com

On 11-Jan-2023 22:46, Bram Moolenaar wrote:
> Patch 9.0.1175
> Problem: The set_ref_in_item() function is too long.
> Solution: Use a separate function for more complicated types. (Yegappan
> Lakshmanan, closes #11802)
> Files: src/eval.c
>
>
>
After this patch msys64 (clang 15.0.5) gives this error message:
<snip>
clang -c -I. -Iproto -DWIN32 -DWINVER=0x0603 -D_WIN32_WINNT=0x0603
-DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -D__USE_MINGW_ANSI_STDIO
-pipe -Wall -O3 -fomit-frame-pointer -fpie -fPIE -DFEAT_GUI_MSWIN
-DFEAT_CLIPBOARD eval.c -o gobjx86-64/eval.o
eval.c:5773:42: error: no member named 'v_job' in 'union
typval_S::(unnamed at ./structs.h:1548:5)'
            return set_ref_in_item_job(tv->vval.v_job, copyID,
                                       ~~~~~~~~ ^
eval.c:5777:46: error: no member named 'v_channel' in 'union
typval_S::(unnamed at ./structs.h:1548:5)'
            return set_ref_in_item_channel(tv->vval.v_channel, copyID,
                                           ~~~~~~~~ ^
2 errors generated.
make: *** [Make_cyg_ming.mak:1206: gobjx86-64/eval.o] Error 1
</snip>

The attached patch tries to fix it.

Cheers
John
eval.c.9.0.1175.patch

Bram Moolenaar

unread,
Jan 11, 2023, 2:11:53 PM1/11/23
to vim...@googlegroups.com, John Marriott
I'll include it, thanks.

--
While it's true that many normal people whould prefer not to _date_ an
engineer, most normal people harbor an intense desire to _mate_ with them,
thus producing engineerlike children who will have high-paying jobs long
before losing their virginity.
(Scott Adams - The Dilbert principle)
Reply all
Reply to author
Forward
0 new messages