def contains_index(self):
        """Returns the *line number* that has the CONTAINS keyword separating the
        member and type definitions from the subroutines and functions."""
        if self._contains_index is None:
            max_t = 0
            for tkey in self.types:
                if self.types[tkey].end > max_t and not self.types[tkey].embedded:
                    max_t = self.types[tkey].end

            #Now we have a good first guess. Continue to iterate the next few lines
            #of the the refstring until we find a solid "CONTAINS" keyword. If there
            #are no types in the module, then max_t will be zero and we don't have
            #the danger of running into a contains keyword as part of a type. In that
            #case we can just keep going until we find it.
            i = 0
            start = self.linenum(max_t)[0]
            max_i = 10 if max_t > 0 else len(self._lines)

            while (self._contains_index is None and i < max_i
                   and start + i < len(self._lines)):
                iline = self._lines[start + i].lower()
                if "contains" in iline:
                    if '!' not in iline or (iline.index('!') > iline.index("contains")):
                        self._contains_index = start + i
                i += 1

            if self._contains_index is None:
                #There must not be a CONTAINS keyword in the module
                self._contains_index = len(self._lines)-1

        return self._contains_index