docs: def expand_entries(entries, ignore_xs=None):
      """Turn all Xs which are not ignored in all entries into ``0`` s and
      ``1`` s.
  
      For example::
  
          >>> from rig.routing_table import RoutingTableEntry
          >>> entries = [
          ...     RoutingTableEntry(set(), 0b0100, 0xfffffff0 | 0b1100),  # 01XX
          ...     RoutingTableEntry(set(), 0b0010, 0xfffffff0 | 0b0010),  # XX1X
          ... ]
          >>> list(expand_entries(entries)) == [
          ...     RoutingTableEntry(set(), 0b0100, 0xfffffff0 | 0b1110),  # 010X
          ...     RoutingTableEntry(set(), 0b0110, 0xfffffff0 | 0b1110),  # 011X
          ...     RoutingTableEntry(set(), 0b0010, 0xfffffff0 | 0b1110),  # 001X
          ...     RoutingTableEntry(set(), 0b1010, 0xfffffff0 | 0b1110),  # 101X
          ...     RoutingTableEntry(set(), 0b1110, 0xfffffff0 | 0b1110),  # 111X
          ... ]
          True
  
      Note that the ``X`` in the LSB was retained because it is common to all
      entries.
  
      Any duplicated entries will be removed (in this case the first and second
      entries will both match ``0000``, so when the second entry is expanded only
      one entry is retained)::
  
          >>> from rig.routing_table import Routes
          >>> entries = [
          ...     RoutingTableEntry({Routes.north}, 0b0000, 0b1111),  # 0000 -> N
          ...     RoutingTableEntry({Routes.south}, 0b0000, 0b1011),  # 0X00 -> S
          ... ]
          >>> list(expand_entries(entries)) == [
          ...     RoutingTableEntry({Routes.north}, 0b0000, 0b1111),  # 0000 -> N
          ...     RoutingTableEntry({Routes.south}, 0b0100, 0b1111),  # 0100 -> S
          ... ]
          True
  
      .. warning::
  
          It is assumed that the input routing table is orthogonal (i.e., there
          are no two entries which would match the same key). If this is not the
          case, any entries which are covered (i.e. unreachable) in the input
          table will be omitted and a warning produced. As a result, all output
          routing tables are guaranteed to be orthogonal.
  
      Parameters
      ----------
      entries : [:py:class:`~rig.routing_table.RoutingTableEntry`...] or similar
          The entries to expand.
  
      Other Parameters
      ----------------
      ignore_xs : int
          Mask of bits in which Xs should not be expanded. If None (the default)
          then Xs which are common to all entries will not be expanded.
  
      Yields
      ------
      :py:class:`~rig.routing_table.RoutingTableEntry`
          Routing table entries which represent the original entries but with all
          Xs not masked off by `ignore_xs` replaced with 1s and 0s.
      """
      # Find the common Xs for the entries
      if ignore_xs is None:
          ignore_xs = get_common_xs(entries)
  
      # Keep a track of keys that we've seen
      seen_keys = set({})
  
      # Expand each entry in turn
      for entry in entries:
          for new_entry in expand_entry(entry, ignore_xs):
              if new_entry.key in seen_keys:
                  # We've already used this key, warn that the table is
                  # over-complete.
                  warnings.warn("Table is not orthogonal: Key {:#010x} matches "
                                "multiple entries.".format(new_entry.key))
              else:
                  # Mark the key as seen and yield the new entry
                  seen_keys.add(new_entry.key)
                  yield new_entry