Mercurial > vim
comparison src/eval.c @ 31686:966f1213dd35 v9.0.1175
patch 9.0.1175: the set_ref_in_item() function is too long
Commit: https://github.com/vim/vim/commit/ea125393af01ecaf75cee8e085a57f8143f3ae3e
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Wed Jan 11 11:46:17 2023 +0000
patch 9.0.1175: the set_ref_in_item() function is too long
Problem: The set_ref_in_item() function is too long.
Solution: Use a separate function for more complicated types. (Yegappan
Lakshmanan, closes #11802)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 11 Jan 2023 13:00:05 +0100 |
parents | 62237ea155d9 |
children | 57248cc8bd70 |
comparison
equal
deleted
inserted
replaced
31685:2ed7c3993447 | 31686:966f1213dd35 |
---|---|
5482 tv.vval.v_partial = cb->cb_partial; | 5482 tv.vval.v_partial = cb->cb_partial; |
5483 return set_ref_in_item(&tv, copyID, NULL, NULL); | 5483 return set_ref_in_item(&tv, copyID, NULL, NULL); |
5484 } | 5484 } |
5485 | 5485 |
5486 /* | 5486 /* |
5487 * Mark the dict "dd" with "copyID". | |
5488 * Also see set_ref_in_item(). | |
5489 */ | |
5490 static int | |
5491 set_ref_in_item_dict( | |
5492 dict_T *dd, | |
5493 int copyID, | |
5494 ht_stack_T **ht_stack, | |
5495 list_stack_T **list_stack) | |
5496 { | |
5497 if (dd == NULL || dd->dv_copyID == copyID) | |
5498 return FALSE; | |
5499 | |
5500 // Didn't see this dict yet. | |
5501 dd->dv_copyID = copyID; | |
5502 if (ht_stack == NULL) | |
5503 return set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack); | |
5504 | |
5505 ht_stack_T *newitem = ALLOC_ONE(ht_stack_T); | |
5506 if (newitem == NULL) | |
5507 return TRUE; | |
5508 | |
5509 newitem->ht = &dd->dv_hashtab; | |
5510 newitem->prev = *ht_stack; | |
5511 *ht_stack = newitem; | |
5512 | |
5513 return FALSE; | |
5514 } | |
5515 | |
5516 /* | |
5517 * Mark the list "ll" with "copyID". | |
5518 * Also see set_ref_in_item(). | |
5519 */ | |
5520 static int | |
5521 set_ref_in_item_list( | |
5522 list_T *ll, | |
5523 int copyID, | |
5524 ht_stack_T **ht_stack, | |
5525 list_stack_T **list_stack) | |
5526 { | |
5527 if (ll == NULL || ll->lv_copyID == copyID) | |
5528 return FALSE; | |
5529 | |
5530 // Didn't see this list yet. | |
5531 ll->lv_copyID = copyID; | |
5532 if (list_stack == NULL) | |
5533 return set_ref_in_list_items(ll, copyID, ht_stack); | |
5534 | |
5535 list_stack_T *newitem = ALLOC_ONE(list_stack_T); | |
5536 if (newitem == NULL) | |
5537 return TRUE; | |
5538 | |
5539 newitem->list = ll; | |
5540 newitem->prev = *list_stack; | |
5541 *list_stack = newitem; | |
5542 | |
5543 return FALSE; | |
5544 } | |
5545 | |
5546 /* | |
5547 * Mark the partial "pt" with "copyID". | |
5548 * Also see set_ref_in_item(). | |
5549 */ | |
5550 static int | |
5551 set_ref_in_item_partial( | |
5552 partial_T *pt, | |
5553 int copyID, | |
5554 ht_stack_T **ht_stack, | |
5555 list_stack_T **list_stack) | |
5556 { | |
5557 if (pt == NULL || pt->pt_copyID == copyID) | |
5558 return FALSE; | |
5559 | |
5560 // Didn't see this partial yet. | |
5561 pt->pt_copyID = copyID; | |
5562 | |
5563 int abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID); | |
5564 | |
5565 if (pt->pt_dict != NULL) | |
5566 { | |
5567 typval_T dtv; | |
5568 | |
5569 dtv.v_type = VAR_DICT; | |
5570 dtv.vval.v_dict = pt->pt_dict; | |
5571 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5572 } | |
5573 | |
5574 for (int i = 0; i < pt->pt_argc; ++i) | |
5575 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID, | |
5576 ht_stack, list_stack); | |
5577 // pt_funcstack is handled in set_ref_in_funcstacks() | |
5578 // pt_loopvars is handled in set_ref_in_loopvars() | |
5579 | |
5580 return abort; | |
5581 } | |
5582 | |
5583 /* | |
5584 * Mark the job "pt" with "copyID". | |
5585 * Also see set_ref_in_item(). | |
5586 */ | |
5587 static int | |
5588 set_ref_in_item_job( | |
5589 job_T *job, | |
5590 int copyID, | |
5591 ht_stack_T **ht_stack, | |
5592 list_stack_T **list_stack) | |
5593 { | |
5594 #ifdef FEAT_JOB_CHANNEL | |
5595 typval_T dtv; | |
5596 | |
5597 if (job == NULL || job->jv_copyID == copyID) | |
5598 return FALSE; | |
5599 | |
5600 job->jv_copyID = copyID; | |
5601 if (job->jv_channel != NULL) | |
5602 { | |
5603 dtv.v_type = VAR_CHANNEL; | |
5604 dtv.vval.v_channel = job->jv_channel; | |
5605 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5606 } | |
5607 if (job->jv_exit_cb.cb_partial != NULL) | |
5608 { | |
5609 dtv.v_type = VAR_PARTIAL; | |
5610 dtv.vval.v_partial = job->jv_exit_cb.cb_partial; | |
5611 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5612 } | |
5613 #endif | |
5614 | |
5615 return FALSE; | |
5616 } | |
5617 | |
5618 /* | |
5619 * Mark the channel "ch" with "copyID". | |
5620 * Also see set_ref_in_item(). | |
5621 */ | |
5622 static int | |
5623 set_ref_in_item_channel( | |
5624 channel_T *ch, | |
5625 int copyID, | |
5626 ht_stack_T **ht_stack, | |
5627 list_stack_T **list_stack) | |
5628 { | |
5629 #ifdef FEAT_JOB_CHANNEL | |
5630 typval_T dtv; | |
5631 | |
5632 if (ch == NULL || ch->ch_copyID == copyID) | |
5633 return FALSE; | |
5634 | |
5635 ch->ch_copyID = copyID; | |
5636 for (ch_part_T part = PART_SOCK; part < PART_COUNT; ++part) | |
5637 { | |
5638 for (jsonq_T *jq = ch->ch_part[part].ch_json_head.jq_next; | |
5639 jq != NULL; jq = jq->jq_next) | |
5640 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack); | |
5641 for (cbq_T *cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL; | |
5642 cq = cq->cq_next) | |
5643 if (cq->cq_callback.cb_partial != NULL) | |
5644 { | |
5645 dtv.v_type = VAR_PARTIAL; | |
5646 dtv.vval.v_partial = cq->cq_callback.cb_partial; | |
5647 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5648 } | |
5649 if (ch->ch_part[part].ch_callback.cb_partial != NULL) | |
5650 { | |
5651 dtv.v_type = VAR_PARTIAL; | |
5652 dtv.vval.v_partial = ch->ch_part[part].ch_callback.cb_partial; | |
5653 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5654 } | |
5655 } | |
5656 if (ch->ch_callback.cb_partial != NULL) | |
5657 { | |
5658 dtv.v_type = VAR_PARTIAL; | |
5659 dtv.vval.v_partial = ch->ch_callback.cb_partial; | |
5660 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5661 } | |
5662 if (ch->ch_close_cb.cb_partial != NULL) | |
5663 { | |
5664 dtv.v_type = VAR_PARTIAL; | |
5665 dtv.vval.v_partial = ch->ch_close_cb.cb_partial; | |
5666 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5667 } | |
5668 #endif | |
5669 | |
5670 return FALSE; | |
5671 } | |
5672 | |
5673 /* | |
5674 * Mark the class "cl" with "copyID". | |
5675 * Also see set_ref_in_item(). | |
5676 */ | |
5677 static int | |
5678 set_ref_in_item_class( | |
5679 class_T *cl, | |
5680 int copyID, | |
5681 ht_stack_T **ht_stack, | |
5682 list_stack_T **list_stack) | |
5683 { | |
5684 int abort = FALSE; | |
5685 | |
5686 if (cl == NULL || cl->class_copyID == copyID | |
5687 || (cl->class_flags & CLASS_INTERFACE) != 0) | |
5688 return FALSE; | |
5689 | |
5690 cl->class_copyID = copyID; | |
5691 for (int i = 0; !abort && i < cl->class_class_member_count; ++i) | |
5692 abort = abort || set_ref_in_item( | |
5693 &cl->class_members_tv[i], | |
5694 copyID, ht_stack, list_stack); | |
5695 | |
5696 for (int i = 0; !abort && i < cl->class_class_function_count; ++i) | |
5697 abort = abort || set_ref_in_func(NULL, | |
5698 cl->class_class_functions[i], copyID); | |
5699 | |
5700 for (int i = 0; !abort && i < cl->class_obj_method_count; ++i) | |
5701 abort = abort || set_ref_in_func(NULL, | |
5702 cl->class_obj_methods[i], copyID); | |
5703 | |
5704 return abort; | |
5705 } | |
5706 | |
5707 /* | |
5708 * Mark the object "cl" with "copyID". | |
5709 * Also see set_ref_in_item(). | |
5710 */ | |
5711 static int | |
5712 set_ref_in_item_object( | |
5713 object_T *obj, | |
5714 int copyID, | |
5715 ht_stack_T **ht_stack, | |
5716 list_stack_T **list_stack) | |
5717 { | |
5718 int abort = FALSE; | |
5719 | |
5720 if (obj == NULL || obj->obj_copyID == copyID) | |
5721 return FALSE; | |
5722 | |
5723 obj->obj_copyID = copyID; | |
5724 | |
5725 // The typval_T array is right after the object_T. | |
5726 typval_T *mtv = (typval_T *)(obj + 1); | |
5727 for (int i = 0; !abort | |
5728 && i < obj->obj_class->class_obj_member_count; ++i) | |
5729 abort = abort || set_ref_in_item(mtv + i, copyID, | |
5730 ht_stack, list_stack); | |
5731 | |
5732 return abort; | |
5733 } | |
5734 | |
5735 /* | |
5487 * Mark all lists, dicts and other container types referenced through typval | 5736 * Mark all lists, dicts and other container types referenced through typval |
5488 * "tv" with "copyID". | 5737 * "tv" with "copyID". |
5489 * "list_stack" is used to add lists to be marked. Can be NULL. | 5738 * "list_stack" is used to add lists to be marked. Can be NULL. |
5490 * "ht_stack" is used to add hashtabs to be marked. Can be NULL. | 5739 * "ht_stack" is used to add hashtabs to be marked. Can be NULL. |
5491 * | 5740 * |
5501 int abort = FALSE; | 5750 int abort = FALSE; |
5502 | 5751 |
5503 switch (tv->v_type) | 5752 switch (tv->v_type) |
5504 { | 5753 { |
5505 case VAR_DICT: | 5754 case VAR_DICT: |
5506 { | 5755 return set_ref_in_item_dict(tv->vval.v_dict, copyID, |
5507 dict_T *dd = tv->vval.v_dict; | 5756 ht_stack, list_stack); |
5508 | |
5509 if (dd != NULL && dd->dv_copyID != copyID) | |
5510 { | |
5511 // Didn't see this dict yet. | |
5512 dd->dv_copyID = copyID; | |
5513 if (ht_stack == NULL) | |
5514 { | |
5515 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack); | |
5516 } | |
5517 else | |
5518 { | |
5519 ht_stack_T *newitem = ALLOC_ONE(ht_stack_T); | |
5520 | |
5521 if (newitem == NULL) | |
5522 abort = TRUE; | |
5523 else | |
5524 { | |
5525 newitem->ht = &dd->dv_hashtab; | |
5526 newitem->prev = *ht_stack; | |
5527 *ht_stack = newitem; | |
5528 } | |
5529 } | |
5530 } | |
5531 break; | |
5532 } | |
5533 | 5757 |
5534 case VAR_LIST: | 5758 case VAR_LIST: |
5535 { | 5759 return set_ref_in_item_list(tv->vval.v_list, copyID, |
5536 list_T *ll = tv->vval.v_list; | 5760 ht_stack, list_stack); |
5537 | |
5538 if (ll != NULL && ll->lv_copyID != copyID) | |
5539 { | |
5540 // Didn't see this list yet. | |
5541 ll->lv_copyID = copyID; | |
5542 if (list_stack == NULL) | |
5543 { | |
5544 abort = set_ref_in_list_items(ll, copyID, ht_stack); | |
5545 } | |
5546 else | |
5547 { | |
5548 list_stack_T *newitem = ALLOC_ONE(list_stack_T); | |
5549 | |
5550 if (newitem == NULL) | |
5551 abort = TRUE; | |
5552 else | |
5553 { | |
5554 newitem->list = ll; | |
5555 newitem->prev = *list_stack; | |
5556 *list_stack = newitem; | |
5557 } | |
5558 } | |
5559 } | |
5560 break; | |
5561 } | |
5562 | 5761 |
5563 case VAR_FUNC: | 5762 case VAR_FUNC: |
5564 { | 5763 { |
5565 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID); | 5764 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID); |
5566 break; | 5765 break; |
5567 } | 5766 } |
5568 | 5767 |
5569 case VAR_PARTIAL: | 5768 case VAR_PARTIAL: |
5570 { | 5769 return set_ref_in_item_partial(tv->vval.v_partial, copyID, |
5571 partial_T *pt = tv->vval.v_partial; | 5770 ht_stack, list_stack); |
5572 int i; | 5771 |
5573 | 5772 case VAR_JOB: |
5574 if (pt != NULL && pt->pt_copyID != copyID) | 5773 return set_ref_in_item_job(tv->vval.v_job, copyID, |
5575 { | |
5576 // Didn't see this partial yet. | |
5577 pt->pt_copyID = copyID; | |
5578 | |
5579 abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID); | |
5580 | |
5581 if (pt->pt_dict != NULL) | |
5582 { | |
5583 typval_T dtv; | |
5584 | |
5585 dtv.v_type = VAR_DICT; | |
5586 dtv.vval.v_dict = pt->pt_dict; | |
5587 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5588 } | |
5589 | |
5590 for (i = 0; i < pt->pt_argc; ++i) | |
5591 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID, | |
5592 ht_stack, list_stack); | 5774 ht_stack, list_stack); |
5593 // pt_funcstack is handled in set_ref_in_funcstacks() | |
5594 // pt_loopvars is handled in set_ref_in_loopvars() | |
5595 } | |
5596 break; | |
5597 } | |
5598 | |
5599 case VAR_JOB: | |
5600 { | |
5601 #ifdef FEAT_JOB_CHANNEL | |
5602 job_T *job = tv->vval.v_job; | |
5603 typval_T dtv; | |
5604 | |
5605 if (job != NULL && job->jv_copyID != copyID) | |
5606 { | |
5607 job->jv_copyID = copyID; | |
5608 if (job->jv_channel != NULL) | |
5609 { | |
5610 dtv.v_type = VAR_CHANNEL; | |
5611 dtv.vval.v_channel = job->jv_channel; | |
5612 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5613 } | |
5614 if (job->jv_exit_cb.cb_partial != NULL) | |
5615 { | |
5616 dtv.v_type = VAR_PARTIAL; | |
5617 dtv.vval.v_partial = job->jv_exit_cb.cb_partial; | |
5618 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5619 } | |
5620 } | |
5621 #endif | |
5622 break; | |
5623 } | |
5624 | 5775 |
5625 case VAR_CHANNEL: | 5776 case VAR_CHANNEL: |
5626 { | 5777 return set_ref_in_item_channel(tv->vval.v_channel, copyID, |
5627 #ifdef FEAT_JOB_CHANNEL | |
5628 channel_T *ch = tv->vval.v_channel; | |
5629 ch_part_T part; | |
5630 typval_T dtv; | |
5631 jsonq_T *jq; | |
5632 cbq_T *cq; | |
5633 | |
5634 if (ch != NULL && ch->ch_copyID != copyID) | |
5635 { | |
5636 ch->ch_copyID = copyID; | |
5637 for (part = PART_SOCK; part < PART_COUNT; ++part) | |
5638 { | |
5639 for (jq = ch->ch_part[part].ch_json_head.jq_next; | |
5640 jq != NULL; jq = jq->jq_next) | |
5641 set_ref_in_item(jq->jq_value, copyID, | |
5642 ht_stack, list_stack); | 5778 ht_stack, list_stack); |
5643 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL; | |
5644 cq = cq->cq_next) | |
5645 if (cq->cq_callback.cb_partial != NULL) | |
5646 { | |
5647 dtv.v_type = VAR_PARTIAL; | |
5648 dtv.vval.v_partial = cq->cq_callback.cb_partial; | |
5649 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5650 } | |
5651 if (ch->ch_part[part].ch_callback.cb_partial != NULL) | |
5652 { | |
5653 dtv.v_type = VAR_PARTIAL; | |
5654 dtv.vval.v_partial = | |
5655 ch->ch_part[part].ch_callback.cb_partial; | |
5656 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5657 } | |
5658 } | |
5659 if (ch->ch_callback.cb_partial != NULL) | |
5660 { | |
5661 dtv.v_type = VAR_PARTIAL; | |
5662 dtv.vval.v_partial = ch->ch_callback.cb_partial; | |
5663 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5664 } | |
5665 if (ch->ch_close_cb.cb_partial != NULL) | |
5666 { | |
5667 dtv.v_type = VAR_PARTIAL; | |
5668 dtv.vval.v_partial = ch->ch_close_cb.cb_partial; | |
5669 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); | |
5670 } | |
5671 } | |
5672 #endif | |
5673 break; | |
5674 } | |
5675 | 5779 |
5676 case VAR_CLASS: | 5780 case VAR_CLASS: |
5677 { | 5781 return set_ref_in_item_class(tv->vval.v_class, copyID, |
5678 class_T *cl = tv->vval.v_class; | 5782 ht_stack, list_stack); |
5679 if (cl != NULL && cl->class_copyID != copyID | |
5680 && (cl->class_flags && CLASS_INTERFACE) == 0) | |
5681 { | |
5682 cl->class_copyID = copyID; | |
5683 for (int i = 0; !abort | |
5684 && i < cl->class_class_member_count; ++i) | |
5685 abort = abort || set_ref_in_item( | |
5686 &cl->class_members_tv[i], | |
5687 copyID, ht_stack, list_stack); | |
5688 | |
5689 | |
5690 for (int i = 0; !abort | |
5691 && i < cl->class_class_function_count; ++i) | |
5692 abort = abort || set_ref_in_func(NULL, | |
5693 cl->class_class_functions[i], copyID); | |
5694 | |
5695 for (int i = 0; !abort | |
5696 && i < cl->class_obj_method_count; ++i) | |
5697 abort = abort || set_ref_in_func(NULL, | |
5698 cl->class_obj_methods[i], copyID); | |
5699 | |
5700 // Mark initializer expressions? | |
5701 } | |
5702 break; | |
5703 } | |
5704 | 5783 |
5705 case VAR_OBJECT: | 5784 case VAR_OBJECT: |
5706 { | 5785 return set_ref_in_item_object(tv->vval.v_object, copyID, |
5707 object_T *obj = tv->vval.v_object; | |
5708 if (obj != NULL && obj->obj_copyID != copyID) | |
5709 { | |
5710 obj->obj_copyID = copyID; | |
5711 | |
5712 // The typval_T array is right after the object_T. | |
5713 typval_T *mtv = (typval_T *)(obj + 1); | |
5714 for (int i = 0; !abort | |
5715 && i < obj->obj_class->class_obj_member_count; ++i) | |
5716 abort = abort || set_ref_in_item(mtv + i, copyID, | |
5717 ht_stack, list_stack); | 5786 ht_stack, list_stack); |
5718 } | |
5719 break; | |
5720 } | |
5721 | 5787 |
5722 case VAR_UNKNOWN: | 5788 case VAR_UNKNOWN: |
5723 case VAR_ANY: | 5789 case VAR_ANY: |
5724 case VAR_VOID: | 5790 case VAR_VOID: |
5725 case VAR_BOOL: | 5791 case VAR_BOOL: |