/* Find the splay tree node for the definition of NAME at LINE in SOURCE, or zero if there is none. */ static splay_tree_node find_definition (const char *name, struct macro_source_file *file, int line) { struct macro_table *t = file->table; splay_tree_node n; /* Construct a macro_key object, just for the query. */ struct macro_key query; query.name = name; query.start_file = file; query.start_line = line; query.end_file = NULL; n = splay_tree_lookup (t->definitions, (splay_tree_key) &query); if (! n) { /* It's okay for us to do two queries like this: the real work of the searching is done when we splay, and splaying the tree a second time at the same key is a constant time operation. If this still bugs you, you could always just extend the splay tree library with a predecessor-or-equal operation, and use that. */ splay_tree_node pred = splay_tree_predecessor (t->definitions, (splay_tree_key) &query); if (pred) { /* Make sure this predecessor actually has the right name. We just want to search within a given name's definitions. */ struct macro_key *found = (struct macro_key *) pred->key; if (strcmp (found->name, name) == 0) n = pred; } } if (n) { struct macro_key *found = (struct macro_key *) n->key; /* Okay, so this definition has the right name, and its scope begins before the given source location. But does its scope end after the given source location? */ if (compare_locations (file, line, found->end_file, found->end_line) < 0) return n; else return 0; } else return 0; }
/* Compare a macro key KEY against NAME, the source file FILE, and line number LINE. Sort definitions by name; for two definitions with the same name, place the one whose definition comes earlier before the one whose definition comes later. Return -1, 0, or 1 if key comes before, is identical to, or comes after NAME, FILE, and LINE. */ static int key_compare (struct macro_key *key, const char *name, struct macro_source_file *file, int line) { int names = strcmp (key->name, name); if (names) return names; return compare_locations (key->start_file, key->start_line, file, line); }
static int foreach_macro_in_scope (splay_tree_node node, void *info) { struct macro_for_each_data *datum = (struct macro_for_each_data *) info; struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def; char *datum_fullname; datum_fullname = macro_source_fullname (datum->file); def = fixup_definition (datum_fullname, datum->line, (struct macro_definition *) node->value); xfree (datum_fullname); /* See if this macro is defined before the passed-in line, and extends past that line. */ if (compare_locations (key->start_file, key->start_line, datum->file, datum->line) < 0 && (!key->end_file || compare_locations (key->end_file, key->end_line, datum->file, datum->line) >= 0)) datum->fn (key->name, def, key->start_file, key->start_line); return 0; }
int TextPointer::CompareToWithError (const TextPointer *pointer, MoonError *error) const { if (!verify_textpointer_in_document (this, error) || !verify_textpointer_in_document (pointer, error)) return -1; if (this->GetParent() == pointer->GetParent()) { DependencyObjectCollection *children = this->GetParentNode()->GetDocumentChildren(); if (children && children->GetCount() > 0) return compare_locations (this->GetLocation(), pointer->GetLocation()); else return this->ResolveLocation() - pointer->ResolveLocation(); } else { GPtrArray *this_array = g_ptr_array_new(); GPtrArray *pointer_array = g_ptr_array_new(); DependencyObject *el = GetParent(); while (el) { g_ptr_array_insert (this_array, 0, el); if (el->Is (Type::RICHTEXTBOX)) break; el = el->GetParent() ? el->GetParent()->GetParent() : NULL; if (!el) break; } el = pointer->GetParent(); while (el) { g_ptr_array_insert (pointer_array, 0, el); if (el->Is (Type::RICHTEXTBOX)) break; el = el->GetParent() ? el->GetParent()->GetParent() : NULL; if (!el) break; } guint32 count_to_compare = MIN (this_array->len, pointer_array->len); for (guint32 i = 0; i < count_to_compare; i ++) { DependencyObject *this_el = (DependencyObject*)g_ptr_array_index (this_array, i); DependencyObject *pointer_el = (DependencyObject*)g_ptr_array_index (pointer_array, i); if (this_el == pointer_el) continue; if (i == 0) { // this shouldn't happen... there shouldn't be a difference between two paths on the first element, since that should always be a RTB int rv = this_array->len < pointer_array->len ? -1 : 1; g_ptr_array_free (this_array, TRUE); g_ptr_array_free (pointer_array, TRUE); return rv; } /* at this point this_el and pointer_el are different. check index i-1's idea of their positions */ DependencyObject *common_parent = (DependencyObject*)g_ptr_array_index (this_array, i-1); IDocumentNode *common_parent_node = IDocumentNode::CastToIDocumentNode (common_parent); int this_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (this_el)); int pointer_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (pointer_el)); g_ptr_array_free (this_array, TRUE); g_ptr_array_free (pointer_array, TRUE); return this_index < pointer_index ? -1 : 1; } // if we make it here, it means we've run through // "count_to_compare" items that were identical, and // one of the paths is longer (so represents a child // of items[count_to_compare]. // so we need to figure out which array has more // elements, then compare that against the other // TextPointer's location if (count_to_compare < this_array->len) { // @this's parent is a child of pointer_array[count_to_compare-1] DependencyObject *parent = (DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare - 1); IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent); guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(this_array, count_to_compare))); return pointer->GetLocation() > child_index ? -1 : 1; } else if (count_to_compare < pointer_array->len) { // @pointer's parent is a child of this_array[count_to_compare-1] DependencyObject *parent = (DependencyObject*)g_ptr_array_index(this_array, count_to_compare - 1); IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent); guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare))); return child_index >= this->GetLocation () ? -1 : 1; } } return -1; }