aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2022-09-28 19:05:16 -0400
committerStefan Monnier2022-09-28 19:05:16 -0400
commitea8daec9bb8ebf3cbca35edec4e4ef7b6edac3de (patch)
tree1a34f44adca5fbf08033829dab643db6340bf296 /src
parent800ecd4767df48beeefabccdacd089b8c4286529 (diff)
downloademacs-ea8daec9bb8ebf3cbca35edec4e4ef7b6edac3de.tar.gz
emacs-ea8daec9bb8ebf3cbca35edec4e4ef7b6edac3de.zip
itree.[ch]: Add sanity checks, comments, and minor tweaks
* src/alloc.c (mark_overlay): Add sanity check. * src/buffer.c (next_overlay_change, previous_overlay_change): Tweak code to keep the same vars for the bounds. * src/itree.c (interval_tree_clear, interval_tree_insert) (interval_tree_remove, interval_tree_insert_fix, interval_tree_remove_fix): Adjust to the `color` -> `red` change. (interval_tree_clear): Prefer `true/false` for booleans. (interval_generator_create): Use an actual `interval_tree_order` value rather than 0. (interval_generator_next): Simplify a tiny bit. Add comment. (interval_generator_narrow): Add sanity check. * src/itree.h (struct interval_node): Replace `color` field with boolean `red` field. (enum interval_tree_order): Remove unused `ITREE_DEFLT_ORDER` value. * src/pdumper.c (dump_interval_node): Adjust to the `color` -> `red` change.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c3
-rw-r--r--src/buffer.c4
-rw-r--r--src/itree.c134
-rw-r--r--src/itree.h7
-rw-r--r--src/pdumper.c2
5 files changed, 89 insertions, 61 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 20b8981bd66..be55dcf8dfd 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6505,6 +6505,9 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6505static void 6505static void
6506mark_overlay (struct Lisp_Overlay *ov) 6506mark_overlay (struct Lisp_Overlay *ov)
6507{ 6507{
6508 /* We don't mark the `interval_node` object, because it is managed manually
6509 rather than by the GC. */
6510 eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike)));
6508 set_vectorlike_marked (&ov->header); 6511 set_vectorlike_marked (&ov->header);
6509 mark_object (ov->plist); 6512 mark_object (ov->plist);
6510} 6513}
diff --git a/src/buffer.c b/src/buffer.c
index 2b1997fc8be..879e14be960 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2992,7 +2992,7 @@ next_overlay_change (ptrdiff_t pos)
2992 ptrdiff_t next = ZV; 2992 ptrdiff_t next = ZV;
2993 struct interval_node *node; 2993 struct interval_node *node;
2994 2994
2995 buffer_overlay_iter_start (current_buffer, pos, ZV, ITREE_ASCENDING); 2995 buffer_overlay_iter_start (current_buffer, pos, next, ITREE_ASCENDING);
2996 while ((node = buffer_overlay_iter_next (current_buffer))) 2996 while ((node = buffer_overlay_iter_next (current_buffer)))
2997 { 2997 {
2998 if (node->begin > pos) 2998 if (node->begin > pos)
@@ -3020,7 +3020,7 @@ previous_overlay_change (ptrdiff_t pos)
3020 struct interval_node *node; 3020 struct interval_node *node;
3021 ptrdiff_t prev = BEGV; 3021 ptrdiff_t prev = BEGV;
3022 3022
3023 buffer_overlay_iter_start (current_buffer, BEGV, pos, ITREE_DESCENDING); 3023 buffer_overlay_iter_start (current_buffer, prev, pos, ITREE_DESCENDING);
3024 while ((node = buffer_overlay_iter_next (current_buffer))) 3024 while ((node = buffer_overlay_iter_next (current_buffer)))
3025 { 3025 {
3026 if (node->end < pos) 3026 if (node->end < pos)
diff --git a/src/itree.c b/src/itree.c
index e31ce39ba11..aa6fcc1bea0 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -233,11 +233,11 @@ interval_tree_clear (struct interval_tree *tree)
233 null->begin = PTRDIFF_MIN; 233 null->begin = PTRDIFF_MIN;
234 null->end = PTRDIFF_MIN; 234 null->end = PTRDIFF_MIN;
235 null->limit = PTRDIFF_MIN; /* => max(x, null.limit) = x */ 235 null->limit = PTRDIFF_MIN; /* => max(x, null.limit) = x */
236 null->color = ITREE_BLACK; 236 null->red = false;
237 tree->root = null; 237 tree->root = null;
238 tree->otick = 1; 238 tree->otick = 1;
239 tree->size = 0; 239 tree->size = 0;
240 tree->iter_running = 0; 240 tree->iter_running = false;
241} 241}
242 242
243#ifdef ITREE_TESTING 243#ifdef ITREE_TESTING
@@ -308,7 +308,7 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
308 node->parent = parent; 308 node->parent = parent;
309 node->left = &tree->null; 309 node->left = &tree->null;
310 node->right = &tree->null; 310 node->right = &tree->null;
311 node->color = ITREE_RED; 311 node->red = true;
312 node->offset = 0; 312 node->offset = 0;
313 node->begin -= offset; 313 node->begin -= offset;
314 node->end -= offset; 314 node->end -= offset;
@@ -351,7 +351,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
351 { 351 {
352 struct interval_node *subst = 352 struct interval_node *subst =
353 (node->right == &tree->null) ? node->left : node->right; 353 (node->right == &tree->null) ? node->left : node->right;
354 if (node->color == ITREE_BLACK) 354 if (!node->red)
355 broken = subst; 355 broken = subst;
356 interval_tree_transplant (tree, subst, node); 356 interval_tree_transplant (tree, subst, node);
357 interval_tree_propagate_limit (tree, subst); 357 interval_tree_propagate_limit (tree, subst);
@@ -361,7 +361,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
361 struct interval_node *min = interval_tree_subtree_min (tree, node->right); 361 struct interval_node *min = interval_tree_subtree_min (tree, node->right);
362 struct interval_node *min_right = min->right; 362 struct interval_node *min_right = min->right;
363 363
364 if (min->color == ITREE_BLACK) 364 if (!min->red)
365 broken = min->right; 365 broken = min->right;
366 if (min->parent == node) 366 if (min->parent == node)
367 min_right->parent = min; /* set parent, if min_right = null */ 367 min_right->parent = min; /* set parent, if min_right = null */
@@ -375,7 +375,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
375 interval_tree_transplant (tree, min, node); 375 interval_tree_transplant (tree, min, node);
376 min->left = node->left; 376 min->left = node->left;
377 min->left->parent = min; 377 min->left->parent = min;
378 min->color = node->color; 378 min->red = node->red;
379 interval_tree_propagate_limit (tree, min_right); 379 interval_tree_propagate_limit (tree, min_right);
380 interval_tree_propagate_limit (tree, min); 380 interval_tree_propagate_limit (tree, min);
381 } 381 }
@@ -440,7 +440,7 @@ interval_tree_iter_start (struct interval_tree *tree,
440 if (tree->iter_running) 440 if (tree->iter_running)
441 emacs_abort (); 441 emacs_abort ();
442 interval_generator_reset (tree->iter, begin, end, order); 442 interval_generator_reset (tree->iter, begin, end, order);
443 tree->iter_running = 1; 443 tree->iter_running = true;
444 tree->file = file; 444 tree->file = file;
445 tree->line = line; 445 tree->line = line;
446} 446}
@@ -464,7 +464,7 @@ interval_tree_iter_finish (struct interval_tree *tree)
464{ 464{
465 if (! tree->iter_running) 465 if (! tree->iter_running)
466 emacs_abort (); 466 emacs_abort ();
467 tree->iter_running = 0; 467 tree->iter_running = false;
468} 468}
469 469
470/* Return the next node of the iterator in the order given when it was 470/* Return the next node of the iterator in the order given when it was
@@ -637,7 +637,7 @@ interval_generator_create (struct interval_tree *tree)
637 637
638 g->stack = interval_stack_create (size); 638 g->stack = interval_stack_create (size);
639 g->tree = tree; 639 g->tree = tree;
640 interval_generator_reset (g, 1, 0, 0); 640 interval_generator_reset (g, 1, 0, ITREE_ASCENDING);
641 return g; 641 return g;
642} 642}
643 643
@@ -667,7 +667,13 @@ interval_generator_ensure_space (struct interval_generator *g)
667 interval_stack_ensure_space (g->stack, interval_tree_max_height (g->tree) + 1); 667 interval_stack_ensure_space (g->stack, interval_tree_max_height (g->tree) + 1);
668} 668}
669 669
670/* Return true, if NODE's interval intersects with [BEGIN, END). */ 670/* Return true, if NODE's interval intersects with [BEGIN, END).
671 Note: We always include empty nodes at BEGIN (and not at END),
672 but if BEGIN==END, then we don't include non-empty nodes starting
673 at BEGIN or ending at END. This seems to match the behavior of the
674 old overlays code but it's not clear if it's The Right Thing
675 (e.g. it breaks the expectation that if NODE1 is included, then
676 a NODE2 strictly bigger than NODE1 should also be included). */
671 677
672static inline bool 678static inline bool
673interval_node_intersects (const struct interval_node *node, 679interval_node_intersects (const struct interval_node *node,
@@ -687,10 +693,29 @@ interval_generator_next (struct interval_generator *g)
687 struct interval_node * const null = &g->tree->null; 693 struct interval_node * const null = &g->tree->null;
688 struct interval_node *node; 694 struct interval_node *node;
689 695
690 do { 696 /* The `visited` flag stored in each node is used here (and only here):
691 node = interval_stack_pop (g->stack); 697 We keep a "workstack" of nodes we need to consider. This stack
698 consist of nodes of two types: nodes that we have decided
699 should be returned by the generator, and nodes which we may
700 need to consider (including checking their children).
701 We start an iteration with a stack containing just the root
702 node marked as "not visited" which means that it (and its children)
703 needs to be considered but we haven't yet decided whether it's included
704 in the generator's output. */
705
706 /* FIXME: We should move the `visited` flag to the stack: each entry
707 there should simply consist of a node and a bool (the `visited` status)
708 so this internal implementation detail doesn't leak into the
709 `interval_node` structure.
710 [ In theory it would also allow multiple iterations to be active
711 at the same time, tho that does not seem particularly useful at
712 this time and would require further changes anyway. ]
713 To save space on the stack, we could hijack the LSB bit of the `node*`
714 word to hold the `visited` bit. */
692 715
693 while (node && ! node->visited) 716 do {
717 while ((node = interval_stack_pop (g->stack))
718 && ! node->visited)
694 { 719 {
695 struct interval_node * const left = node->left; 720 struct interval_node * const left = node->left;
696 struct interval_node * const right = node->right; 721 struct interval_node * const right = node->right;
@@ -724,7 +749,6 @@ interval_generator_next (struct interval_generator *g)
724 interval_stack_push_flagged (g->stack, node, true); 749 interval_stack_push_flagged (g->stack, node, true);
725 break; 750 break;
726 } 751 }
727 node = interval_stack_pop (g->stack);
728 } 752 }
729 /* Node may have been invalidated by interval_generator_narrow 753 /* Node may have been invalidated by interval_generator_narrow
730 after it was pushed: Check if it still intersects. */ 754 after it was pushed: Check if it still intersects. */
@@ -740,6 +764,8 @@ static inline void
740interval_generator_narrow (struct interval_generator *g, 764interval_generator_narrow (struct interval_generator *g,
741 ptrdiff_t begin, ptrdiff_t end) 765 ptrdiff_t begin, ptrdiff_t end)
742{ 766{
767 eassert (begin >= g->begin);
768 eassert (end <= g->end);
743 g->begin = max (begin, g->begin); 769 g->begin = max (begin, g->begin);
744 g->end = min (end, g->end); 770 g->end = min (end, g->end);
745} 771}
@@ -980,7 +1006,7 @@ interval_tree_rotate_right (struct interval_tree *tree, struct interval_node *no
980static void 1006static void
981interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node) 1007interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node)
982{ 1008{
983 while (node->parent->color == ITREE_RED) 1009 while (node->parent->red)
984 { 1010 {
985 /* NODE is red and its parent is red. This is a violation of 1011 /* NODE is red and its parent is red. This is a violation of
986 red-black tree property #3. */ 1012 red-black tree property #3. */
@@ -991,14 +1017,14 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
991 our "uncle". */ 1017 our "uncle". */
992 struct interval_node *uncle = node->parent->parent->right; 1018 struct interval_node *uncle = node->parent->parent->right;
993 1019
994 if (uncle->color == ITREE_RED) /* case 1.a */ 1020 if (uncle->red) /* case 1.a */
995 { 1021 {
996 /* Uncle and parent are red but should be black because 1022 /* Uncle and parent are red but should be black because
997 NODE is red. Change the colors accordingly and 1023 NODE is red. Change the colors accordingly and
998 proceed with the grandparent. */ 1024 proceed with the grandparent. */
999 node->parent->color = ITREE_BLACK; 1025 node->parent->red = false;
1000 uncle->color = ITREE_BLACK; 1026 uncle->red = false;
1001 node->parent->parent->color = ITREE_RED; 1027 node->parent->parent->red = true;
1002 node = node->parent->parent; 1028 node = node->parent->parent;
1003 } 1029 }
1004 else 1030 else
@@ -1011,8 +1037,8 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1011 interval_tree_rotate_left (tree, node); 1037 interval_tree_rotate_left (tree, node);
1012 } 1038 }
1013 /* case 3.a */ 1039 /* case 3.a */
1014 node->parent->color = ITREE_BLACK; 1040 node->parent->red = false;
1015 node->parent->parent->color = ITREE_RED; 1041 node->parent->parent->red = true;
1016 interval_tree_rotate_right (tree, node->parent->parent); 1042 interval_tree_rotate_right (tree, node->parent->parent);
1017 } 1043 }
1018 } 1044 }
@@ -1021,11 +1047,11 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1021 /* This is the symmetrical case of above. */ 1047 /* This is the symmetrical case of above. */
1022 struct interval_node *uncle = node->parent->parent->left; 1048 struct interval_node *uncle = node->parent->parent->left;
1023 1049
1024 if (uncle->color == ITREE_RED) /* case 1.b */ 1050 if (uncle->red) /* case 1.b */
1025 { 1051 {
1026 node->parent->color = ITREE_BLACK; 1052 node->parent->red = false;
1027 uncle->color = ITREE_BLACK; 1053 uncle->red = false;
1028 node->parent->parent->color = ITREE_RED; 1054 node->parent->parent->red = true;
1029 node = node->parent->parent; 1055 node = node->parent->parent;
1030 } 1056 }
1031 else 1057 else
@@ -1036,8 +1062,8 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1036 interval_tree_rotate_right (tree, node); 1062 interval_tree_rotate_right (tree, node);
1037 } 1063 }
1038 /* case 3.b */ 1064 /* case 3.b */
1039 node->parent->color = ITREE_BLACK; 1065 node->parent->red = false;
1040 node->parent->parent->color = ITREE_RED; 1066 node->parent->parent->red = true;
1041 interval_tree_rotate_left (tree, node->parent->parent); 1067 interval_tree_rotate_left (tree, node->parent->parent);
1042 } 1068 }
1043 } 1069 }
@@ -1045,7 +1071,7 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1045 1071
1046 /* The root may have been changed to red due to the algorithm. Set 1072 /* The root may have been changed to red due to the algorithm. Set
1047 it to black so that property #5 is satisfied. */ 1073 it to black so that property #5 is satisfied. */
1048 tree->root->color = ITREE_BLACK; 1074 tree->root->red = false;
1049} 1075}
1050 1076
1051/* Repair the tree after a deletion. Part of the RB-Tree 1077/* Repair the tree after a deletion. Part of the RB-Tree
@@ -1054,38 +1080,38 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1054static void 1080static void
1055interval_tree_remove_fix (struct interval_tree *tree, struct interval_node *node) 1081interval_tree_remove_fix (struct interval_tree *tree, struct interval_node *node)
1056{ 1082{
1057 while (node != tree->root && node->color == ITREE_BLACK) 1083 while (node != tree->root && !node->red)
1058 { 1084 {
1059 if (node == node->parent->left) 1085 if (node == node->parent->left)
1060 { 1086 {
1061 struct interval_node *other = node->parent->right; 1087 struct interval_node *other = node->parent->right;
1062 1088
1063 if (other->color == ITREE_RED) /* case 1.a */ 1089 if (other->red) /* case 1.a */
1064 { 1090 {
1065 other->color = ITREE_BLACK; 1091 other->red = false;
1066 node->parent->color = ITREE_RED; 1092 node->parent->red = true;
1067 interval_tree_rotate_left (tree, node->parent); 1093 interval_tree_rotate_left (tree, node->parent);
1068 other = node->parent->right; 1094 other = node->parent->right;
1069 } 1095 }
1070 1096
1071 if (other->left->color == ITREE_BLACK /* 2.a */ 1097 if (!other->left->red /* 2.a */
1072 && other->right->color == ITREE_BLACK) 1098 && !other->right->red)
1073 { 1099 {
1074 other->color = ITREE_RED; 1100 other->red = true;
1075 node = node->parent; 1101 node = node->parent;
1076 } 1102 }
1077 else 1103 else
1078 { 1104 {
1079 if (other->right->color == ITREE_BLACK) /* 3.a */ 1105 if (!other->right->red) /* 3.a */
1080 { 1106 {
1081 other->left->color = ITREE_BLACK; 1107 other->left->red = false;
1082 other->color = ITREE_RED; 1108 other->red = true;
1083 interval_tree_rotate_right (tree, other); 1109 interval_tree_rotate_right (tree, other);
1084 other = node->parent->right; 1110 other = node->parent->right;
1085 } 1111 }
1086 other->color = node->parent->color; /* 4.a */ 1112 other->red = node->parent->red; /* 4.a */
1087 node->parent->color = ITREE_BLACK; 1113 node->parent->red = false;
1088 other->right->color = ITREE_BLACK; 1114 other->right->red = false;
1089 interval_tree_rotate_left (tree, node->parent); 1115 interval_tree_rotate_left (tree, node->parent);
1090 node = tree->root; 1116 node = tree->root;
1091 } 1117 }
@@ -1094,40 +1120,40 @@ interval_tree_remove_fix (struct interval_tree *tree, struct interval_node *node
1094 { 1120 {
1095 struct interval_node *other = node->parent->left; 1121 struct interval_node *other = node->parent->left;
1096 1122
1097 if (other->color == ITREE_RED) /* 1.b */ 1123 if (other->red) /* 1.b */
1098 { 1124 {
1099 other->color = ITREE_BLACK; 1125 other->red = false;
1100 node->parent->color = ITREE_RED; 1126 node->parent->red = true;
1101 interval_tree_rotate_right (tree, node->parent); 1127 interval_tree_rotate_right (tree, node->parent);
1102 other = node->parent->left; 1128 other = node->parent->left;
1103 } 1129 }
1104 1130
1105 if (other->right->color == ITREE_BLACK /* 2.b */ 1131 if (!other->right->red /* 2.b */
1106 && other->left->color == ITREE_BLACK) 1132 && !other->left->red)
1107 { 1133 {
1108 other->color = ITREE_RED; 1134 other->red = true;
1109 node = node->parent; 1135 node = node->parent;
1110 } 1136 }
1111 else 1137 else
1112 { 1138 {
1113 if (other->left->color == ITREE_BLACK) /* 3.b */ 1139 if (!other->left->red) /* 3.b */
1114 { 1140 {
1115 other->right->color = ITREE_BLACK; 1141 other->right->red = false;
1116 other->color = ITREE_RED; 1142 other->red = true;
1117 interval_tree_rotate_left (tree, other); 1143 interval_tree_rotate_left (tree, other);
1118 other = node->parent->left; 1144 other = node->parent->left;
1119 } 1145 }
1120 1146
1121 other->color = node->parent->color; /* 4.b */ 1147 other->red = node->parent->red; /* 4.b */
1122 node->parent->color = ITREE_BLACK; 1148 node->parent->red = false;
1123 other->left->color = ITREE_BLACK; 1149 other->left->red = false;
1124 interval_tree_rotate_right (tree, node->parent); 1150 interval_tree_rotate_right (tree, node->parent);
1125 node = tree->root; 1151 node = tree->root;
1126 } 1152 }
1127 } 1153 }
1128 } 1154 }
1129 1155
1130 node->color = ITREE_BLACK; 1156 node->red = false;
1131} 1157}
1132 1158
1133/* Link node SOURCE in DEST's place. */ 1159/* Link node SOURCE in DEST's place. */
diff --git a/src/itree.h b/src/itree.h
index e5d68fbfabb..8f0454dc7a4 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -45,8 +45,8 @@ struct interval_node
45 ptrdiff_t offset; /* The amount of shift to apply to this subtree. */ 45 ptrdiff_t offset; /* The amount of shift to apply to this subtree. */
46 uintmax_t otick; /* offset modified tick */ 46 uintmax_t otick; /* offset modified tick */
47 Lisp_Object data; /* Exclusively used by the client. */ 47 Lisp_Object data; /* Exclusively used by the client. */
48 enum { ITREE_RED, ITREE_BLACK } color; 48 bool_bf red : 1;
49 bool_bf visited : 1; /* For traversal via generator. */ 49 bool_bf visited : 1; /* Internal to `interval_generator_next`. */
50 bool_bf rear_advance : 1; /* Same as for marker and overlays. */ 50 bool_bf rear_advance : 1; /* Same as for marker and overlays. */
51 bool_bf front_advance : 1; /* Same as for marker and overlays. */ 51 bool_bf front_advance : 1; /* Same as for marker and overlays. */
52}; 52};
@@ -64,8 +64,7 @@ struct interval_tree
64}; 64};
65 65
66enum interval_tree_order { 66enum interval_tree_order {
67 ITREE_ASCENDING = 0, 67 ITREE_ASCENDING,
68 ITREE_DEFLT_ORDER = 0,
69 ITREE_DESCENDING, 68 ITREE_DESCENDING,
70 ITREE_PRE_ORDER, 69 ITREE_PRE_ORDER,
71}; 70};
diff --git a/src/pdumper.c b/src/pdumper.c
index 79644c01517..44486015f05 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2154,7 +2154,7 @@ dump_interval_node (struct dump_context *ctx, struct interval_node *node,
2154 DUMP_FIELD_COPY (&out, node, offset); 2154 DUMP_FIELD_COPY (&out, node, offset);
2155 DUMP_FIELD_COPY (&out, node, otick); 2155 DUMP_FIELD_COPY (&out, node, otick);
2156 dump_field_lv (ctx, &out, node, &node->data, WEIGHT_STRONG); 2156 dump_field_lv (ctx, &out, node, &node->data, WEIGHT_STRONG);
2157 DUMP_FIELD_COPY (&out, node, color); 2157 DUMP_FIELD_COPY (&out, node, red);
2158 DUMP_FIELD_COPY (&out, node, visited); 2158 DUMP_FIELD_COPY (&out, node, visited);
2159 DUMP_FIELD_COPY (&out, node, rear_advance); 2159 DUMP_FIELD_COPY (&out, node, rear_advance);
2160 DUMP_FIELD_COPY (&out, node, front_advance); 2160 DUMP_FIELD_COPY (&out, node, front_advance);