code: def _next_unscanned_addr(self, alignment=None):
          
  
          # TODO: Take care of those functions that are already generated
          if self._next_addr is None:
              self._next_addr = self._get_min_addr()
              curr_addr = self._next_addr
          else:
              curr_addr = self._next_addr + 1
  
          if not self._inside_regions(curr_addr):
              curr_addr = self._next_address_in_regions(curr_addr)
  
          if curr_addr is None:
              l.debug("All addresses within memory regions have been scanned.")
              return None
  
          if self._seg_list.has_blocks:
              curr_addr = self._seg_list.next_free_pos(curr_addr)
  
          if alignment is not None:
              if curr_addr % alignment > 0:
                  curr_addr = curr_addr - (curr_addr % alignment) + alignment
  
          # Make sure curr_addr exists in binary
          accepted = False
          for start, end in self._regions.items():
              if start <= curr_addr < end:
                  # accept
                  accepted = True
                  break
              if curr_addr < start:
                  # accept, but we are skipping the gap
                  accepted = True
                  curr_addr = start
                  break
  
          if not accepted:
              # No memory available!
              return None
  
          self._next_addr = curr_addr
          if self._inside_regions(curr_addr):
              l.debug("Returning a new recon address: %#x", curr_addr)
              return curr_addr
  
          l.debug("%#x is beyond the ending point. Returning None.", curr_addr)
          return None
docs: Find the next address that we haven't processed
  
          :param alignment: Assures the address returns must be aligned by this number
          :return: An address to process next, or None if all addresses have been processed