#-------------------------------------------------------------------------------
# elftools: dwarf/compileunit.py
#
# DWARF compile unit
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
from .die import DIE


class CompileUnit(object):
    """ A DWARF compilation unit (CU). 
    
            A normal compilation unit typically represents the text and data
            contributed to an executable by a single relocatable object file.
            It may be derived from several source files, 
            including pre-processed "include files"
            
        Serves as a container and context to DIEs that describe objects and code
        belonging to a compilation unit.
        
        CU header entries can be accessed as dict keys from this object, i.e.
           cu = CompileUnit(...)
           cu['version']  # version field of the CU header
        
        To get the top-level DIE describing the compilation unit, call the 
        get_top_DIE method.
    """
    def __init__(self, header, dwarfinfo, structs, cu_offset, cu_die_offset):
        """ header:
                CU header for this compile unit
            
            dwarfinfo:
                The DWARFInfo context object which created this one
                        
            structs:
                A DWARFStructs instance suitable for this compile unit
            
            cu_offset:
                Offset in the stream to the beginning of this CU (its header)
            
            cu_die_offset:
                Offset in the stream of the top DIE of this CU
        """
        self.dwarfinfo = dwarfinfo
        self.header = header
        self.structs = structs
        self.cu_offset = cu_offset
        self.cu_die_offset = cu_die_offset
        
        # The abbreviation table for this CU. Filled lazily when DIEs are 
        # requested.
        self._abbrev_table = None
        
        # A list of DIEs belonging to this CU. Lazily parsed.
        self._dielist = []
    
    def dwarf_format(self):
        """ Get the DWARF format (32 or 64) for this CU
        """
        return self.structs.dwarf_format
    
    def get_abbrev_table(self):
        """ Get the abbreviation table (AbbrevTable object) for this CU
        """
        if self._abbrev_table is None:
            self._abbrev_table = self.dwarfinfo.get_abbrev_table(
                self['debug_abbrev_offset'])
        return self._abbrev_table

    def get_top_DIE(self):
        """ Get the top DIE (which is either a DW_TAG_compile_unit or 
            DW_TAG_partial_unit) of this CU
        """
        return self._get_DIE(0)
    
    def iter_DIEs(self):
        """ Iterate over all the DIEs in the CU, in order of their appearance.
            Note that null DIEs will also be returned.
        """
        self._parse_DIEs()
        return iter(self._dielist)
    
    #------ PRIVATE ------#
    
    def __getitem__(self, name):
        """ Implement dict-like access to header entries
        """
        return self.header[name]

    def _get_DIE(self, index):
        """ Get the DIE at the given index 
        """
        self._parse_DIEs()
        return self._dielist[index]
    
    def _parse_DIEs(self):
        """ Parse all the DIEs pertaining to this CU from the stream and shove
            them sequentially into self._dielist.
            Also set the child/sibling/parent links in the DIEs according
            (unflattening the prefix-order of the DIE tree).
        """
        if len(self._dielist) > 0:
            return
            
        # Compute the boundary (one byte past the bounds) of this CU in the 
        # stream
        cu_boundary = ( self.cu_offset + 
                        self['unit_length'] + 
                        self.structs.initial_length_field_size())
        
        # First pass: parse all DIEs and place them into self._dielist
        die_offset = self.cu_die_offset
        while die_offset < cu_boundary:
            die = DIE(
                    cu=self,
                    stream=self.dwarfinfo.debug_info_sec.stream,
                    offset=die_offset)
            self._dielist.append(die)
            die_offset += die.size

        # Second pass - unflatten the DIE tree
        self._unflatten_tree()
    
    def _unflatten_tree(self):
        """ "Unflatten" the DIE tree from it serial representation, by setting
            the child/sibling/parent links of DIEs.
            
            Assumes self._dielist was already populated by a linear list of DIEs
            read from the stream section
        """
        # the first DIE in the list is the root node
        root = self._dielist[0]
        parentstack = [root]
        
        for die in self._dielist[1:]:
            if not die.is_null():
                cur_parent = parentstack[-1]
                # This DIE is a child of the current parent
                cur_parent.add_child(die)
                die.set_parent(cur_parent)
                if die.has_children:
                    parentstack.append(die)
            else:
                # end of children for the current parent
                parentstack.pop()

