class RDoc::Parser::ChangeLog

def parse_entries

def parse_entries
  @time_cache ||= {}
  entries = []
  entry_name = nil
  entry_body = []
  @content.each_line do |line|
    case line
    when /^\s*$/ then
      next
    when /^\w.*/ then
      entries << [entry_name, entry_body] if entry_name
      entry_name = $&
      begin
        time = Time.parse entry_name
        @time_cache[entry_name] = time
        # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other"
        entry_name = nil unless entry_name =~ /#{time.year}/
      rescue NoMethodError
        # HACK Ruby 2.1.2 and earlier raises NoMethodError if time part is absent
        entry_name.split '  ', 2
      rescue ArgumentError
        if /out of range/ =~ $!.message
          Time.parse(entry_name.split('  ', 2)[0]) rescue entry_name = nil
        else
          entry_name = nil
        end
      end
      entry_body = []
    when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..."
      entry_body << $2.dup
    when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..."
      entry = $2
      if entry_body.last =~ /:/ then
        entry_body << entry.dup
      else
        continue_entry_body entry_body, entry
      end
    when /^(\t| {8})?\s*(.*)/ then
      continue_entry_body entry_body, $2
    end
  end
  entries << [entry_name, entry_body] if entry_name
  entries.reject! do |(entry,_)|
    entry == nil
  end
  entries
end